https://www.u3dc.com/archives/3509
目录
什么是DOTS
打印案例
1、Struct结构体数据继承IComponentData接口
public struct PrintComponentData : IComponentData {
public float printData;
}
2、系统脚本继承ComponentSystem,遍历所有实例找到对应的组件数据脚本
public class PrintComponentSystem : ComponentSystem {
protected override void OnUpdate() {
Entities.ForEach((ref PrintComponentData data) => {
Debug.Log(data.printData);
});
}
}
3、游戏对象添加ConverToEntity组件转为实体Entities,这时运行程序游戏对象就会消失
4、添加Authoring脚本,在游戏对象转换为实体时调用此脚本,用以将组件数据绑定至实体上
public class PrintAuthoring : MonoBehaviour, IConvertGameObjectToEntity {
public float printDataInAuthoring;
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) {
dstManager.AddComponentData(
entity, new PrintComponentData() {
printData = printDataInAuthoring
}); ;//实体管理器为entity添加组件数据
}
}
步骤总结
组件存放数据,继承IComponentData => 系统类处理逻辑,继承ComponentSystem => 游戏对象添加ConvertToEntity脚本,用以转换为实体 => Authoring脚本继承IConvertGameObjectToEntity,添加在游戏对象转为实体时调用的逻辑方法 => 完毕
DOTS调试面板
Window->Analysis -> EntityDebugger
- 左侧是正在运行的系统。运行时取消勾选某个系统,该系统就会暂停。如取消勾选PrintComponentSystem就会停止打印;左上角按钮可以选择不同世界。
- 中间是所有的实体,点击后即可在Inspector面板显示,该实体附带的所有组件以及组件的数据,该实体被哪些系统调用;可使用Filter按钮根据组件对实体进行过滤。
- 右侧是组件堆的使用情况。
Translation组件的使用
Translation为自带组件,所以省去了继承IComponentData的组件数据;又因为实体默认自带Translation组件,所以省去了Authoring类,只需定义System类处理逻辑
public class TranslationSystem : ComponentSystem {
protected override void OnUpdate() {
Entities.ForEach((ref Translation translationData) => {
translationData.Value = new float3(1f, 1f, 1f);//唯一到(1,1,1)点
});
}
}
Transform命名空间下组件使用
默认实体不自带RotationEulerXYZ组件,所以需要Authoring+System两个脚本
public class RotationEulerXYZAuthoring : MonoBehaviour, IConvertGameObjectToEntity {
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) {
dstManager.AddComponentData(entity, new RotationEulerXYZ());
}
}
注意对比第一个小案例,new PirntComponentData时后面可以添加代码块?
public class RotationEulerXYZSystem : ComponentSystem {
protected override void OnUpdate() {
Entities.ForEach((ref RotationEulerXYZ rotationEulerXYZ) => {
rotationEulerXYZ.Value = new Unity.Mathematics.float3(0f, 45f, 0f);//绕Y轴转45度
});
}
}
屏蔽系统之间的干扰
第三个Rotation案例中的Cube会受第二个案例内Transform组件的影响,即System自动启用,关闭方法是添加[DisableAutoCreation]特性,之后发现Cube原地旋转
[DisableAutoCreation]
public class TranslationSystem : ComponentSystem {
protected override void OnUpdate() {
Entities.ForEach((ref Translation translationData) => {
translationData.Value = new float3(1f, 1f, 1f);
});
}
}
Prefab => Entity预制体 => Entity实体
从MonoBehaviour中实例化实体
public class ECSPrefabCreator : MonoBehaviour {
public GameObject cube;
void Start() {
GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);
Entity cubeEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(cube, settings);
EntityManager manager = World.DefaultGameObjectInjectionWorld.EntityManager;
Entity cubeEntity = manager.Instantiate(cubeEntityPrefab);
}
}
- 没明白各个类干嘛使的,先记录下,TODO
通过EntityManager修改组件Translation的值
public class ECSPrefabCreator : MonoBehaviour {
public GameObject cube;
void Start() {
GameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);
Entity cubeEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(cube, settings);
EntityManager manager = World.DefaultGameObjectInjectionWorld.EntityManager;
Translation translation = new Translation();//值类型
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
Entity cubeEntity = manager.Instantiate(cubeEntityPrefab);
translation.Value.x += 2;
manager.SetComponentData(cubeEntity, translation);
}
translation.Value.x = 0;
translation.Value.y += 2;
}
}
}
核心:manager.SetComponentData(cubeEntity, translation);
JobComponentSystem+Burst优化RotationEulerXYZ
public class JobSystemTest : JobComponentSystem {
protected override JobHandle OnUpdate(JobHandle inputDeps) {
JobHandle jobHandle = Entities.ForEach((ref RotationEulerXYZ rotationEulerXYZ) => {
rotationEulerXYZ.Value = new float3(0, 45, 0);
}).WithBurst().Schedule(inputDeps);
return jobHandle;
}
}
- 没懂,TODO
GPU Instancing优化批处理
在Material中设置Enable GPU Instancing,原理未知
- TODO