Unity3D实体系统如何工作?

我看到了Java Artemis实体组件系统,并想到了Unity3D中的实体系统。

例如在Artemis中,您只能为每个实体添加一个组件types,而逻辑不在组件中。

在Unity3D中是完全不同的。 有人能解释一下统一3D中的实体系统是如何工作的吗?

我的意思是,Unity3D是一个真正的实体系统,还是其他的东西?

是的,它仍然是一个实体系统。 对于一个实体系统应该如何工作没有严格的定义,所以它和Artemis不同。 两者仍然有由组件组成的实体。

实体系统的目标是摆脱基于inheritance的devise。 Unity的系统实现了这个目标。

与Artemis类似,您可以将组件添加到实体以创建新对象。 更改组件中的数据可以在表面级别上大幅改变生成的对象。 一些关键的区别是存储逻辑的位置,以及如何将组件分组进行处理 。 虽然这些差异可能看起来很戏剧性,但并没有太大的差别。 两种方法都可以修改得更加相似。 例如,您可以在Unity中创建仅包含数据的组件,并创建“系统”来查找具有特定组件的所有游戏对象并对其进行处理。

无论哪种方式,你将有组件和实体。 如果实体不是从一长串inheritance的类派生的。 这减less了代码重复,减less了不必要的代码和数据,并为您提供了一个简单的方法来思考如何创建对象。

虽然定义可能会有所不同,但我不会将Unity3D定义为实体系统引擎。 当我们谈论实体系统时,我们应该遵循亚当·马丁的定义。

根据他的想法,系统应该由程序员创建,而在Unity3D中,“系统”是在引擎中预定义的,不能被扩展。

这是管理实体和组件的一种古老方式,它更多的是古代技术的进化,游戏对象持有指向与引擎function(如渲染,剔除等)兼容的组件的指针。

当然,当不能扩展“系统”function时,扩展实体逻辑的唯一方法是在组件内部添加逻辑。 这是经典的面向对象技术向前迈出的一步。 面向组件(我称之为实体组件,没有系统)框架就像Unity中的一样,推动编码者偏好组合inheritance,这当然是更好的做法。

Unity中的所有逻辑应该写在关注的MonoBehaviour中。 每个MonoBehaviour应该只有一个function或责任,并且不应该在GameObject本身之外进行操作。 应该以模块化的方式来编写它们,这样它们可以在多个GameObjects上独立重用。 Monobehaviours也拥有Data,其devise明显遵循OOP的基本概念。

现代devise倾向于将数据与逻辑分离。 参见例如MVC或MVP模式。 数据,视图和逻辑应该分开,以达到更好的代码模块化。

Unity实体组件devise的真正问题是需要以合理的方式使两个实体进行通信,而不会导致使用各种反模式。

Unity颠倒了对实体创建的控制,因此编码器对它们的创建没有任何控制权。 反转创作控制是一件好事,但Unity并没有以适当的方式去做。 不能在实体中注入依赖关系是一个限制,迫使编码人员使用反模式来克服所有内在的后果。

最后,最简洁的选项是使用单身来共享实体之间的信息。

这就是为什么使用Unity管理和维护大型项目非常困难。 我在博客中写了很多有关这些问题的信息。 所以,如果你想要,你可以继续阅读我的想法:

http://www.sebaslab.com/ioc-container-for-unity3d-part-1/

http://www.sebaslab.com/ioc-container-for-unity3d-part-2/

http://www.sebaslab.com/the-truth-behind-inversion-of-control-part-i-dependency-injection/

http://www.sebaslab.com/the-truth-behind-inversion-of-control-part-ii-inversion-of-control/

http://www.sebaslab.com/the-truth-behind-inversion-of-control-part-iii-entity-component-systems/

http://www.sebaslab.com/the-truth-behind-inversion-of-control-part-iv-dependency-inversion-principle/

http://www.sebaslab.com/the-truth-behind-inversion-of-control-part-v-drifting-away-from-ioc-containers/

在这些post中,我广泛讨论了阻碍大项目开发的Unity3Ddevise缺陷,以及IoC容器和实体组件系统框架作为可能的解决scheme。

Unity3D在GameObject-Component模型的基础上工作。 它与实体组件系统完全不同。 根据我的经验,这更糟,因为当你想编写一些逻辑的时候把它放到脚本组件中,而不是系统。 与OOP模型有什么不同? Unity3D GameObject包含数据和逻辑 – 与OOP相同,这些组件不可重用(这是不做OOP的原因之一)。 当然,你可以制定一些防弹的约定来防止混合数据和逻辑,但这样做可能是一件相当艰巨的工作。

依赖。 在ECS中工作时,每个系统都有一个方面(它描述了它管理的组件)。 由于方面,你的组件依赖于系统而不是其他组件。 我看过很less的组件引用对方的代码。 当执行顺序设置不正确的时候,那么…一塌糊涂。 当你重构组件(逻辑)依赖关系时,最好在一个地方完成,比如System,而不是less数地方(Components)。

Unity3D中使用的模型的另一个很大的缺点是管理同一个方面(组件集合)的对象是一个问题。 在我看来,如果可能的话,最好是采用ECS的方式,或者更接近它。 在Unity3D中采取这种方法,请看@ Byte56答案。