【不用找素材】ECS 游戏Demo制作教程(2) 1.16

一、知识点补充

1.工程内部

上一篇最后一步运行时,突然发现

变成52:1了,难道每次baking都是随机的?

破案了,52是index索引,1是version版本号

如果您在场景视图中看不到实体,但仍然可以在游戏视图中看到它们 - 打开“首选项”窗口(“编辑”>“首选项...”),然后在“实体”部分中,确保“场景视图模式” ;设置为“运行时数据”不是“创作数据”

using Unity.Entities;
using UnityEngine;

public class MyAuthoring : MonoBehaviour
{
    public int bakeIntData = 0;

    class MyBaker : Baker
    {
        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;
}

2.代码知识点

1.Unity DOTS中的baking Baker简介

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
    {
        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.NoneTransformUsageFlags.Dynamic的区别:

【不用找素材】ECS 游戏Demo制作教程(2) 1.16_第1张图片

 

对比一下可以发现,右边Dynamic的多了LocalToWorldLocalTransform两个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。

你可能感兴趣的:(游戏)