Является ли использование основного сценария обработки меньших сценариев нарушением SRP / высокой сплоченности в Unity? - PullRequest
0 голосов
/ 24 декабря 2018

Я создал несколько небольших скриптов, чтобы следовать модульному шаблону в Unity.Однако для этих сценариев может потребоваться информация из других сценариев.Я делаю это, чтобы я мог повторно использовать сценарии в качестве компонентов для других объектов.Создание «основного» сценария, объединяющего эти сценарии, является плохой практикой или нарушением SRP?Есть ли лучший способ приблизиться к этому, что я должен рассмотреть?Может быть, события?

Допустим, у меня есть враг, и когда этот враг умирает, он бросает добычу и дает некоторый опыт.Я создал скрипт для опыта, добычи, смерти и здоровья.Каждый будет выполнять несколько функций.Я создал «главный» скрипт, который называется EnemyHandler, и этот скрипт решает, когда запускать каждый скрипт.Методы активируются из события Health, когда враг получает повреждения, и EnemyHandler является подписчиком этого события.

Другим вариантом было использование события OnHealthChanged и дополнительного события OnDeath и запуск каждого сценария, но я чувствую, что это сделает их более зависимыми.

Это мой код (каждый класс отличаетсясценарий)

class AnimalHandler : MonoBehaviour
{
    private IHealth ihealth;

    [SerializeField]
    private ObjectDeath objectDeath;

    [SerializeField]
    private SmokeEffect smokeEffect;

    [SerializeField]
    private LootSpawner lootSpawner;

    [SerializeField]
    private ExperienceAdder experienceAdder;

    [SerializeField]
    private animalRange animalRangeScript;

    void Start()
    {
        ihealth = gameObject.GetComponent<IHealth>();
        ihealth.OnHealthChanged += WhenAnimalDies;    
    }

    private void OnDisable()
    {
        ihealth.OnHealthChanged -= WhenAnimalDies;        
    }

    public void WhenAnimalDies(float healthPercentage)
    {
        if (healthPercentage <= 0f)
        {
            objectDeath.Dead();
            smokeEffect.ProduceSmoke();
            lootSpawner.SpawnLoot();
            experienceAdder.AddExperience();
        }
    }
}

class SmokeEffect : MonoBehaviour
{
    [SerializeField]
    private GameObject smoke;

    public void ProduceSmoke()
    {
        Instantiate(smoke, transform.position, transform.rotation);
    }
}

class LootSpawner : MonoBehaviour
{
    //Lootbag when the animal dies
    [SerializeField]
    private GameObject lootbag;

    public void SpawnLoot()
    {
        lootbag.gameObject.SetActive(true);
        lootbag.transform.position = transform.position;
    }
}

class Health : MonoBehaviour, IHealth
{
    [SerializeField]
    private int maxHealth;
    private int currentHealth;
    public int CurrentHealth{..}

    public float CurrentHealthPercentage
    {
        get { return (float)CurrentHealth / (float)maxHealth; }
    }

    public event Action<float> OnHealthChanged = delegate { };

    void Start()
    {
        CurrentHealth = maxHealth;
    }

    public void ChangeHealth(int healthChange)
    {
        if (CurrentHealth <= 0)
            return;

        CurrentHealth += healthChange; //Damage is a negative number
        OnHealthChanged(CurrentHealthPercentage);
    }
}

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Он известен как объект Бога

https://en.wikipedia.org/wiki/God_object

Я бы порекомендовал не делать этого, потому что этот объект знает слишком много, а вместо этого я бы порекомендовал Inpendency Injection (DI)

(Кроме того, если вы используете этот объект Бога в качестве одиночного, вы будете иметь его везде в своем приложении, представьте, что вы хотите переименовать его, и у вас нет помощи IDE, вам придется обратиться к каждому отдельному файлу и сделать это,это высокая когезия)

https://www.codementor.io/mrfojo/c-with-dependency-injection-k2qfxbb8q

0 голосов
/ 24 декабря 2018

Это нарушает SRP?Нет

SRP (принцип единой ответственности) гласит, что класс должен управлять собой.В случае с вашим кодом ваши классы управляют .Когда враг умирает, у него есть эффекты: дым, анимация, выпадение добычи, опыт и так далее.Таким образом, классы, которые обрабатывают ... эти эффекты, передаются вашему классу противника, и когда враг умирает, он говорит: «О, мертвый сейчас, эй, после смерти, делайте свое дело».

Если это нарушит SRP, то ни один класс никогда не сможет вызывать методы любого другого класса. ответственность вашего врага заключается в порождении добычи.Он не знает, какого рода, как это происходит или какие-либо другие детали, просто он знает, что у него есть предмет добычи, и что после смерти он должен позвонить loot.spawn().

...