Unity DOTS Baking System与Baking World

发布时间 2023-12-01 11:05:28作者: 游戏开发阿博

最近DOTS终于发布了正式的版本, 我们来分享一下DOTS里面Baking阶段,Baking System,Baking World的关键概念,方便大家上手学习掌握Unity DOTS开发。Unity在Baking也是基于ECS模式开发设计的,所以Baking的时候也会有Baking System与Baking World,把Baking出来的数据放到Baking World里面。

对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。

Baking 的主要阶段

在Baker阶段执行之前,Unity会把subscene中所有的Authoring GameObject创建出对应的entity,这个阶段entity不包含任何组件数据,只包含一些metadata的描述数据。创建完Entity以后,就会执行Bakers 每个Baker处理对应它的authoring component的数据转化。每种类型的数据对应一种Baker,例如Entities Graphics就会有Baker将GameObject的渲染数据转换成renderers的数据。Unity Physics有Baker 把刚体RigidBody组件转成ecs数据。相同的类型只要一种Baker就即可。

Unity在运行Baker转换的时候,无法保证执行Baker的顺序, Baker不存在依赖关系。因此Baker不能去读取与改变entity中的组件数据,只能创建新的组件到entity。

PreBakingSystemGroup: 这个System分组执行发生在所有Bakers运行之前;

TransformBakingSystemGroup: 是一个用于处理实体的变换信息的系统组。它负责将实体的Transform数据进行烘焙,以提高性能和优化渲染。

实时Baking时,Unity会运行所有的baking system分组,它会把entity数据存入到entity scene,并序列化到磁盘。并把烘培出来后变化的数据同步到main ECS World里面。

Baking World

Unity 在Baker 每个entity scene的时候都是独立的。每次只处理一个场景。同时每个独立的场景都有一个独立的main world。同时在Baker每个场景的时候,我们的Unity会额外分配两个世界:

Unity 会在 Conversion world 里面来运行Baker与Baking Sytems来做场景物体的Baking。当Baking结束以后,Unity Baking比较Shadow World与Conversion World的变化,看哪些改变了,Unity只把本次改变同步给main World。

Baking System

Baking System 是一种机制,被用于批量处理ecs components与entities的数据。一个Baking System在Unity DOTS内部也是一个System,它基于多线程与Burst 编译器,能够很好做批量的处理。Baking System与Baker机制不同的点在于Baker是将authoring data一个一个的处理转换,然后Baking System用户成批的处理已经转换好的ecs components与entities。所以Baking这个过程在执行Baking System 之前,必须要把要先执行让Baker把所有的entity 都初始化创建出来以后,才能只能执行Baking System, 批量处理。在Baking System中你可以改变当前

创建一个Baking System,我们需要给Baking System加上[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]的注解。加了这个注解,我们系统Baker处理就会把它识别出来,并把它加入到Baking World里面来进行迭代。Unity每次Baking,都会迭代World里面的所有Baking System。接下来我们看一个Baking System 添加一个tag component到包含的某A组件的entity中的示例代码:

public struct AnotherTag : IComponentData { }

[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)]

partial struct AddTagToRotationBakingSystem : ISystem

{

public void OnUpdate(ref SystemState state)

{

var queryMissingTag = SystemAPI.QueryBuilder()

.WithAll<RotationSpeed>()

.WithNone<AnotherTag>()

.Build();

state.EntityManager.AddComponent<AnotherTag>(queryMissingTag);

// Omitting the second part of this function would lead to inconsistent

// results during live baking. Added tags would remain on the entity even

// after removing the RotationSpeed component.

var queryCleanupTag = SystemAPI.QueryBuilder()

.WithAll<AnotherTag>()

.WithNone<RotationSpeed>()

.Build();

state.EntityManager.RemoveComponent<AnotherTag>(queryCleanupTag);

}

}

定义了一个Baking System, 每次迭代update的时候,找出World中所有包含RotationSpeed组件并且不含AnotherTag组件的Entity的集合,给它们加上AnotherTag组件,找出所有不包含RotationSpeed且包含AnotherTag的Entity集合,把它们的AnotherTag删除掉。

今天的Baking Phase, Baking World与Baking System就分享到这里了,关注我学习更多的最新Unity DOTS开发技巧。