【发布时间】:2022-01-17 22:56:50
【问题描述】:
我正在尝试通过使用接口升级特定的大炮,我面临的问题是由于某种原因,函数被正确调用并且没有错误,但实际上参数没有“升级”为预计。
BaseWeapon.cs
public class BaseWeapon : MonoBehaviour
{
public new string name;
public int level = 1;
public int damage;
public int cost;
private BaseEnemy target;
public IDoDamage damageType;
public IDoUpgrade upgradeType;
public int TryDoDamage(BaseEnemy target, int damage)
{
this.target = target;
int dmg = (int)damageType?.DoDamage(target, damage);
target.UpdateHealth();
return dmg;
}
public void TryDoUpgrade(BaseCannon cannon)
{
Debug.Log("Inside TryDoUpgrade SUCCESS"); // This debug works
upgradeType?.DoUpgrade(cannon);
Island.Instance.Spend(cannon.cost);
}
上述调试有效,按预期从播放器中减去金币。
DefCannon.cs我用它来实例化一个BaseCannon,它继承自BaseWeapon,带有自定义参数,这是默认的cannon,我也有一个FireCannon作为例子,它们都继承自BaseCannon , 而后者又继承自 BaseWeapon.:
public class DefCannon : BaseCannon
{
public void Init(int level)
{
name = "Defcannon";
this.level = level;
cannonMat = Cannonballs.cbCannonMat["Default"];
damage = 50 * level;
ballMat = Cannonballs.cbMat["Default"];
cbSpeed = Cannonballs.cbSpeed["Default"];
minPrecision = 0.91f;
maxPrecision = 1.11f;
minReload = 0.5f;
maxReload = 1.0f;
damageType = new DefDamage(level);
upgradeType = new DefUpgrade(this, level);
}
}
我认为问题也可能在这里upgradeType = new DefUpgrade(this, level);
this = DefCannon.cs // which inherits from BaseCannon
但是DefUpgrade(BaseCannon baseCannon, int level) DefUpgrade 要求BaseCannon,而不是我们给它一个BaseCannon 的孩子,在这种情况下是DefCannon,这可能是它不起作用的原因吗?我将如何解决这个问题,我没有从子脚本中引用BaseCannon 脚本,有没有办法做到this.BaseCannon,(以某种方式调用父类?)
澄清一下,上面的脚本只用于设置参数,我有一个prefabCannon,没有脚本,当我实例化那个prefabCannon时,我添加脚本DefCannon或FireCannon,这取决于我想要哪个cannon实例化,这样我可以让他们都使用他们都需要的通用函数,但每个人都有自定义参数等。
DefUpgrade.cs 这是问题所在,BaseWeapon 脚本中的Debug.Log 有效,但是当它进入DefUpgrade.cs 并尝试调用DoUpgrade() 时,下一步它会失败,因为有Debug.Log在那个脚本中永远不会被调用:
public class DefUpgrade : IDoUpgrade
{
public int level;
public DefUpgrade(BaseCannon baseCannon, int level)
{
this.level = level;
baseCannon.cost = DefUpgradeDictionary.cost[level];
}
public void DoUpgrade(BaseCannon baseCannon)
{
Debug.Log("Inside DoUpgrade SUCCESS"); // This debug is never reached/called
var baseDamage = baseCannon.damage / baseCannon.level;
baseCannon.level++;
baseCannon.damage = baseDamage * level;
var lvl = baseCannon.level;
baseCannon.damageType = new DefDamage(lvl); //CHECK IF IT WORKS
baseCannon.minPrecision = DefUpgradeDictionary.minPrecision[lvl];
baseCannon.maxPrecision = DefUpgradeDictionary.maxPrecision[lvl];
baseCannon.minReload = DefUpgradeDictionary.minReload[lvl];
baseCannon.maxReload = DefUpgradeDictionary.maxReload[lvl];
baseCannon.cost = DefUpgradeDictionary.cost[lvl];
}
}
我使用完全相同的界面结构来造成伤害,因为所有大炮都需要造成伤害,但再次使用不同的参数,在那个结构中我没有问题,但是当我为升级重新创建它时,它似乎不起作用但是什么让这变得如此令人困惑的是,没有控制台错误,没有丢失的引用,它调试函数 A,然后调用函数 B,但函数 B 中的调试永远不会被调用!
IDoUpgrade.cs 接口
public interface IDoUpgrade
{
void DoUpgrade(BaseCannon cannon);
}
致电TryDoUpgrade()
baseCannon = PlayerRays.Instance.baseCannon;
if (PlayerRays.Instance.safe && Island.Instance.gold >= baseCannon.cost)
{
PlayerRays.Instance.baseWeapon.TryDoUpgrade(baseCannon);
}
这最后 2 个脚本工作正常,问题似乎不存在。
感谢您对此进行调查,非常感谢,因为我已经尝试了将近 2 天了。
更新 1:添加 BaseCannon.cs:
public class BaseCannon : BaseWeapon
{
private Transform cannon, cylinder, spawn, closestEnemy;
private MeshRenderer mesh;
private GameObject flame;
private List<Transform> enemyShips;
public Material cannonMat, ballMat;
public float cbSpeed;
private float aliveTime = 15f;
public float minPrecision, maxPrecision, minReload, maxReload;
void Start()
{
cannon = transform.Find("Cannon");
cylinder = cannon.transform.Find("Cylinder");
spawn = cylinder.transform.Find("Spawn");
flame = spawn.transform.Find("Flame").gameObject;
flame.SetActive(false);
mesh = cannon.GetComponent<MeshRenderer>();
mesh.material = cannonMat;
}
}
【问题讨论】:
-
我猜我们错过了
BaseCannon的代码 ... -
instead we give it a child of BaseCannon.. 它不是“孩子”,您的DefCannon是BaseCannon只是带有一些额外的字段/方法等.. 除非它 隐藏一个成员(有一个与基类同名但不使用override)应该没有理由让它表现不同 -
感谢您的快速回复 DerHugo.DefCannon 不隐藏任何内容,仅初始化值,但我按照您的要求添加了 BaseCannon 脚本 :)
-
我真正需要弄清楚的是为什么 BaseWeapon 中的
upgradeType?.DoUpgrade(cannon);被调用,但随后从未被执行,也不会在控制台中抛出任何空引用异常。 -
好吧
upgradeType?.DoUpgrade(cannon);基本上是if(upgradeType != null) upgradeType.DoUpgrade(cannon);的简写,所以它的全部目的是防止NullReferenceException但如果upgradeType是null则不会做任何事情...你确定DefCannon.Init被调用了吗?
标签: c# unity3d inheritance interface