Unity ECS System在什么时候更新?如何自定义这个更新的时机?

在什么时候更新?

在其他用户代码都执行完之后。

去Netcode的ClientServerBootstrap里可以找到CreateLocalWorld函数,里面有类似这样的代码:

public static World CreateLocalWorld(string defaultWorldName = "Default World")
{
var world = new World(defaultWorldName, WorldFlags.Game);
var systems = DefaultWorldInitialization.GetAllSystems(WorldSystemFilterFlags.Default);
DefaultWorldInitialization.AddSystemsToRootLevelSystemGroups(world, systems);
ScriptBehaviourUpdateOrder.AppendWorldToCurrentPlayerLoop(world);
return world;
}

其中ScriptBehaviourUpdateOrder.AppendWorldToCurrentPlayerLoop就是将World更新附加到UnityEngine.LowLevel.PlayerLoop后面的函数。这个函数内容也很简单,本质上是通过world.GetExistingSystemManaged分别获得InitializationSystemGroupSimulationSystemGroupPresentationSystemGroup;然后作为PlayerLoopSystem的SubSystem,构造出新的PlayerLoop之后,通过PlayerLoop.SetPlayerLoop应用到当前环境里。

没有Netcode的情况下也是类似的,只不过是通过DefaultWorldInitialization这个类来完成了。

如何自定义?

知道在哪里创建的,自然就知道该怎么自定义了。只要把ScriptBehaviourUpdateOrder.AppendWorldToCurrentPlayerLoop换成自己的东西就行了。比如:

var initGroup = world.GetExistingSystemManaged<InitializationSystemGroup>();
var simGroup = world.GetExistingSystemManaged<SimulationSystemGroup>();
var presGroup = world.GetExistingSystemManaged<PresentationSystemGroup>();
//找个地方调用initGroup.Update()
//找个地方调用simGroup.Update()
//找个地方调用presGroup.Update()
//顺序不要搞错了

以FishNet为例,就可以在TimeManager.OnPostTick里运行所有WorldSystemFilterFlags.ServerSimulation的System,于是这些基于GameObject的网络库也就可以用ECS设计模式了。
不过自定义了更新之后,在Editor的Systems界面里就看不到了,也算是一个小缺点吧。

posted @   horeaper  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· RFID实践——.NET IoT程序读取高频RFID卡/标签
点击右上角即可分享
微信分享提示