概念
在System中,我们就可以对Component中的数据进行处理了,例如我们每帧改变Translation Component的值,就可以使Entity移动起来。
ECS为我们提供了以下几种System类型,通常情况下,若我们要自己编写一个System用来处理Component数据的话,只需要继承SystemBase即可。其他的System类型用于提供一些特殊的功能,ECS已经为我们提供了几个EntityCommandBufferSystem和ComponentSystemGroup的实例,一般情况下使用它们即可。
SystemBase | 继承该类就可以实现一个System的创建 |
EntityCommandBufferSystem | 用于解决Sync points的问题,在下一篇会讲解到 |
ComponentSystemGroup | 用于将其他的System进行层次结构的划分以及排序,ECS提供了几个默认的Component System Group |
GameObjectConversionSystem |
注:ComponentSystem和JobComponentSystem两个类以及它们的IJobForEach接口,将会被DOTS弃用。请使用SystemBase类与对应的Entities.ForEach接口代替。
ECS会自动找到项目中所有的System,并在运行时实例化它们,并将它们添加进一个默认的组里面。
创建一个System(SystemBase)
我们可以通过继承抽象类SystemBase来创建System(Entity和Component都是struct类型,System为class类型)。同时还必须要重写其OnUpdate方法,而其他的基类方法可以在我们需要的时候去重写。
System就和我们平常使用的MonoBehaviour十分的相像,它也有相应的生命周期,执行顺序如下图
OnCreate | System被创建的时候调用 |
OnStartRunning | 在第一次OnUpdate之前和System恢复运行的时候调用 |
OnUpdate | System的Enabled为true时,每帧调用 |
OnStopRunning | System的Enabled为false时,或者没有找到相对应的Entity会调用,OnDestroy前也会调用 |
OnDestroy | System被销毁的时候调用 |
一个System Group下有多个System,System的OnUpdate方法是由System Group的OnUpdate方法调用的,若我们设置System Group的Enabled属性,同时会影响到该Group下所有的System的Enabled属性。(有关System Group的知识后面会讲解到)
System所有的事件都是在主线程上执行的,理想的情况下,我们OnUpdate里的逻辑应该使用Job来进行多线程处理,从而提高效率。我们可以使用下面方法来在System中调度Job
Entities.ForEach | 迭代ECS Component数据的最简单方法 |
Job.WithCode | 单独执行一个lambda方法,后台job |
IJobChunk | 根据一个个Chunk去查找Component中的数据 |
C# Job System | 自己编写Job,实例化并调度 |
注:不太了解Job System的可以参考下之前的文章:https://blog.csdn.net/wangjiangrong/article/details/107020789
我们可以在Entity Debugger中查看所有的System以及对应的Group信息等
Entities.ForEach
Entities.ForEach方法由SystemBase提供,它让我们很简单的就实现对Entity上Component的逻辑处理。Entities.ForEach的参数为一个lambda方法,其参数即为Entity的查询条件,查找到所有符合条件的Entity后会执行其方法体。
对于要执行的l