上一篇最后一步运行时,突然发现
变成52:1了,难道每次baking都是随机的?
破案了,52是index索引,1是version版本号
如果您在场景视图中看不到实体,但仍然可以在游戏视图中看到它们 - 打开“首选项”窗口(“编辑”>“首选项...”),然后在“实体”部分中,确保“场景视图模式” ;设置为“运行时数据”不是“创作数据”
using Unity.Entities;
using UnityEngine;
public class MyAuthoring : MonoBehaviour
{
public int bakeIntData = 0;
class MyBaker : Baker<MyAuthoring>
{
public override void Bake(MyAuthoring authoring)
{
var entity = GetEntity(TransformUsageFlags.None);
AddComponent(entity, new IntComponent { value = authoring.bakeIntData });
}
}
}
public struct IntComponent : IComponentData
{
public int value;
}
baking是DOTS ECS工作流的一环,大概的意思就是将原先Editor下的GameObject数据,全部转换为Entity数据的过程。baking是一个不可逆的过程,原先的GameObject在运行时不复存在,都会变成Entity。
baking只会在Editor环境下运行,而且只会对SubScene中包含的GameObject进行烘焙。SubScene是Unity提供的一种场景格式,SubScene中的GameObjects和MonoBehaviour会转换成ECS中的entity和component。之所以搞出一个新的格式,是因为ECS和之前老的scene system不兼容。
baking主要分为两个关键步骤,其一是Bakers,负责将GameObjects转换为entities和components,其二是Baking systems,对上一步中生成的entities可以再做额外处理。
通常,一个Baker和一个MonoBehaviour绑定,Baker可以使用MonoBehviour中的数据,为Entity添加组件,例如:
using Unity.Entities;
using UnityEngine;
public class MyAuthoring : MonoBehaviour
{
public int bakeIntData = 0;
class MyBaker : Baker<MyAuthoring>
{
public override void Bake(MyAuthoring authoring)
{
var entity = GetEntity(TransformUsageFlags.None);
AddComponent(entity, new IntComponent { value = authoring.bakeIntData });
}
}
}
public struct IntComponent : IComponentData
{
public int value;
}
代码很简单,就是为当前的Entity添加了一个IntComponent
的Component,这个IntComponent
的value是用MyAuthoring
里的bakeIntData
设置的。
我们在代码中获取当前Enity时,使用了TransformUsageFlags.None
这个参数。根据Unity给出的官方文档,这个flag是用来告诉Unity如何将GameObject中的transform转换成ECS的Components的。如果flag为None,说明Entity不需要transform相关的Components,而如果flag为dynamic,则会尽可能把transform的信息复制到Entity里。
我们可以对比一下使用TransformUsageFlags.None
和TransformUsageFlags.Dynamic
的区别:
?
对比一下可以发现,右边Dynamic的多了LocalToWorld
和LocalTransform
两个Component,它们包含了transform的各种信息。
那么,Baker触发的时机是怎样的呢?
首先,对于SubScene,它在Hierarchy中有两种状态,一种是open,一种是closed,在Editor环境下,SubScene的右侧有个勾选,如果没有勾选,就是closed,反之则是open。
根据官方文档,closed状态下,Unity会执行full baking,这是一个异步的过程。
在SubScene里放两个空的GameObject,分别叫GameObject1和GameObject2,给它们都挂上MyAuthoring这个脚本,这时,进入挂有SubScene的场景时,就会触发Bake了。说明只有SubScene需要被load时,才会触发它的baking。
下面,我们回到SubScene,只修改某一个GameObject的transform或者MyAuthoring的BakeIntData:
保存之后再次回到场景,会发现没有修改过的GameObject2也重新进行了baking,也的确是full baking。但是,如果我们把GameObject1修改回之前,却发现此时并不会触发full baking,原来Unity对baking的结果是会进行缓存的,如果缓存中存在就不会再次baking了。
不过,我们也可以手动触发full baking,比如直接reimport SubScene,或者在Preference中clear掉缓存。
除此之外,open subscene会执行incremental baking,也就是只bake发生修改过的data,不过这要取决于需要处理的数据量。
比如此时如果只修改GameObject1的transform,MyAuthoring的Bake是不会被触发的,因为它本身并没有发生改变。incremental baking的log也提供了相关的信息:
如果我们再修改MyAuthoring的BakeIntData,此时就会触发Bake了,不过因为只有GameObject1发生了修改,所以也只有GameObject1需要重新进行Bake。