UnityECS的组件是专门用来存储数据的数据结构一般继承自IComponentData接口,当然Unity还提供了其他类型组件。
1.IShareComponentData 接口,定义共享数据组件。
using Unity.Entities;
using UnityEngine;
public struct OtherComponentData : IComponentData
{
}
//共享组件
public struct ShareComponentData : ISharedComponentData
{
public Mesh mesh;
}
主要用于列如大量敌人有共同的材质或者网格时候存储数据的,他们不会产生复制,只会占用一块内存。Unity会自动将他们汇集成一个Chunk(块) 内(注意块也是有大小的),当拥有共享组件的实体修改了其共享组件中数据时,会从内存复制一份该共享组件来修改,并重新放入一个Chun(块)里。
注意:创建共享组件时,我们要选择那些不经常变动的组件作为共享组件,因为修改实体共享组件中的数据时,会导致这个实体被移动到新的Chunk(块)中,这种移动块的操作是比较消耗时间的。(修改普通组件的值是不会改变实体的Chunk的)共享实体可以节省内存,特别是大量创建相同物体时,但不要滥用,这也会降低效率。
2.ChunkComponent(块组件)块组件和共享组件有点类似,它俩的区别是:修改块组件的值不会导致实体被移动到新的Chunk(块),而是将实体所在块的所有实体的块组件的值也一起修改。(可以看做直接操作的块的 “根数据” )
public struct ChunkComponent : IComponentData
{
}
public class EntityNew : MonoBehaviour, IConvertGameObjectToEntity
{
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
dstManager.AddChunkComponentData<ChunkComponent>(entity);
}
}
3.ISytemStateComponent (状态组件) 接口,它继承自IComponentData接口。ECS中目前没有提供回调方法,列如当物体删除时我们想要回调知道他被删除了,而状态组件在实体被销毁时该组件是不会被删除的,除非主动去删除。
// 状态组件
public struct SystemStateComponent:ISystemStateComponentData
{
}
namespace Unity.Entities
{
public interface ISystemStateComponentData : IComponentData
{
}
}
4.ISystemStateSharedComponentData(状态共享组件) ,同上,标记整个Chunk(块)
//共享状态组件
public struct SharedSystemStateComponent : ISystemStateSharedComponentData
{
}
namespace Unity.Entities
{
public interface ISystemStateSharedComponentData : ISharedComponentData
{
}
}
5.IBufferElementData(动态队列/缓冲区/数组),实体身上不能同时挂载两个相同的组件,但是也提供了可以挂载的方式。
//可以被挂载多次的组件
public struct IBufferComponetData : IBufferElementData
{
public int num;
}
namespace Unity.Entities
{
public interface IBufferElementData
{
}
}
public class BufferMonobehaviour : MonoBehaviour
{
public GameObject prefab;
private void Start()
{
var entityManager = World.Active.EntityManager;
Entity entity = GameObjectConversionUtility.ConvertGameObjectHierarchy(this.prefab, World.Active);
entity = entityManager.Instantiate(entity);
// 给实体添加一个缓冲队列
DynamicBuffer<IBufferComponetData> dynamicBuffer = entityManager.AddBuffer<IBufferComponetData>(entity);
//给该实体的缓冲队列添加数据
dynamicBuffer.Add(new IBufferComponetData { num = 1 });
dynamicBuffer.Add(new IBufferComponetData { num = 2 });
dynamicBuffer.Add(new IBufferComponetData { num = 3 });
}
}
//如何操作数据
public class BufferSystem : JobComponentSystem
{
struct BufferJob : IJobForEachWithEntity_EB<IBufferComponetData>
{
public void Execute(Entity entity, int index, DynamicBuffer<IBufferComponetData> bufferDatas)
{
for (int i = 0; i < bufferDatas.Length; i++)
{
Debug.Log("===" + bufferDatas[i].num);
}
}
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
BufferJob bufferJob = new BufferJob();
JobHandle bufferHandle = bufferJob.Schedule(this, inputDeps);
return bufferHandle;
}
}
注意这里Job中的IJobForEachWighEntity_EB专门用来筛选这种类型的。
相关脚本参考项目中 Scene16_OtherComponent 文件夹:
远程项目仓库(github):https://github.com/h1031464180/UnityECS