Unity DOTS 从入门到精通之 创建实体
文章目录
- 前言
- 安装 DOTS 包
- 创建实体
- 1.手动创建空实体(适用于运行时动态创建)
- 2.克隆 预制体(主线程同步操作)
- 3.克隆 预制体(兼容Job System)
- 4.通过 GameObject 转换(Baker方式)
- 其他Entity实体操作
前言
作为 DOTS 教程,我们将创建一个旋转立方体的简单程序,并将传统的 Unity 设计转换为 DOTS 设计。
- Unity 2022.3.52f1
- Entities 1.3.10
安装 DOTS 包
要安装 DOTS 包,请按照以下步骤操作:
(1)从菜单“窗口 → 包管理器”打开包管理器。
(2)搜索“ Entities” 并安装 Entities和Entities Graphics。
(3)搜索“ Universal RP” 并安装 Universal RP,并设置Graphics/Scriptable Render Pipeline Settings。
这会添加“实体”作为依赖项,并递归添加它所依赖的关联包( Burst、Collections、Jobs、Mathematics等)。
创建实体
1.手动创建空实体(适用于运行时动态创建)
// 通过 EntityManager 创建
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
Entity entity = entityManager.CreateEntity();
// 添加组件
entityManager.AddComponent<Rotator>(entity);
entityManager.SetComponentData(entity, new Rotator { speed = 100f });
2.克隆 预制体(主线程同步操作)
// 在 System 中实例化
public partial struct SpawnSystem : ISystem
{
[BurstCompile]
public void OnUpdate(ref SystemState state) {
//克隆子弹预制体
Entity bulletEntity = state.EntityManager.Instantiate(entitiesReferences.bulletPrefabEntity);
//设置子弹位置
SystemAPI.SetComponent(bulletEntity, LocalTransform.FromPosition(bulletSpawnWorldPosition));
//设置子弹伤害等属性
RefRW<Bullet> bulletBullet = SystemAPI.GetComponentRW<Bullet>(bulletEntity);
bulletBullet.ValueRW.damageAmount = shootAttack.ValueRO.damageAmount;
bulletTarget.ValueRW.targetEntity = findTarget.ValueRO.targetEntity;
}
}
3.克隆 预制体(兼容Job System)
// 在 System 中实例化
public partial struct SpawnSystem : ISystem
{
[BurstCompile]
public void OnUpdate(ref SystemState state) {
// 通过 EntityCommandBuffer 安全实例化
var ecb = new EntityCommandBuffer(Allocator.TempJob);
Entity bulletPrefab = GetSingleton<BulletPrefab>().Value;
Entity newBullet = ecb.Instantiate(bulletPrefab);
ecb.SetComponent(newBullet, new Bullet {
speed = 10f,
damageAmount = 5
});
ecb.Playback(state.EntityManager);
}
}
在 System 中创建实体时,推荐使用 EntityCommandBuffer 实现线程安全
动态创建实体需确保已添加必要的组件依赖(如 Transform 组件)
预制件方式适合需要大量复用的游戏对象(如子弹、敌人等)
4.通过 GameObject 转换(Baker方式)
原理:
GetEntity() 自动为 GameObject 创建 Entity
TransformUsageFlags.Dynamic 表示实体需要动态变换组件
适用于 SubScene 场景中的对象(烘焙阶段自动处理)
using UnityEngine;
using Unity.Entities;
public class RotatorAuthoring : MonoBehaviour
{
public float Speed;
//将 MonoBehaviour 的 RotatorAuthoring 组件数据(如 Speed)
//转换为 ECS 的 Rotator 组件数据(IComponentData)
public class RotatorBaker : Baker<RotatorAuthoring>
{
public override void Bake(RotatorAuthoring authoring)
{
//通过Bake方式,把当前游戏对象转换为Entity
var entity = GetEntity(TransformUsageFlags.Dynamic);
//给Entity添加数据组件
AddComponent(entity, new Rotator { speed = authoring.Speed });
}
}
}
//旋转数据类
public struct Rotator : IComponentData
{
public float speed;
}
其他Entity实体操作
摧毁一个实体
entityManager.DestroyEntity(entity);
添加组件
・AddComponent(Entity, ComponentType) : 全部
・AddComponentData<T>(Entity, T) : 基本组件
・AddSharedComponentData<T>(Entity, T) : 共享组件
・AddBuffer<T>(Entity) : 动态缓冲区组件
・AddChunkComponentData<T>(Entity) : Chunk 组件
・AddComponentObject(Entity, object) : 组件对象
entityManager.AddComponentData(entity, new Translation {
Value = new float3(2f, 0f, 4f)
});
获取组件
・GetComponentData<T>(Entity):基本组件
・GetSharedComponentData<T>(Entity):共享组件
・GetBuffer<T>(Entity):动态缓冲区组件
・GetChunkComponentData<T>(ArchetypeChunk):Chunk 组件
・GetComponentObject<T>(Entity):组件对象
Position position = entityManager.GetComponentData<Position>(entity);
组件更新
・SetComponentData<T>(Entity, T):基本组件
・SetSharedComponentData<T>(Entity, T):共享组件
・SetChunkComponentData<T>(ArchetypeChunk, T):Chunk 组件
entityManager.SetComponentData(entity, new Translation {
Value = new float3(2f, 0f, 4f)
});
删除组件
entityManager.RemoveComponent<Position>(entity);