【UnityDOTS 二】Entity的理解

Entity的理解

Entity作为一种对CPU的Cache友好的编码方式,是DOTS中重要的编码流程与思想。需要程序员由OOP的思想转为DOD的思想,即:面向数据的编码方式。

Unity的ECS:
Entity:只是一个代表,用于快速查找数据等
Component:只有数据的Struct,无法被引用(特殊手法可以),大量相同的Component并排在内存中,可以提高Cache的命中率,以及Burst编译器生成SIMD命令提高性能。
System:用于处理Component的类,包含真正的处理逻辑,有一套自己的生命周期管理。可以遍历筛选出自己需要的Component进行处理。在System中可以结合JOBS来进一步提升性能。

一、Entity是什么?

Entity在DOTS的ECS系统中,只是作为一个包装的概念,看下官方文档的解释。
【UnityDOTS 二】Entity的理解_第1张图片
简单理解就是一个Struct,里面包含两个数据,Index以及Version。Index指向Entity在EntityWorld中的编号,Version则是版本号。因为Index会被复用,所以销毁一个Enity,又创建一个的时候,这个Index会被复用,然后通过Version就可以判定一个唯一的Enity了。

二、Entity的创建

1.Authoring模式

Authoring模式,在subScene中创建一个GameObject,Unity会隐式使用一个叫做Bake的过程,把托管的GameObject转换成对应的Entity(以及附带的各种内部Component)。
我们还需要用自定义的Component,这个时候,可以在对应的Monobehaviour脚本中,添加一个继承Baker的类,来转换你想要的Enity,以及动态添加自定义的Component

struct RotateSpeed : IComponentData
    {
        public float rotateSpeed;
    }
    public class RotateSpeedAuthoring : MonoBehaviour
    {
        [Range(0, 360)]public float rotateSpeed = 360.0f;
        public class Baker : Baker<RotateSpeedAuthoring>
        {
            public override void Bake(RotateSpeedAuthoring authoring)
            {
                var entity = GetEntity(TransformUsageFlags.Dynamic);
                var data = new RotateSpeed
                {
                    rotateSpeed = math.radians(authoring.rotateSpeed)
                };
                AddComponent(entity,data);
            }
        }
    }

以上代码就是将一个挂载了RotateSpeedAuthoring脚本的GameObject转换成一个Entity的过程。同时还为这个Entity添加了RotateSpeed的自定义Component

注意:Baker是增量bake的。

/// 
        /// Called in the baking process to bake the authoring component
        /// 
        /// 
        /// This method will be called for every instance of TAuthoringType in order to bake that instance.
        /// 
        /// The authoring component to bake
        public abstract void Bake(TAuthoringType authoring);

备注:BakingSystem:用于控制Bake产出的Entity行为,相当于bake转换Entity时,可以通过这个类来控制对应的Entity产出,比如:可以给某些entity转换时,都加上一个Component数据。避免一个个在各个Bake里面手动加代码。

2.Runtime模式

World:Entity的集合,每个Entity在一个World中ID唯一,但是Unity中可以有多个World,各个World中的Entity可能有相同的ID。
EntityManager:管理他自身所在World中的所有Entity,可以创建,销毁Entity,也可以增、删、刷新Entity中的Component数据

ComponentData与Entity具有一定的映射关系,同时ComponentData因为是Struct类型,所以无法(一般情况下)在托管对象进行引用从而管理里面的数据。

创建Entity流程:
1.创建World或者获取一个World;2.拿到World中的EnityManager,创建一个Entity;3.,同时也可以通过这个EntityManager来管理Entity上的Component;4.通过创建的Entity来获取EntityAcheType来实例化更多同类型Entity;5.对应的System就可以实现对这些Entity进行逻辑处理了。

备注:Entity之间没有父子之类的关系,但是可以通过Parent组件来体现这种关系。

var generator = SystemAPI.GetSingleton<CubeGeneratorByPrefab>();
            var cubes = CollectionHelper.CreateNativeArray<Entity>(generator.cubeCount, Allocator.Temp);
            state.EntityManager.Instantiate(generator.cubeEntityProtoType, cubes);
            int count = 0;
            foreach (var cube in cubes)
            {
                state.EntityManager.AddComponentData<RotateAndMoveSpeed>(cube, new RotateAndMoveSpeed
                {
                    rotateSpeed = count*math.radians(60.0f),
                    moveSpeed = count
                });
                var position = new float3((count - generator.cubeCount * 0.5f) * 1.2f, 0, 0);
                var transform = SystemAPI.GetComponentRW<LocalTransform>(cube);
                transform.ValueRW.Position = position;
                count++;
            }
    
            cubes.Dispose();

其中:SystemAPI.GetSingleton可以用来获取唯一的组件如上图的:CubeGeneratorByPrefab【UnityDOTS 二】Entity的理解_第2张图片

总结

ECS作为DOTS中的一种面向数据的设计思想,理解内核还是很重要的,后续再加上其他内容

你可能感兴趣的:(DOTS,unity,c#,DOTS)