组件驱动的设计架构 - 组件之间的通信

时间:2018-04-04 19:23:52

标签: unity3d architecture components

我正在使用Unity3D构建一个游戏,我有一个关于如何构建我的actor体系结构的问题(演员我指的是可以用这种或那种方式与其他对象交互的对象)。

所以,我遵循了一个组件驱动的设计,每个组件负责处理一个对象的不同方面(例如动画组件,移动组件,攻击组件等),但是我无法确定组件应该如何与之通信彼此。我的想法是:

  1. 每个对象都有一个组件管理器,用于保存对象上附加的每个组件的引用。组件通过组件管理器的引用相互通信。

  2. 每个组件都负责保存自己的引用并在内部处理通信。我能想到的缺点是多个组件将保持相同的引用。

  3. 使用自动消息系统处理通信。(事件和听众)

  4. 我的问题是:有更好的方法来处理组件通信吗?                      每种方式有哪些好处或缺点?

    p.s我不是要求Unity或语言特定的答案只是向正确的方向推进。提前谢谢!

2 个答案:

答案 0 :(得分:1)

  

每个对象都有一个组件管理器,用于保存对每个对象的引用   附加在对象上的组件。组件与每个组件通信   其他通过组件管理器的引用。

     

使用自动消息系统处理通信。(事件   和听众)

我想说要把这两者混合起来。拥有每个对象的组件管理器将非常有用,尤其是在将来添加新组件时。只需在经理中为这个新参考字段创建一个参考字段即可。管理者也可以充当外部实体和经理组件之间的切入点。

相反,让对象拥有自己对其他组件的引用肯定是不好的,因为当新组件进入时你必须为所有组件分配引用。另外,这可能不会使组件彼此独立工作,因为他们将不得不在某个时间点访问彼此的功能,属性或变量。

使用事件在同一对象的组件之间进行通信可能不是一个好主意。在某些情况下,您可能需要调用函数并使用它的返回值来确定是否继续。例如,假设玩家有机会阻止传入的攻击,并且只有在攻击成功时才应更新玩家UI。你可以做点什么

void OnPlayerDamagedCommon() {
    bool damaged = PlayerDefense.OnPlayerDamaged();
    PlayerUI.OnPlayerDamaged(damaged);
}

但是,在不同对象之间进行通信时,事件将非常有用。例如,玩家可以在执行攻击时触发OnAttack事件,并且所有已订阅此事件的敌人都可以相应地做出响应。此外,任何类型的实体都可以订阅事件。成为敌人,NPC或环境对象。这样可以更轻松地本地化行为逻辑。

您还可以使用接口将一个对象添加到另一个对象的处理列表中。

class Enemy : IShootable {
    void Enemy() { 
        playerManager.AddToShootable(this); 
        public void OnShoot() {...}    
    }
}

class PlayerAttack {
    void OnShoot () {
        foreach(IShootable s in _shootableList) {
            if(CheckRaycast(s)) 
            { 
                s.OnShoot() 
            }
        }
    }
}

这有助于本地化代码以确定敌人是否被击中一个地方,而不是每个敌人都拥有自己的光线投射检查代码,如果您使用事件就是这种情况

答案 1 :(得分:0)

  

每个对象都有一个组件管理器,用于保存对象上附加的每个组件的引用。

如果组件继承自MonoBehaviour,则已经可以使用。 GetComponent()从GameObject获取组件,这适用于脚本和组件。

您是否有任何特殊原因希望建立自己的管理系统而不是使用内置的解耦系统?

来源:https://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html