使用主脚本处理较小的脚本是否违反了Unity中的SRP /高内聚性?

时间:2018-12-24 01:33:44

标签: c# unity3d module single-responsibility-principle

我创建了多个小脚本来遵循Unity中的模块化模式。但是,此脚本可能需要其他脚本的信息。我这样做是为了可以将脚本作为其他对象的组件重用。是否正在创建将这些脚本归类为不良做法或违反SRP的“主”脚本?有没有更好的方法可以解决这个问题?可能有活动吗?

比方说我有一个敌人,当那个敌人死亡时,它将掉落一些战利品并提供一些经验。我为体验,战利品,死亡和健康创建了一个脚本。每个将具有几个功能。我创建了一个名为EnemyHandler的“主”脚本,该脚本决定何时启动每个脚本。每当敌人受到伤害时,就会从运行状况事件中激活该方法,并且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 :(得分:0)

这是否违反了SRP?不

SRP(单一责任原则)规定,班级应自行管理。就您的代码而言,您的类进行自我管理。当敌人死亡时,它会产生影响:烟雾,动画,战利品掉落,经验等等。这样,处理...这些效果的类就会传递到您的敌人类中,并且当敌人死亡时,它会说:“哦,现在死了,嘿,死后的东西,做您的事。”

如果这违反了SRP,则任何类都无法调用任何其他类上的方法。敌人的责任是生成战利品。它不知道它的种类,发生的方式或其他任何细节,只是知道它有一个战利品,而死后其责任是打电话给loot.spawn()

答案 1 :(得分:0)

它被称为神物

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

我建议不要执行此操作,因为该对象了解太多,而我建议使用依赖注入(DI)

(此外,如果将God Object用作Singleton,您将在应用程序中到处都有它,假设您要重命名它,而没有IDE帮助,则必须转到每个文件并执行该操作,凝聚力高)

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