ECS官方案例3. IJobChunk

官方案例解析3

開始之前的準備工作:
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/3. IJobChunk ,並打開IJobChunk 場景

3. IJobChunk

這個案例演示了基於Jobs的ECS系統如何旋轉一對方塊兒,與同樣使用Jobs系統的案例2不同的是,在循環遍歷的時候,前者迭代的是實體,而這個案例迭代的是塊(內存塊,這個塊是被一開始基於相同原型分配好了的,也就是說,如果這20個實體有相同的組件,那麼他們會被緊密的安排在一塊內存中,從而方便處理器進行操作。這是相對於面向對象的散列內存而言的,在面向對象中要操作內存中的某個對象時,你不得不在整個內存中尋找它,這樣會降低讀取速度,也不方便批量操作。ECS則會非常緊密地分配實體在內存中的位置,相同的組件會被統一放在塊中,讀取速度快,也方便批量操作)。下面來一探究竟:

  • Main Camera ……主攝像機
  • Directional Light……光源
  • RotatingCube……旋轉的方塊
    • ChildCube……子方塊

和案例2一樣RotatingCube上同樣掛了ConvertToEntity腳本,它將Unity的遊戲對象GameObject轉化成Entity,從而讓遊戲運行更加高效,腳本的工作原理已經在上一篇講過了,此處跳過。
RotatingCube上還掛了另外一個腳本RotationSpeedAuthoring_IJobChunk,下面我們來看一下這個腳本:

[RequiresEntityConversion]
public class RotationSpeedAuthoring_IJobChunk : MonoBehaviour, IConvertGameObjectToEntity
{
    public float DegreesPerSecond = 360.0F;
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        var data = new RotationSpeed_IJobChunk { RadiansPerSecond = math.radians(DegreesPerSecond) };
        dstManager.AddComponentData(entity, data);
    }
}

代碼和上一篇的腳本RotationSpeedAuthoring_IJobForEach幾乎一毛一樣,區別在於Chunk關鍵字上了,我這裏略過儲存數據的RotationSpeed_IJobChunk腳本不講,實在沒有什麼可說的,就儲存了一個數據而已:

/// <summary>
/// 我啥也不幹,就放數據
/// </summary>
[Serializable]
public struct RotationSpeed_IJobChunk : IComponentData
{
    public float RadiansPerSecond;
}

這裏的IComponentData上次講過,它就是一個空接口而已,作用只是表明自己是Component的身份,從而讓System識別,非常純粹的一個腳本。這裏我們將理解到表明身份的重要性,下面是這個案例的重點腳本RotationSpeedSystem_IJobChunk:

/// <summary>
/// 按塊操作實體系統
/// </summary>
public class RotationSpeedSystem_IJobChunk : JobComponentSystem
{
    EntityQuery m_Group;//查詢到特定組件的實體,將其放入這個組中

    /// <summary>
    /// 這裏根據類型來查詢到特定的實體
    /// </summary>
    protected override void OnCreate()
    {
        // Cached access to a set of ComponentData based on a specific query
        ///typeof(Rotation)=帶有Rotation組件的;ComponentType=對應RotationSpeed_IJobChunk組件類型的
        /// ReadOnly=只讀會加快獲取實體的速度,ReadWrite=讀寫 則相對較慢
        m_Group = GetEntityQuery(typeof(Rotation), ComponentType.ReadOnly<RotationSpeed_IJobChunk>());
    }

    // Use the [BurstCompile] attribute to compile a job with Burst. You may see significant speed ups, so try it!
    [BurstCompile]//同樣使用Burst編譯器來加速,區別是使用了塊接口:IJobChunk
    struct RotationSpeedJob : IJobChunk
    {
        public float DeltaTime;
        /// <summary>
        /// 原型塊組件類型=Rotation
        /// </summary>
        public ArchetypeChunkComponentType<Rotation> RotationType;
        /// <summary>
        /// 只讀 原型塊組件類型=RotationSpeed_IJobChunk
        /// </summary>
        [ReadOnly] public ArchetypeChunkComponentType<RotationSpeed_IJobChunk> RotationSpeedType;
        /// <summary>
        /// 找出滿足條件的實體來執行
        /// </summary>
        /// <param name="chunk"><原型塊/param>
        /// <param name="chunkIndex">塊索引</param>
        /// <param name="firstEntityIndex">第一個實體索引</param>
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var chunkRotations = chunk.GetNativeArray(RotationType);
            var chunkRotationSpeeds = chunk.GetNativeArray(RotationSpeedType);
            for (var i = 0; i < chunk.Count; i++)
            {
                var rotation = chunkRotations[i];
                var rotationSpeed = chunkRotationSpeeds[i];

                // Rotate something about its up vector at the speed given by RotationSpeed_IJobChunk.
                chunkRotations[i] = new Rotation
                {
                    Value = math.mul(math.normalize(rotation.Value),
                        quaternion.AxisAngle(math.up(), rotationSpeed.RadiansPerSecond * DeltaTime))
                };
            }
        }
    }

    // OnUpdate runs on the main thread.
    /// <summary>
    /// 這個方法在主線程上運行
    /// </summary>
    /// <param name="inputDependencies">輸入依賴</param>
    /// <returns></returns>
    protected override JobHandle OnUpdate(JobHandle inputDependencies)
    {
        // Explicitly declare: 聲明
        // - Read-Write access to Rotation 讀寫的方式訪問旋轉
        // - Read-Only access to RotationSpeed_IJobChunk 只讀的方式訪問旋轉速度
        var rotationType = GetArchetypeChunkComponentType<Rotation>();
        var rotationSpeedType = GetArchetypeChunkComponentType<RotationSpeed_IJobChunk>(true);

        var job = new RotationSpeedJob()
        {
            RotationType = rotationType,
            RotationSpeedType = rotationSpeedType,
            DeltaTime = Time.deltaTime
        };

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

思路是明確的,一個案例比之前一個更快,切更有目的性!
這就是代碼的優化迭代!

小結

我們來對比案例二:

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

和案例三:

ECS Scripts Inherit
Entity RotationSpeedAuthoring_IJobChunk IConvertGameObjectToEntity
Component RotationSpeed_IJobChunk IComponentData
System RotationSpeedSystem_IJobChunk JobComponentSystem

變化不大,System都利用了Jobs和Burst編譯器,Chunk會跑得更快!

DOTS 邏輯圖表

SystemBurstJobsEntities你好!任務交給你快速編譯一下?編譯好了,任務交給你安排執行?不好意思,你們的旋轉已經排上日程了!全體都有,集合,向右看齊,向前看,轉起來!我們不想轉,我們要放假!又轉起來了!爲什麼會說“又”?旋轉,跳躍我閉着眼……SystemBurstJobsEntities

流程大體如下:

Data
Schedule
OnUpdate
Entities
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主世界

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章