可以表示多个不同 类 且具有一些共同属性的数据类型,无需继承

Data type which can represent multiple different classes with some common properties without inheritance

我正在统一使用 c#。我有 class 调用 CarPart,它派生自 MonoBehaviour(M.B。是每个统一脚本的基础 class)。在此 class 中,我声明了特定的汽车部件 classes 不能从任何基础派生 class 因为 unity inspector 不会显示它们的属性,但它们需要单声道行为所以我声明它们在确实派生自 MonoBehaviour 的 class (CarPart) 中。

public class CarPart : MonoBehaviour {

    [System.Serializable] //required to show full objects in inspector
    public class Chassis {
        //common properties for all car parts
        public GameObject prefab;
        public int price;
        //specific properties for every car part
        public bool AWD;
        public int suspensionDepth;
        //specific implementation of equip for chassis
        public void equip() {
            //instantiate chassis as root object 
        }
    }
    [System.Serializable] //required to show full objects in inspector
    public class Engine {
        //common properties for all car parts
        public GameObject prefab;
        public int price;
        //specific properties for every car part
        public bool supportsAddOnExhaust;
        public int power;
        //specific implementation of Equip for engine
        public void Equip() {
            //instantiate engine as child object of chassis in hierarchy 
        }
    }
    //this code is heavily simplified
}

然后我有 class VehicleConfig,它是管理器游戏对象的组件(这个 G.O。在整个游戏期间处于活动状态)。 VehicleConfig 与 GUI 通信,并根据 GUI 输入配置车辆。它还声明了所有汽车部件,这些部件稍后将分配给检查器(功率、悬架深度)和 3D 模型(预制件)的特定值。

public class VehicleConfig : CarPart{
    public Chassis[] chassis; //assigned from inspector
    public Engine[] engines;  //assigned from inspector    
    //and more car components like these two...
    //arrays because there will be multiple to chose from each type        

    public void Setup (unknownDataType component) {
        component.Equip;
        DoSomethingWithCommonVariables(component.price, component.prefab);
    }
    //method called from GUI example:
    public void MountFirstEngine() {
        Setup(engines[0]);
    }
} 

我的问题是,我有更多的特定汽车组件,而不仅仅是引擎和底盘,而且所有这些组件都有更多具有特定实现的常用方法,而不仅仅是 Equip()。 Setup() 也比上面的例子复杂一点。所以我希望 Setup() 被一些数据类型重载,这些数据类型可以代表所有汽车部件(引擎、底盘...)的所有常用方法和属性,这样我就可以重载 Setup(),例如 Engines[0] 转换为那种特殊的数据类型。我知道有不同的方法可以使用抽象 class 实现此功能,所有常见的抽象方法都是 classes 像 Engine 或 Chassis 派生的,并且会为这些方法提供某些实现,但正如我提到的早些时候,unity inspector 无法显示派生的 classes 的成员变量。如果有人有建议、想法或完全不同的方法。提前提一下我真的很感激 :) 谢谢。

您可以将公共数据存储在单独的对象中。我建议 CarBase

public class CarBase
{
    public GameObject prefab;
    public int price;
}

然后,创建一个必须为您的方法实现的接口。我建议 ICarEquip

public interface ICarEquip
{
    public void Equip();
}

现在,对于您想要创建的任何汽车部件,从 Unity 的 MonoBehaviour 和您自己的 ICarEquip

派生它
public class Engine : MonoBehaviour, ICarEquip
{
    // Attach your CarBase information
    [System.Serializable]
    CarBase carBase;

    // Specific properties
    public bool doesSupportAddonExhaust;
    public int power;

    // Implement your interface methods
    public void Equip()
    {

    }
}

您不会回避您的汽车零件 class 彼此不同的事实,但您将从 DRY(不要重复自己)原则中受益匪浅。

您的 VehicleConfig class 将不得不更改它访问和应用这些组件的方式。我不会让它实现 CarBase,因为它不是 CarBase 的一种。您的 VehicleConfig 将承担更多 Mediator Pattern。它将以自己的方式与不同的汽车部件互动。

我不太确定你对抽象 类 有什么问题,但你可以使用抽象 类 来实现你想要的并在检查器中提供可用的属性:

public abstract class CarElement
{
  //common properties for all car parts
  public GameObject prefab;
  public int price;
  public abstract void Equip();
}

[System.Serializable] //required to show full objects in inspector
public class Chassis : CarElement
{
    //specific properties for every car part
    public bool AWD;
    public int suspensionDepth;
    public override void Equip() { }
}

[System.Serializable] //required to show full objects in inspector
public class Engine : CarElement
{
    //specific properties for every car part
    public bool supportsAddOnExhaust;
    public int power;
    public override void Equip(){ }
}

public class VehicleConfig : CarPart
{
    public Chassis[] chassis; //assigned from inspector
    public Engine[] engines;  //assigned from inspector    
    //and more car components like these two...
    //arrays because there will be multiple to chose from each type        

    public void Setup(CarElement component)
    {
          component.Equip();
          DoSomethingWithCommonVariables(component.price, component.prefab);
    }
    //method called from GUI example:
    public void MountFirstEngine()
    {
        Setup(engines[0]);
    }
}