官方文档Entities overview | Entities | 1.0.0-pre.15 (unity3d.com)
Entities包,是Unity“面向数据的技术堆栈(DOTS)”的一部分, 实现了一套面向数据的“实体-组件-系统(ECS)”架构。
请参阅GitHub - Unity-Technologies/EntityComponentSystemSamples以获取一些介绍材料,包含教程,实例和视频。
运行时在一个system的静态方法中调用SystemAPI的方法会产生报错:No suitable code replacement generated, this is either due to generators failing, or lack of support in your current context.
Blob Assets不支持带有yield return的方法。
从Entities0.51升级到1.0,你需要做的如下:
更新Transforms
更新conversions
移除GenerateAuthorComponent
更新get和create一个system的代码
移除继承ISystem的系统里的Entities.Foreach
更新IJobChunk来处理可激活的组件
IJobEntityBatch和IJobEntityBatchWithIndex换成IJobChunk
重命名异步EntityQuery的get/set方法
IJobEntityBatch和IJobEntityBatchWithIndex换成IJobChunk
刷新系统状态组件,清理组件
刷新TypeManager代码,使用TypeIndex而非int
刷新被直接访问的EntityCommandBufferComponent
更改system update的代码
重命名EntityQueryDescBuilder
更新SystemBase.Time和SystemState.Time
添加Entities Graphics包到项目里
移除的:
自动生成光照模式移除了
新增:
Aspects
Baking
Enableable components
The Journaling editor window
New authoring-tuntime workflow
Query
更新:
Tansforms
无需BuildConfiguration
设置从DOTS menu菜单挪到Preference窗口
版本日志:Changelog | Entities | 1.0.0-pre.15 (unity3d.com)
Entites1.0要求Unity版本2022.2.0b8及以上。
打开Package Manager窗口(Window->Package Manager),
点击左上角+号Add the package by its name,
安装com.unity.entities和com.unity.entities.graphics。
编辑器使用Visual Studio2022+或Rider2021.3.3+,以支持Source Generators | Microsoft Learn。
要在Entities项目中获得最佳性能,请禁用Unity的Domain Reload:
在Edit->Project Setting->Editor菜单中,
启用Enter Play Mode Options,
禁用Reload Domain和Reload Scene.
注意:如果你禁用了Domain Reloads,要留意静态属性和事件的使用。
Unity的ECS由一系列包,和部分参与协作的Unity引擎内容构成,来帮助你创建高效的代码。
主要有:
Entities(本包):ECS的实现。
C# Job System:快速,安全,多线程的代码解决方案。
Burst compiler:可以深度优化代码的编译器。
Collections:一套非托管类型的集合,例如lists和hash maps。这些在2和3中会用到,因为这些上下文只能访问非托管数据。
Mathematics:专为3优化过的数学库。
基于这些核心模块,还有一些DOTS包:
Physics:无状态的和确定性的物理系统。
Netcode:客户端-服务器网络编码解决方案。
Entities Graphics:使用可编程渲染管线(SRP)来渲染entities。
探索Unity ECS工作流,来理解在Unity中,各个模块如何通过协作,以实现面向数据的编程。
使用Unity ECS框架创建Unity应用的工作流,从原理上和实现上,都不同与以往的面向对象的Unity应用。在你开始使用这套框架创建项目之前,理解ECS工作流是有必要的。
ECS使用 subscenes来存放你的应用内容。添加GameObject和MonoBehaviour组件到subscene,bakers会将其转换成entities和ECS组件。
Components为你的应用存储数据。 systems通过读写ECS Component的数据,来为你的应用创建行为。ECS工作流是面向数据的,所以在编写systems或创建entities之前,规划数据格式并创建好ECS Component是更好的。
components有很多类型,用于不同的功能。了解更多信息,参考Component types.
Entities代表着应用中的不同事物。添加GameObjects到subscene,以在编辑器下创建entities。baking过程会把这些GameObejcts转换成entities。另外,在转换出的entities上添加ECS Components,你也可以创建bakers。当你创建baker时,要定义它是哪个Mono组件的,然后编码使用这个Mono的数据来创建并添加ECS component到转换出的entities上。你也可以从baker创建额外的entities,并添加ECS component。在这个流程中,Mono组件也称作authoring component。
TIP:建议你创建的authoring components类名都以Authoring结尾。
Systems 为你的应用定义行为。为此它们可以查询和转换Component的数据,创建或销毁entities,添加或移除entities上的components。默认情况下,Unity会将其你创建的system实例化并添加到默认的 world。
systems有很多类型,用于不同的功能。了解更多信息,参考System types.
默认情况下,system中的代码是在主线程中同步执行的。如果系统调集了很多entities并能获益于多线程,推荐创建Burst compatible jobs,尽可能使其并行。Burst将C#代码优化编译,并支持多线程。
如果一个system比较简单,例如只是处理少量的entities的数据,并行调度jobs的消耗可能会高于多线程带来的优化。分析这种jobs,用CPU profiler对比Unity在使用和不使用多线程时的耗时。如果调度jobs使代码多线程运行使得Unity耗时更长,尝试如下方法优化job:
在主线程中运行job。
如果system时非托管的ISystem,用SystemAPI.Query和一般的foreach替代job。然后你可以应给包含SystemAPI.Query的方法加上BurestCompile标签,来让query和代码被Burst编译。
【Mono(Authoring)通过Baker转成Componnet】
using UnityEngine;
using Unity.Entities;
using Unity.Mathematics;
public class SpawnerAuthoring : MonoBehaviour
{
public GameObject Prefab;
public float SpawnRate;
}
public struct Spawner : IComponentData
{
public Entity Prefab;
public float3 SpawnPosition;
public float NextSpawnTime;
public float SpawnRate;
}
public class SpawnerBaker : Baker
{
public override void Bake(SpawnerAuthoring authoring)
{
AddComponent(new Spawner
{
Prefab = GetEntity(authoring.Prefab),
SpawnPosition = authoring.transform.position,
NextSpawnTime = 0.0f,
SpawnRate = authoring.SpawnRate
});
}
}
using Unity.Entities;
using Unity.Transforms;
using Unity.Burst;
[BurstCompile]
public partial struct SpawnerSystem : ISystem
{
public void OnCreate(ref SystemState state) { }
public void OnDestroy(ref SystemState state) { }
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
foreach (RefRW
{
if (spawner.ValueRO.NextSpawnTime < SystemAPI.Time.ElapsedTime)
{
Entity newEntity = state.EntityManager.Instantiate(spawner.ValueRO.Prefab);
state.EntityManager.SetComponentData(newEntity, LocalTransform.FromPosition(spawner.ValueRO.SpawnPosition));
spawner.ValueRW.NextSpawnTime = (float)SystemAPI.Time.ElapsedTime + spawner.ValueRO.SpawnRate;
}
}
}
}
using Unity.Entities;
using Unity.Transforms;
using Unity.Burst;
[BurstCompile]
public partial struct SpawnerSystem : ISystem
{
public void OnCreate(ref SystemState state) { }
public void OnDestroy(ref SystemState state) { }
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
new ProcessSpawnerJob
{
ElapsedTime = SystemAPI.Time.ElapsedTime,
Ecb = SystemAPI.GetSingleton
}.ScheduleParallel();
}
}
[BurstCompile]
public partial struct ProcessSpawnerJob : IJobEntity
{
public double ElapsedTime;
public EntityCommandBuffer.ParallelWriter Ecb;
private void Execute([ChunkIndexInQuery] int chunkIndex, ref Spawner spawner)
{
if (spawner.NextSpawnTime < ElapsedTime)
Entity newEntity = Ecb.Instantiate(chunkIndex, spawner.Prefab);
Ecb.SetComponent(chunkIndex, newEntity, LocalTransform.FromPosition(spawner.SpawnPosition));
spawner.NextSpawnTime = (float)ElapsedTime + spawner.SpawnRate;
}
}
}
Entities包使用ECS架构组织代码和数据。entity是一个特殊字符,如同一个GameObject轻量的非托管替代。entity与其ID相关的component协同工作。与GameObject不同,entities不包含代码:他们是system处理数据的单元。
Component表示ECS架构的数据。Entities与Compnents协作,systems提供读写component数据的逻辑。本节将介绍ECS Components,并解释如何使用它们。
你项目里的数据通过Baking转化成entities和components。本节讲解Unity如何转换你的数据。
Baking提供一个系统,在Editor下转换GameObejct数据,在Runtime时写入EntitiyScene。
Baking可分解为多个部分,但核心是关键的两步:Bakers和Baking Systems。
当你打开一个SubScene并在其中编辑authoring物体时,Baking也会执行。
ECS会检测你正在进行的修改,并计算出完成这些变换所需Bakers的最小量。
这个结果在编辑或运行时会传递到Entity World。
Profiler模块
Journaling