0下载Unity编辑器(2019.1.0f1 or 更新的版本),if(已经下载了)continue;
1下载官方案例,打开Git Shell输入:
git clone https://github.com/Unity-Technologies/EntityComponentSystemSamples.git --recurse
or 点击Unity官方ECS示例下载代码
if(已经下载了)continue;
2用Unity Hub打开官方的项目:ECSSamples
3在Assets目录下找到HelloCube/7. SpawnAndRemove,并打开SpawnAndRemove场景
上一个案例演示了如何使用实体来生成别的实体,那么有生成,自然就有移除,下面一起来一探究竟吧:
打开Spawner生成器的Inspector窗口,我们发现这个案例是建议在第六个之上的,因为它也是先将自身转化成实体,再生成别的实体。所以我们忽略相同之处,看不同的地方,也就是移除操作了。
因此移除操作就只能在LifeTimeSystem(生命周期系统)实现了,且看:
///
/// 生命周期,这里属于Component
///
public struct LifeTime : IComponentData
{
public float Value;
}
///
/// 这个系统负责场景中所有实体的生命周期
/// 也可以将其改装来负责特定实体的生命周期,添加刷选条件Filter即可
///
public class LifeTimeSystem : JobComponentSystem
{
///
/// 实体命令缓存系统--阻塞
///
EntityCommandBufferSystem m_Barrier;
///
/// 将阻塞缓存起来
///
protected override void OnCreate()
{
m_Barrier = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
}
[BurstCompile]//Burst加速编译器
struct LifeTimeJob : IJobForEachWithEntity<LifeTime>
{
public float DeltaTime;
[WriteOnly]//只写
public EntityCommandBuffer.Concurrent CommandBuffer;
///
/// 每帧执行,如果寿命 < 0 则摧毁实体
///
/// 实体
/// 任务索引
/// 寿命
public void Execute(Entity entity, int jobIndex, ref LifeTime lifeTime)
{
lifeTime.Value -= DeltaTime;
if (lifeTime.Value < 0.0f)
{
CommandBuffer.DestroyEntity(jobIndex, entity);
}
}
}
// OnUpdate runs on the main thread.
///
/// 在主线程上每帧运行OnUpdate
///
/// 输入依赖
/// 任务
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var commandBuffer = m_Barrier.CreateCommandBuffer().ToConcurrent();
var job = new LifeTimeJob
{
DeltaTime = Time.deltaTime,
CommandBuffer = commandBuffer,
}.Schedule(this, inputDependencies);
m_Barrier.AddJobHandleForProducer(job);
return job;
}
}
其实这里的写法和我们OOP的写法差不多的,只是我们写在Update里面而已,也没有利用到Jobs和Burst。
没有什么好讲的地方,寿命到了就摧毁实体,再简单不过了。
这里我们可以看到另外一个ECS的特性,那就是多组件,多系统同时协作。这和我们原来的开发模式差不多,把需要的脚本挂在对象上面执行,多个脚本之间不会互相干涉(如果解耦的话)
这里是彻底解耦了的,你在生命周期系统上的更改,对旋转系统并没有影响。如果实体摧毁了,那么对应的组件也不存在了,对应的系统自然也会停止工作。这些蝴蝶效应应该是自发的,因为没有多余的代码来做这个工作。
这个案例结合了案例二和案例六,因此都列出来了。
案例二:
ECS | Scripts | Interface |
---|---|---|
Entity | RotationSpeedAuthoring_IJobForEach | IConvertGameObjectToEntity |
Component | RotationSpeed_IJobForEach | IComponentData |
System | RotationSpeedSystem_IJobForEach | JobComponentSystem |
案例六:
ECS | Scripts | Interface1 | Interface2 |
---|---|---|---|
Entity | SpawnerAuthoring_FromEntity | IConvertGameObjectToEntity | IDeclareReferencedPrefabs |
Component | Spawner_FromEntity | IComponentData | |
System | SpawnerSystem_FromEntity | JobComponentSystem |
案例七:
ECS 1 | Scripts | Interface1 | Interface2 |
---|---|---|---|
Entity 1 | SpawnerAuthoring_SpawnAndRemove | IConvertGameObjectToEntity | IDeclareReferencedPrefabs |
Component1 | Spawner_SpawnAndRemove | IComponentData | |
System 1 | SpawnerSystem_SpawnAndRemove | JobComponentSystem |
ECS 2 | Scripts | Interface1 | Interface2 |
---|---|---|---|
Entity 2 | RotationSpeedAuthoring_SpawnAndRemove | IConvertGameObjectToEntity | |
Component2 | RotationSpeed_SpawnAndRemove | IComponentData | |
System 2 | RotationSpeedSystem_SpawnAndRemove | JobComponentSystem |
ECS 3 | Scripts | Interface1 | Interface2 |
---|---|---|---|
Entity 3 | RotationSpeedAuthoring_SpawnAndRemove | IConvertGameObjectToEntity | |
Component3 | LifeTime | IComponentData | |
System 3 | LifeTimeSystem | JobComponentSystem |
案例七并没有复用之前的ECS,而是独立创建了,其实脚本是大同小异的。通过对比,我们发现不同的组件和系统,可以共用同一个实体,就像表格ECS2和ECS3中所列出来的一样,它们共用了一个实体。
因此我查询了官方文档,发现ECS中实体+组件+系统三者之间并非缺一不可的关系,我发现实体是可有可无的,组件和系统因为实体而存在,却并不依赖它。这就是解耦,需要却并不依赖。
而实体却依赖组件,否则实体的数据没地方传递给系统,所以对于实体来说组件是必须的。
至于系统,实体可以不需要系统,组件也可以不需要系统,系统也可以当它们不存在,系统是完全解耦的。
Remove流程大体如下:
这个图画得有点乱,稍微废话解释一下,Entities把寿命通过LifeTime传给LifeTimeSystem来控制的,在生命周期系统中OnUpdate会在主线程上每帧执行发布新的LifeTimeJob任务,该任务会排到主线程的Schedule表上等待执行,每次的任务都会执行这样的判定,如果实体的寿命到了,那么就会把摧毁实体的命令缓存到CommandBuffer中。
那么CommandBuffer什么时候摧毁实体呢?CommandBuffer会在OnUpdate中传给LifeTimeJob任务,该任务会交给主线程。
执行的时机实际上由EntityCommandBufferSystem来掌控,通过AddJobHandleForProducer,最终的任务由阻塞(EntityCommandBufferSystem)和主线程协调。
大概是这样!
Spawn流程大体如下:
DOTS系统:
这一篇主要是多线程的地方要注意一下线程安全问题,其他的都是之前梳理过的。
如果喜欢我的文章可以点赞支持一下,谢谢鼓励!如果有什么疑问可以给我留言,有错漏的地方请批评指证!
如果有技术难题需要讨论,可以加入开发者联盟:566189328(付费群)为您提供有限的技术支持,以及,心灵鸡汤!
当然,不需要技术支持也欢迎加入进来,随时可以请我喝咖啡、茶和果汁!( ̄┰ ̄*)