用户代码中调用Instantiate时,引擎内分为两步执行:
异步InstantiateAsync与同步接口的区别在于:
由于微信小游戏是单线程,使用JobSystem加速transfer序列化构建对象无法达到预期的效果。另外对于单次实例包含大量对象, 例如包含Collider、Renderer等的Prefab,在完成IntegrateMainThread进入引擎事件生命周期后,首次更新会有较长的创建物理几何体,编译shader等耗时。
从实际的测试来看,执行第二步IntegrateMainThread所在的那一帧总时间远高于执行第一步构建对象所在的帧。 因此在微信小游戏平台上,我们对第二步IntegrateMainThread做了进一步分帧处理,允许单次InstantiateAsync调用能够拆分成更多帧执行。 当前版本为保证Renderer和粒子等继承自Behaviour的对象运行时序正确,允许最多分成4帧执行。纹理、shader等资源以及用户的MonoBehaviour不受该限制影响。
实例化总耗时 | 单帧最高时长 | 7帧总耗时 | 平均每帧耗时 | |
---|---|---|---|---|
Instantiate | 73.2ms | 73.2ms | 160ms | 22.8ms |
InstantiateAsync | 84ms | 35.6ms | 135ms | 19.2ms |
从测试结果看,在实例化相同的对象时,单帧最高时长为73.10ms。替换为InstantiateAsync后,降低为35.6ms。另外,异步接口因为将工作负载拆分到了4帧完成,7帧总耗时降低为135ms,同步接口耗时约160ms。
InstantiateAsync 的分帧效果受IntegrationTime时长设置影响较大,默认为每帧2ms, 可通过AsyncInstantiateOperation.SetIntegrationTimeMS 接口设置时长。更小的值能够减少卡顿,但会延长实例化的总耗时。
使用InstantiateAsync()接口时需要注意,在完成对象的实例化前,不能提前卸载对象所在的AB和其依赖AB。否则可能出现材质或prefab引用丢失的情况,导致游戏逻辑或渲染出错。