ECS官方案例2. IJobForEach

中文版一圖讀懂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的過程是循序漸進的,註釋還算明瞭吧?
下面還是按照老規格理清一下思路好了!

小結

我們來對比案例一:

ECS Scripts 繼承
Entity RotationSpeedAuthoring_ForEach IConvertGameObjectToEntity
Component RotationSpeed_ForEach IComponentData
System RotationSpeedSystem_ForEach ComponentSystem

案例二:

ECS Scripts Inherit
Entity RotationSpeedAuthoring_IJobForEach IConvertGameObjectToEntity
Component RotationSpeed_IJobForEach IComponentData
System RotationSpeedSystem_IJobForEach JobComponentSystem

通過上面兩個對照表是不是理清開發思路了?區別在於System的迭代進化,充分利用了Jobs和Burst編譯器,因此會跑得更快!

DOTS 邏輯圖表

SystemBurstJobsEntity你好!任務交給你快速編譯一下?編譯好了,任務交給你安排執行?不好意思,你的旋轉已經排上日程了!轉起來,謝謝!我不想轉,謝謝!Oh,NO!旋轉,跳躍我閉着眼……SystemBurstJobsEntity

上面大概表現了幾者的關係,我是從表象上這麼理解的,至於底層怎麼弄的,I don‘t care。流程大體如下:

Data
Schedule
OnUpdate
Entity
Component
System
Burst
Jobs
ForEach

更新計劃

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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章