ECS官方案例2. IJobForEach

31 篇文章 3 订阅

中文版一图读懂ECS

在这里插入图片描述

前言

在上一篇基于Unity2019最新ECS架构开发MMO游戏笔记0中讲了官方的第一个案例,通过图文并茂的分析,相信各位大佬已经对ECS有了一定的认识,这一篇会继续分析官方案例。
关于源码,如果有意想深入了解的,请看大鹏的专栏

官方案例解析2

开始之前的准备工作:
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/2. IJobForEach ,并打开IJobForEach 场景

2. IJobForEach

和第一个案例1. JobForEach中的场景一样,里面仅有四个游戏对象,那么这个案例究竟有啥子不同呢?下面一探究竟:

  • Main Camera ……主摄像机
  • Directional Light……光源
  • RotatingCube……旋转的方块
    • ChildCube……子方块

和案例1一样RotatingCube上同样挂了ConvertToEntity脚本,它将Unity的游戏对象GameObject转化成Entity,从而让游戏运行更加高效,脚本的工作原理已经在上一篇讲过了,此处跳过。
RotatingCube上还挂了另外一个脚本RotationSpeedAuthoring_IJobForEach,下面我们来看一下这个脚本:

   /// <summary>
/// 这就是ECS中的E了,它将数据交给C
/// </summary>
[RequiresEntityConversion]//必须实体转化
public class RotationSpeedAuthoring_IJobForEach : MonoBehaviour, IConvertGameObjectToEntity
{//继承接口IConvertGameObjectToEntity,并实现Convert
    public float DegreesPerSecond = 360;

    /// <summary>
    /// 这个方法上一篇讲过,通过该方法,实体将数据交给组件储存起来
    /// </summary>
    /// <param name="entity">实体</param>
    /// <param name="dstManager">目标实体管理器</param>
    /// <param name="conversionSystem">转化系统</param>
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        var data = new RotationSpeed_IJobForEach { RadiansPerSecond = math.radians(DegreesPerSecond) };
        dstManager.AddComponentData(entity, data);
    }
}

代码和上一篇的脚本RotationSpeedAuthoring_ForEach几乎一毛一样,区别在于IJob关键字上了,我猜后面一定会使用C#的Job系统,来充分利用多线程。按照流程,Entity把数据通过Convert方法传给Component组件了,下面我们来看RotationSpeed_IJobForEach 脚本:

/// <summary>
/// 我啥也不干,就放数据
/// </summary>
[Serializable]
public struct RotationSpeed_IJobForEach : IComponentData
{
    public float RadiansPerSecond;
}

这里提一下IComponentData,它就是一个空接口而已,作用只是表面自己是Component的身份,从而让System识别,非常纯粹的一个脚本。下面是这个案例的重点RotationSpeedSystem_IJobForEach:

// This system updates all entities in the scene with both a RotationSpeed_IJobForEach and Rotation component.
/// <summary>
/// 这里利用了Jobs和Burst编译器,它们和ECS共同组成DOTS,使代码运行更加高效
/// </summary>
public class RotationSpeedSystem_IJobForEach : JobComponentSystem 
{//通过继承JobComponentSystem来利用Jobs多线程的特性
    // Use the [BurstCompile] attribute to compile a job with Burst. You may see significant speed ups, so try it!
    [BurstCompile]//使用这个定语来利用Burst编译器,需要在Unity编辑器菜单栏Jobs-》Burst-》Enable Compilition来激活编译器
    struct RotationSpeedJob : IJobForEach<Rotation, RotationSpeed_IJobForEach>
    {
        public float DeltaTime;

        // The [ReadOnly] attribute tells the job scheduler that this job will not write to rotSpeedIJobForEach
        /// <summary>
        /// 该方法会在OnUpdate中每帧执行
        /// </summary>
        /// <param name="rotation">旋转</param>
        /// <param name="rotSpeedIJobForEach">[ReadOnly]定语告诉Jobs任务系统预定器这项任务不需要写入,这样会更快速</param>
        public void Execute(ref Rotation rotation, [ReadOnly] ref RotationSpeed_IJobForEach rotSpeedIJobForEach)
        {
            // Rotate something about its up vector at the speed given by RotationSpeed_IJobForEach.
            //Component的数据在这里使用,使方块旋转起来
            rotation.Value = math.mul(math.normalize(rotation.Value), quaternion.AxisAngle(math.up(), rotSpeedIJobForEach.RadiansPerSecond * DeltaTime));
        }
    }

    // OnUpdate runs on the main thread.
    /// <summary>
    /// OnUpdate在主线程上运行,上面写的旋转任务会在这里加入到计划当中
    /// </summary>
    /// <param name="inputDependencies">输入依赖</param>
    /// <returns></returns>
    protected override JobHandle OnUpdate(JobHandle inputDependencies)
    {
        var job = new RotationSpeedJob
        {
            DeltaTime = Time.deltaTime
        };

        return job.Schedule(this, inputDependencies);
    }
}

和第一个案例大同小异,不过更加先进了,从1到2的过程是循序渐进的,注释还算明了吧?
下面还是按照老规格理清一下思路好了!

小结

我们来对比案例一:

ECSScripts继承
EntityRotationSpeedAuthoring_ForEachIConvertGameObjectToEntity
ComponentRotationSpeed_ForEachIComponentData
SystemRotationSpeedSystem_ForEachComponentSystem

案例二:

ECSScriptsInherit
EntityRotationSpeedAuthoring_IJobForEachIConvertGameObjectToEntity
ComponentRotationSpeed_IJobForEachIComponentData
SystemRotationSpeedSystem_IJobForEachJobComponentSystem

通过上面两个对照表是不是理清开发思路了?区别在于System的迭代进化,充分利用了Jobs和Burst编译器,因此会跑得更快!

DOTS 逻辑图表

System Burst Jobs Entity 你好!任务交给你快速编译一下? 编译好了,任务交给你安排执行? 不好意思,你的旋转已经排上日程了! 转起来,谢谢! 我不想转,谢谢! Oh,NO! 旋转,跳跃 我闭着眼…… System Burst Jobs Entity

上面大概表现了几者的关系,我是从表象上这么理解的,至于底层怎么弄的,I don‘t care。流程大体如下:

Data
Schedule
OnUpdate
Entity
Component
System
Burst
Jobs
ForEach

更新计划

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主世界

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CloudHu1989

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值