用继承类作为参数进行覆盖

问题描述 投票:1回答:2

我正在为我的2D游戏制作一个模块化的武器系统,我被下面的问题卡住了。

假设我有一个抽象的基类,名为 Weapon

public abstract class Weapon : MonoBehaviour
{
    public int damage { get; set; }
    public int durablity { get; set; }
    public Sprite sprite { get; set; }

    public abstract void Initialize(WeaponData weaponData);
}

和a Pistol 继承自 Weapon

public class Pistol : Weapon {
    PistolData pistolData;

    void Start() {
        Initialize(pistolData);
    }

    public override void Initialize(PistolData pistolData) {
       //do something
    }
}

像你可以看到这两个类在Initialize MethodFunction中使用了以下两个类。A WeaponData 类。

public abstract class WeaponData : ScriptableObject
{
    public int durability;
    public int damage;
}

和a PistolData 继承自 WeaponData

[CreateAssetMenu(fileName = "new PistolData", menuName = "MyAssets/PistolData", order = 0)]
public class PistolData : WeaponData
{
    public Vector2 pivotPoint;
    public Vector2 firePoint;
    public GameObject bulletPrefab;
    public float bulletForce;
    public Sprite weaponSprite;
    public float fireRate;
}

我的问题:我得到一个错误,因为Initialize需要一个 WeaponData 而非 PistolData. 我认为这将工作,因为 PistolData 实际上是 WeaponData 通过继承... 至少我是这么认为的。

有什么方法可以让这种继承成为可能吗?如果没有,我应该如何解决呢?

Im very new to Unity and C# and I have no Idea left how I could Manage my Weapon System if not like this.

c# unity3d inheritance
2个回答
1
投票

使用泛型和泛型约束应该可以得到你所需要的东西。

public abstract class Weapon<TWeaponData> : MonoBehaviour
    where TWeaponData : WeaponData
{
    public int damage { get; set; }
    public int durablity { get; set; }
    public Sprite sprite { get; set; }

    public abstract void Initialize(TWeaponData weaponData);
}

那你的手枪班可以这样做

public class Pistol : Weapon<PistolData>
{
    PistolData pistolData;

    void Start() {
        Initialize(pistolData);
    }

    public override void Initialize(PistolData pistolData) {
       //do something
    }
}

2
投票

你可以让这个方法不需要参数,只需使用字段

public override void Initialize()
{
    // do something with pistolData since you seem to have it as field
}

你也可以添加一个类型检查,比如

public class Pistol : Weapon 
{
    [SerializeField] PistolData _pistolData;

    void Start() 
    {
        Initialize(pistolData);
    }

    public override void Initialize(WeaponData weaponData)
    {
        if (!(weaponData is PistolData pistolData))
        {
            Debug.LogError("I expected a " + nameof(PistolData), this);
            return;
        }

        // use pistolData
    }
}

或者您可以在 Weapon 武器应该做什么,并在你的继承中使用非覆盖方法。

public abstract class Weapon : MonoBehaviour
{
    public int damage { get; private set; }
    public int durablity { get; private set; }
    public Sprite sprite { get; set; }

    protected void Initialize(WeaponData weaponData)
    {
        damage = weapondData.damage;
        durability = weaponData.durability
    }
}

然后

public class Pistol : Weapon
{
    public void Initialize(PistolData pistolData)
    {
        base.Initialize(pistolData);

        // do pistol specific stuff
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.