前言
- 看来unity已经认识到现在编写代码的一些问题了:OO的模型、mono所编译的糟糕的机器码、GC和单线程。emmm
- ECS的推出就是为了解决上面的问题,同时使用ECS是为了能够利用C# Job System和Burst compiler。job system是支持多线程的(( Ĭ ^ Ĭ ))
ComponentSystem
- 在后面的文章中会说到ECS中的Component,这里简单说下,新的component模型只包含了数据,而ComponentSystem包含了行为。
- 一个ComponentSystem负责在每帧中对物体进行操作,这些物体必须匹配ComponentSystem所定义的一组component。有点类似后面讲到的的EntityArchetype。看下代码的例子:
1 | class Rotator : MonoBehaviour |
- Rotator是现在系统中的一个MonoBehaviour,而RotatorSystem是一个ComponentSystem。后者包含了一个Group用于匹配GameObject,而OnUpdate方法则是处理行为的函数。
如何在现有的系统中使用ComponentSystem
目前是需要在每个GameObject上挂一个GameObjectEntity脚本,它在OnEnable方法中会创建一个entity,挂上GameObject上的所有组件。然后就能被ComponentSystem使用了。
这意味着你可以将所有的行为处理从MonoBehaviour.Updata中转移到 ComponentSystem.OnUpdate中,数据仍旧可以保持在MonoBehaviour中。
这样做的优势
- 数据(MonoBehaviour)与行为(ComponentSystem)的分离
- 一些对象上的系统操作是批量的(应该是基于Job System),便于优化代码。比如上面代码中的deltaTime的使用。
- 可以继续使用现存的inspector、editor工具等。
劣势
- 实例化时间没有改善
- 加载的时间没有改善
- 数据时随机访问的,非线性。线性数据访问的问题下面会说到。
- 非多核的
- 非SIMD
总结来说这样的混合方案性能提升有限
Pure ECS
- ECS不支持托管类型,支持struct和NativeContainer类型。所以只有IComponentData可以被C# Job安全的访问。
- EntityManager(后面会提到)保证了线性的内存布局 ,这是性能提升很重要的部分。通过job和IComponentData可以做到。
- 目前想将ComponentData添加到GameObject上需要使用ComponentDataWrapper
1 | // The rotation speed component simply stores the Speed value |
1 | // Using IJobProcessComponentData to iterate over all entities matching the required component types. |
- 这段代码和ComponentSystem的部分有类似的结构,但是它结合了JobSystem,做到了并发执行。而且里面还有依赖注入的部分,下一篇在将ECS功能的时候会详细来说。
总结
- Unity ECS做到了数据与行为的分离,而且更加轻量级。
- 通过结合JobSystem实现了CPU多核的利用。
- 目前来看在已有系统结构上使用ECS有点累赘的感觉。