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的特性,那就是多组件,多系统同时协作。这和我们原来的开发模式差不多,把需要的脚本挂在对象上面执行,多个脚本之间不会互相干涉(如果解耦的话)
这里是彻底解耦了的,你在生命周期系统上的更改,对旋转系统并没有影响。如果实体摧毁了,那么对应的组件也不存在了,对应的系统自然也会停止工作。这些蝴蝶效应应该是自发的,因为没有多余的代码来做这个工作。

小结

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

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中实体+组件+系统三者之间并非缺一不可的关系,我发现实体是可有可无的,组件和系统因为实体而存在,却并不依赖它。这就是解耦,需要却并不依赖。
而实体却依赖组件,否则实体的数据没地方传递给系统,所以对于实体来说组件是必须的。
至于系统,实体可以不需要系统,组件也可以不需要系统,系统也可以当它们不存在,系统是完全解耦的。

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
SystemBurstJobsEntities你好!任务交给你快速编译一下?编译好了,任务交给你安排执行?不好意思,你们的旋转已经排上日程了!全体都有,集合,向右看齐,向前看,转起来!我们不想转,我们要放假!又转起来了!为什么会说“又”?旋转,跳跃我闭着眼……SystemBurstJobsEntities

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

更新计划

Mon 12Mon 19Mon 261. ForEach 2. IJobForEach 3. IJobChunk 4. SubScene 5. SpawnFromMonoBehaviour 6. SpawnFromEntity 7. SpawnAndRemove 休息修正更新计划参加表哥婚礼进阶:FixedTimestepWorkaround进阶:BoidExample进阶:SceneSwitcher我是休息时间 资源整合 部署服务器 启动流程 登录流程 游戏主世界 待计划 待计划 待计划 待计划 待计划 我是休息时间 待计划 待计划 待计划 待计划 待计划 我是休息时间 读取Excel自动生成Entity 读取Excel自动生成Component读取数据库自动生成Entity读取数据库自动生成ComponentESC 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主世界

发布了37 篇原创文章 · 获赞 30 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览