System的理解
前言
System主要用于在ECS中进行逻辑处理。它具有自己的声明周期,主要分为两类:ISystem,SystemBase。前一个是非托管内存访问,后一个是托管内存访问。
一、Systemg认知
System在主线程运行,可以在代码中使用Job系统来分发任务到其他子线程中。具有类似monoBehavour的生命周期函数:OnCreate,OnDestroy,OnUpdate等,根据名字不难判定他的调度时机。这些函数会传入一个ref SystemState参数,基本上提供了访问整个Entity环境内各种系统的方法。
一个World中只有一个对应的System实例,从原理上来说System可以访问任意Entity,但是建议还是System访问自己所在的World中的数据。
二、ISystem,SystemBase功能区分
ISystem可以使用的功能:Burst编译、非托管内存分配、原子性的Foreach访问、使用IJobEntity与IJobChunk。
SystemBase可以使用的功能:GC、可存储管理托管对象、原子性Foreach、Entities.ForEach、Job.WithCode、使用IJobEntity与IJobChunk、支持继承。
三、SystemGroup
1.SystemGroup
用于对System进行管理,控制各个System的生命周期时机。
Unity默认创建的三种Group:Initialization,Simulation,Presentation。分别对应更新Unity引擎中PlayLoop中的更新时机(初始,循环,PreLate)。
SystemGroup中可以放入任意其他SystemGroup以及对应的System。其中Unity本身也预定义了很多自己的SystemGroup以及System。
我们可以自定义自己的SystemGroup,并将对应的System放入到我们自己定义的SystemGroup中。目前我们自定义的SystemGroup一般都会被Unity放入到Simulation System Group中去。
通过继承ComponentSystemGroup就可以自定义一个自己的Group。
2.控制System中的更新顺序
UpateInGroup:可以指定你的System加入到对应的Group中
UpdateBefore/UpdateAfter:可以指定System在相同的Group中的前后更新顺序
CreateBefore/CreateAfter:可以直接指定与其他System的前后创建与销毁的顺序,即OnCrate,OnDestroy的调用顺序。备注:Destroy与Create顺序相反。
DisableAutoCreation:禁止World自动给你创建这个System。默认状态下编写了一个System,world会自动实例化这个System,并进行运行。开启这个后,可以手动添加System,手动调用.Updateq去更新,对有特殊更新逻辑的System可以用这种方式。
总结
SystemGroup可以用来管理组内的System,也可以使用Enable来控制整个Group是否启用。
备注:需要控制SystemGroup的空跑Update,原理与MonoBehavoiur类似。
在System中尽可能不要定义Public数据对外提供数据功能,破坏了线程调度的安全性(虽然System在主线程中运行,但是对外提供比如对Job提供了访问数据的功能,就会造成线程不安全)。
最好是使用EntityQuery以及GetComponentTypeHandle的方式来访问Chunk中的Component数据,不要通过EntityManager来访问,比较低效。(有些功能,比如创建Entity之类的,这种就应该使用EntityManager来进行)