Тип данных, который может представлять несколько различных классов с некоторыми общими свойствами без наследования - PullRequest
0 голосов
/ 06 февраля 2019

Я работаю с c # в единстве.У меня есть класс с именем CarPart, который происходит от MonoBehaviour (MB является базовым классом для каждого скрипта Unity).В этом классе я объявил конкретные классы автомобильных деталей, которые не могут быть производными от какого-либо базового класса, потому что инспектор единства не будет показывать их свойства, но они требуют моно поведения, поэтому я объявил их в классе (CarPart), который происходит от MonoBehaviour.

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
}

Тогда у меня есть класс VehicleConfig, который является компонентом игрового объекта менеджера (этот GO активен в течение всей игры).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]);
    }
} 

Моя проблема в том, что у меня есть гораздо более конкретные автомобильные компонентычем просто Engine и Chassis, и все они имеют гораздо более распространенные методы с конкретной реализацией, чем просто Equip ().Также Setup () немного сложнее, чем в примере выше.Поэтому я хочу, чтобы Setup () был перегружен некоторым типом данных, который может представлять все общие методы и свойства всех автомобильных деталей (Двигатель, Ходовая часть ...), чтобы я мог перегрузить Setup (), например, с двигателями [0], преобразованными вэтот особый тип данных.Я знаю, что существует другой подход для реализации этой функциональности с помощью абстрактного класса со всеми распространенными абстрактными методами, из которых будут производные классы, такие как Engine или Chassis, и обеспечит определенную реализацию для этих методов, но, как я упоминал ранее, инспектор единства не может показатьпеременные-члены производных классов.Если у кого-то есть совет, идея или совершенно другой подход.Я был бы очень признателен, упомянув об этом :) спасибо заранее.

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Я не совсем уверен, какая у вас проблема с абстрактными классами, но вы можете использовать абстрактные классы для достижения желаемого и иметь свойства, доступные в инспекторе:

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]);
    }
}

enter image description here

0 голосов
/ 06 февраля 2019

Вы можете хранить общие данные в отдельном объекте.Я бы предложил CarBase

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

Затем создайте интерфейс, который вы должны реализовать для своего метода.Я предлагаю ICarEquip

public interface ICarEquip
{
    public void Equip();
}

Теперь для любой части автомобиля, которую вы хотите создать, извлеките ее из MonoBehaviour Unity и вашей собственной 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()
    {

    }
}

.Вы не сможете обойти тот факт, что классы деталей вашего автомобиля отличаются друг от друга, но вы получите большую пользу от принципа СУХОЙ (не повторяйте себя).

Ваш класс VehicleConfig должен будет изменить то, какон получает доступ и применяет эти компоненты.Я бы не стал реализовывать CarBase, так как это не тип CarBase.Ваш VehicleConfig получит больше паттерна Mediator .Он будет взаимодействовать с различными частями автомобиля по-своему.

...