ECS官方案例7. SpawnAndRemove

官方案例解析7

开始之前的准备工作:

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场景

7. SpawnAndRemove

上一个案例演示了如何使用实体来生成别的实体,那么有生成,自然就有移除,下面一起来一探究竟吧:

  • Main Camera ……主摄像机
  • Directional Light……光源
  • Spawner……旋转方块生成器

打开Spawner生成器的Inspector窗口,我们发现这个案例是建议在第六个之上的,因为它也是先将自身转化成实体,再生成别的实体。所以我们忽略相同之处,看不同的地方,也就是移除操作了。

  • 实体和案例六几乎一致,所以对应的Entity脚本SpawnerAuthoring_SpawnAndRemove就跳过了。
  • Component组件脚本Spawner_SpawnAndRemove也跳过,该脚本存储的数据和案例六几乎一致。
  • 实体生成实体的System和案例六一致,所以SpawnerSystem_SpawnAndRemove跳过。

因此移除操作就只能在LifeTimeSystem(生命周期系统)实现了,且看:

/// <summary>
/// 生命周期,这里属于Component
/// </summary>
public struct LifeTime : IComponentData
{
    public float Value;
}

/// <summary>
/// 这个系统负责场景中所有实体的生命周期
/// 也可以将其改装来负责特定实体的生命周期,添加刷选条件Filter即可
/// </summary>
public class LifeTimeSystem : JobComponentSystem
{
    /// <summary>
    /// 实体命令缓存系统--阻塞
    /// </summary>
    EntityCommandBufferSystem m_Barrier;

    /// <summary>
    /// 将阻塞缓存起来
    /// </summary>
    protected override void OnCreate()
    {
        m_Barrier = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    }

    [BurstCompile]//Burst加速编译器
    struct LifeTimeJob : IJobForEachWithEntity<LifeTime>
    {
        public float DeltaTime;

        [WriteOnly]//只写
        public EntityCommandBuffer.Concurrent CommandBuffer;

