Unity DOTS1.0(4) Baking 和 Baker

Baking

概念:

  1. 把Editor中的GameObject数据转换成entities数据写入到Entity Scens里面,这个过程我们叫做Baking
  2. Baking是一种不可逆的操作,把低效代价昂贵的但是灵活的GameObjects转换成性能高效的Entities与Components。

作用:

  1. 在传统的模式下,开发者使用的GameObject机制进行创作,然后运行也是基于它的. 通过baking,能让用户在ecs模式下,创作的时候使用还是使用GameObject机制来创作,增加易用性。
  2. Unity通过Baking的方式,把GameObject数据Authoring Data(创作数据)在编译时就转换为Runtime Data(运行数据),这样在运行的时候就可以直接使用运行数据

处理过程

  • 在ECS模式下,传统的GameObject,称为Authoring GameObject, Authoring GameObject上的Component 称为: Authoring Component

  • Authoring Scenes:传统的GameObject所在场景叫做authoring scene,用来将传统GameObject数据转换成ECS模式下的数据所在的场景(场所);

  • Baking 转换发生的过程只会在编辑器的模式下,在运行前先转好ecs数据,然后运行的时候直接使用ecs数据; 无论什么时候,只要我们Authoring Scene中的Authoring GameObject被改变了,就会触发我们Baking; Authoring Scene必须要必须要作为subscene加载进来时,创作Scene才会执行baking;

    • 会baking:
      会触发baking
    • 不会baking
      不会触发baking

baking的两种模式:

  • Full baking(全baking): Unity整个Authoring Scene 全部bake成entities scene;

    • 触发条件:
      1:在我们的disk上,找不到转换好的entities scene的数据;
      2:我们的Authoring Scene被修改了,同时entity scene,已经过期了;
      3:当修改了Baker代码的时候,BakingVersion,注解的时候,会引发full baking;
      4: A[BakingVersion] attribute注解的Baking代码被修改了,会引发full baking.
      5: Project Setting设置里面与Entities相关的设置被修改了,会导致引发fullbaking;
      6:如果你在subscene节点的属性检查器里面点击了reimport按钮,那么这个时候会导致full baking;
      7:如果你清理了Baking Cache,也会导致我们的full baking;
    • Full Baking会把我们的输出数据存放到我们的磁盘disk上(一些文件文件),你编辑器或运行的时候需要使用,就去加载
  • lncremental baking(增量baking):只bake改变的数据;

    • 当作为subscene来加载创作场景的同时我们也创建与初始化了Incremental baking;
    • 在创作编辑的时候,可以在ECS的数据里面直接体现出实时编辑与修改的结果;
    • 增量Baking只会发生在我们的内存里面,不会同步到我们的disk;
    • 当编辑场景数据的时候,会把改变的baking到内存里面,所以ECS就可以直接使用编辑好的数据。同时只baking改变的数据,所以速度非常快;
  • 注意: lncremental Baking 和Full baking输出是不同的,就会导致entity的顺序不同,内存大小不同,chunk的排布可能也不同。所以为了避免一些可能的未知错误,需要使用Reimport来强制进行full baking
    在这里插入图片描述

Baker运作机制

  • 一个Baker就是Baking 的其中的一个执行者,负责把某个Authoring Data转成ecs data;
  • 要定义一个Baker,首先要定一个托管类:继承Baker,T指的是要转换的Authoring Component的类型;
  • 当Baking的时候只要遇到这种类型的Authoring Component,就会找到这个Baker,然后调用这个Baker方法,并把要转的组件数据对象作为参数,输入进来;
  • 代码示例:
// IComponentData是一个空接口,只是用来标记这个类是一个ComponentData
// 这是unmanaged 类型,不会被GC管理, 内部只能使用unmanaged的数据类型
struct ComponentData : IComponentData
{
    public float rotSpeed;
}

public class ComponentAuthoring : MonoBehaviour
{
    public float rotateSpeed = 90f;
}

// 自定义一个Baker,方便我们场景在Bake的时候,来转这个组件数据
public class MyComponentBaker : Baker<ComponentAuthoring>
{
    // subscene bake时调用的方法 编译时就调用
    public override void Bake(ComponentAuthoring authoring)
    {
        // 获取到对应的Entity
        var entity = GetEntity(TransformUsageFlags.Dynamic);
        // 这里只是数据传递,并不是Entity中通过Archetype分配出来的内存
        var data = new ComponentData()
        {
            // authoring是我们在场景中设置的值
            // ECS 中使用的数学库是Unity.Mathematics!
            rotSpeed = math.radians(authoring.rotateSpeed)
        };
        // 将数据添加到Entity中
        AddComponent(entity, data);
    }
}
  • 对于其他Unity自带的Component(例如 Collider这些),Unity已经提供了写好了的Baker。
  • Full Baking,Authoring Scene 里面所有组件的Baker都会被调用一次;lncremental Baking:那么只有修改的组件才会被Baker一次;

在baker中访问其他来源数据

为了保证lncremental Baking的正常工作,Unity会自动跟踪我们的Authoring Component中的数据成员,当数据成员改变了,就会调用Baker的bake方法,让他重新执行;但是Unity不会跟踪这个转换依赖的其它的数据资源, 所以需要在Baker方法里面添加依赖关系,系统才可以追踪依赖的变化。

  • 代码示例:
public class DependentDataAuthoring : MonoBehaviour
        {
            public GameObject Other;
            public Mesh Mesh;
        }

        public class GetComponentBaker : Baker<DependentDataAuthoring>
        {
            public override void Bake(DependentDataAuthoring authoring)
            {
                // Before any early out, declare a dependency towards the external references.
                // Because even if those evaluate to null, they might still be a proper Unity
                // reference to a missing object. The dependency ensures that the baker will
                // be triggered when those objects are restored.

                DependsOn(authoring.Other);
                DependsOn(authoring.Mesh);

                if (authoring.Other == null) return;
                if (authoring.Mesh == null) return;

                var transform = GetComponent<Transform>();
                var transformOther = GetComponent<Transform>(authoring.Other);

使用DependOn方法声明依赖项,这样当Other或者Mesh变化时,这个GameObject也会被Baking

**注意:**这里的GetComponent并不是原来意义上的GetComponent. 它在调用时内部也会注册依赖关系, 即使一开始对象上没有GetComponent获取的组件(baking时返回为空) 当重新获得这个组件的时候也会再一次触发这个Baker

  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值