根据给定数据的类型执行不同的任务。

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

我试图创建一个游戏,其中有一个武器系统,会有近战、火器等武器类型。我创建了数据类,然后我将在另一个类中引用这些数据类,并相应地执行任务(开火、重装等)。

public abstract class WeaponData {
      public int damage;

      public abstract void Fire();
}

请注意,抽象的是,我把这个类作为一个基础,用于每个武器都会有的普通东西。然后,我们将为每种类型的武器都有继承上面这个类的类。

public class FirearmData : WeaponData {
     public SupplyData ammoTypeData;
     public int magazineSize;
     public AnimationClip reloadAnimation;

     public override void Fire() {
           // blablabla...
     }
}

这个类覆盖了Fire()方法,并且有一些其他不同的领域。这是另一个武器类型的类。

public class MeleeWeaponData : WeaponData {
     public AnimationClip swingAnimation;

     public override void Fire() {
           // blablabla...
     }
}

到目前为止,我成功地创建了这些类,但这并不意味着我以后不会再创建更多类似于这两个类的类,我在这里不提了,因为我发现这个系统是行不通的... ...

所以我也有一个Weapon类,我会引用一个WeaponData,它的方法会根据数据做不同的任务。

public class Weapon {
     public WeaponData data;

     void Fire() {
         data.Fire();
     }

     void Reload() {
        // the problem is here;
     }
}

所以问题就出在这里,我在这个类中包含了所有数据可能需要的方法,但如果你问我,这并不优雅,因为WeaponData将是MeleeWeaponData,在这种情况下,它不需要Reload()方法,也不需要一个整数弹匣字段。我仍然可以让它工作,通过做一些开关的东西来检查数据的类型。但是每当我碰巧创建更多的数据类型时,我就必须在这里每次都要在开关中多加一条语句。而我不希望这样。

所以我想咨询一下通用的这个问题,比如说。

public class Weapon<T> where T : WeaponData {

}

但这也不能让我获得WeaponData子类的字段,就像你告诉我的那样... ...

你们能想出一个适合我的系统吗?我正在Unity上制作游戏,如果这意味着什么的话,我确实使用ScriptableObjects来制作数据。

c# unity3d generics constraints
2个回答
0
投票

一个简单的解决方案是这样的。

public abstract class WeaponData
{
    public int damage;

    public abstract void Fire();

    public virtual void Reload()
    {
        return;
    }
}

然后在需要的地方覆盖Reload()。

public class FirearmData : WeaponData {
     public SupplyData ammoTypeData;
     public int magazineSize;
     public AnimationClip reloadAnimation;

     public override void Fire() {
           // blablabla...
     }

     public override void Reload() {
           // blablabla...
     }
}

不需要的地方就忽略它:

public class MeleeWeaponData : WeaponData {
     public AnimationClip swingAnimation;

     public override void Fire() {
           // blablabla...
     }
}

0
投票

我建议你用接口来代替: IFireable, IReloadable, 例如:

interface IWeapon
{
    void Fire();
}

interface IReloadable
{
    void Reload();
}

实现你的WeaponData ase

class WeaponData: IWeapon
{
    public int damage;
    public abstract Fire();
}

对于火器,派生自WeaponData,并实现IReloadable。

public class FirearmData : WeaponData, IReloadable
{
     public SupplyData ammoTypeData;
     public int magazineSize;
     public AnimationClip reloadAnimation;

     public override void Fire() 
     {
           // blablabla...
     }
     public void Reload() 
     {
           // Reload
     }
}

Fire MaleeData,只派生自WeaponData。

这样,在你的Weapon类中,检查武器的类型,如果它支持IReloadable,就进行重装,否则,什么都不做。

public class Weapon {
     public WeaponData data;

     void Fire() {
         data.Fire();
     }

     void Reload() {
        if(data is IReloadable reloadableData)
        {
             reloadableData.Reload();
        }
        else
            // Do nothing.
     }
}


© www.soinside.com 2019 - 2024. All rights reserved.