        /// <summary>
        /// 每帧执行,如果寿命 < 0 则摧毁实体
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="jobIndex">任务索引</param>
        /// <param name="lifeTime">寿命</param>
        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.
    /// <summary>
    /// 在主线程上每帧运行OnUpdate
    /// </summary>
    /// <param name="inputDependencies">输入依赖</param>
    /// <returns>任务</returns>
    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的特性,那就是多组件,多系统同时协作。这和我们原来的开发模式差不多,把需要的脚本挂在对象上面执行,多个脚本之间不会互相干涉(如果解耦的话)
这里是彻底解耦了的,你在生命周期系统上的更改,对旋转系统并没有影响。如果实体摧毁了,那么对应的组件也不存在了,对应的系统自然也会停止工作。这些蝴蝶效应应该是自发的,因为没有多余的代码来做这个工作。

小结

这个案例结合了案例二和案例六,因此都列出来了。
案例二:

ECSScriptsInterface
EntityRotationSpeedAuthoring_IJobForEachIConvertGameObjectToEntity
ComponentRotationSpeed_IJobForEachIComponentData
SystemRotationSpeedSystem_IJobForEachJobComponentSystem

案例六:

ECSScriptsInterface1Interface2
EntitySpawnerAuthoring_FromEntityIConvertGameObjectToEntityIDeclareReferencedPrefabs
ComponentSpawner_FromEntityIComponentData
SystemSpawnerSystem_FromEntityJobComponentSystem

案例七:

ECS 1ScriptsInterface1Interface2
Entity 1SpawnerAuthoring_SpawnAndRemoveIConvertGameObjectToEntityIDeclareReferencedPrefabs
Component1Spawner_SpawnAndRemoveIComponentData
System 1SpawnerSystem_SpawnAndRemoveJobComponentSystem
ECS 2ScriptsInterface1Interface2
Entity 2RotationSpeedAuthoring_SpawnAndRemoveIConvertGameObjectToEntity
Component2RotationSpeed_SpawnAndRemoveIComponentData
System 2RotationSpeedSystem_SpawnAndRemoveJobComponentSystem
ECS 3ScriptsInterface1Interface2
Entity 3RotationSpeedAuthoring_SpawnAndRemoveIConvertGameObjectToEntity
Component3LifeTimeIComponentData
System 3LifeTimeSystemJobComponentSystem

案例七并没有复用之前的ECS,而是独立创建了,其实脚本是大同小异的。通过对比,我们发现不同的组件和系统,可以共用同一个实体,就像表格ECS2和ECS3中所列出来的一样,它们共用了一个实体。
因此我查询了官方文档,发现ECS中实体+组件+系统三者之间并非缺一不可的关系,我发现实体是可有可无的,组件和系统因为实体而存在,却并不依赖它。这就是解耦,需要却并不依赖。
而实体却依赖组件,否则实体的数据没地方传递给系统,所以对于实体来说组件是必须的。
至于系统,实体可以不需要系统,组件也可以不需要系统,系统也可以当它们不存在,系统是完全解耦的。

DOTS 逻辑图表

Remove流程大体如下:

Value
lifeTime
Execute
New
Schedule
AddJobHandleForProducer
AddJobHandleForProducer
CreateCommandBuffer
DestroyEntity
Entities
LifeTime
LifeTimeSystem
LifeTimeJob
CommandBuffer
OnUpdate
主线程
EntityCommandBufferSystem

这个图画得有点乱,稍微废话解释一下,Entities把寿命通过LifeTime传给LifeTimeSystem来控制的,在生命周期系统中OnUpdate会在主线程上每帧执行发布新的LifeTimeJob任务,该任务会排到主线程的Schedule表上等待执行,每次的任务都会执行这样的判定,如果实体的寿命到了,那么就会把摧毁实体的命令缓存到CommandBuffer中。
那么CommandBuffer什么时候摧毁实体呢?CommandBuffer会在OnUpdate中传给LifeTimeJob任务,该任务会交给主线程。
执行的时机实际上由EntityCommandBufferSystem来掌控,通过AddJobHandleForProducer,最终的任务由阻塞(EntityCommandBufferSystem)和主线程协调。
大概是这样!
Spawn流程大体如下:

DeclareReferencedPrefabs
Convert
ConvertGameObjectHierarchy
Execute
Instantiate
SetComponent
Spawner
Prefab
SpawnerEntity
PrefabEntity
CommandBuffer
Entities
DOTS

DOTS系统:

Data
Schedule
OnUpdate
Entities
Component
System
Burst
Jobs
ForEach
System Burst Jobs Entities 你好!任务交给你快速编译一下? 编译好了,任务交给你安排执行? 不好意思,你们的旋转已经排上日程了! 全体都有,集合,向右看齐,向前看,转起来! 我们不想转,我们要放假! 又转起来了! 为什么会说“又”? 旋转,跳跃 我闭着眼…… System Burst Jobs Entities

这一篇主要是多线程的地方要注意一下线程安全问题,其他的都是之前梳理过的。

更新计划

Mon 12 Mon 19 Mon 26 1. ForEach 2. IJobForEach 3. IJobChunk 4. SubScene 5. SpawnFromMonoBehaviour 6. SpawnFromEntity 7. SpawnAndRemove 休息 修正更新计划 参加表哥婚礼 进阶:FixedTimestepWorkaround 进阶:BoidExample 进阶:SceneSwitcher 我是休息时间 资源整合 部署服务器 启动流程 登录流程 游戏主世界 待计划 待计划 待计划 待计划 待计划 我是休息时间 待计划 待计划 待计划 待计划 待计划 我是休息时间 读取Excel自动生成Entity 读取Excel自动生成Component 读取数据库自动生成Entity 读取数据库自动生成Component ESC LuaFrameWork Skynet DOTS 官方示例学习笔记 -----休息----- 基于ECS架构开发MMO学习笔记 LuaFrameWork学习笔记 -----休息----- 基于Skynet架构开发服务器学习笔记 制作代码自动生成工具 总结 基于Unity2019最新ECS架构开发MMO游戏笔记

作者的话

AltAlt

如果喜欢我的文章可以点赞支持一下,谢谢鼓励!如果有什么疑问可以给我留言,有错漏的地方请批评指证!
如果有技术难题需要讨论,可以加入开发者联盟:566189328(付费群)为您提供有限的技术支持,以及,心灵鸡汤!
当然,不需要技术支持也欢迎加入进来,随时可以请我喝咖啡、茶和果汁!( ̄┰ ̄*)

ECS系列目录

ECS官方示例1:ForEach

ECS官方案例2:IJobForEach

ECS官方案例3:IJobChunk

ECS官方案例4:SubScene

ECS官方案例5:SpawnFromMonoBehaviour

ECS官方案例6:SpawnFromEntity

ECS官方案例7:SpawnAndRemove

ECS进阶:FixedTimestepWorkaround

ECS进阶:Boids

ECS进阶:场景切换器

ECS进阶:MegaCity0

ECS进阶:MegaCity1

UnityMMO资源整合&服务器部署

UnityMMO选人流程

UnityMMO主世界

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页