你好,我是跟著大智學Unity的萌新,我叫小新,最近在探索DOTS。
由於ECS概念過於複雜,還是看看如何Code吧, 咱們先來看下如何編寫一個最簡單的ECS代碼。
這就又要從Hello World說起了。
首先需要把DOTS的環境搭好。本課程最開頭講了如何安裝Entities包,如果還沒安裝好需要去複習一下。
這個Hello World需要做什麼呢?咱們用ECS來控制一個Cube的旋轉。
ECS咱們已經知道了分三個部分,咱們來看看這三個部分如何創建。
按照和之前一樣的方法,在場景中創建一個Cube物體。
但這樣並不是ECS中的Entity,可以使用一個腳本[ConvertToEntity],將GameObject轉換成Entity。
這個腳本有一個屬性,ConversionMode: Convert And Destroy:將GameObject轉換成Entities,並且銷毀GameObject。 Convert And Inject GameObject:將GameObject轉換成Entities,保留GameObject。咱們在這選擇Convert And Destroy。這樣咱們就有了一個E,這時候如果你運行呢,你就會發現場景裡有一個Cube,但是在Hierarchy中看不到這個Cube。那如何查看這個Cube上面的信息呢?這時候需要使用Entity Debugger。打開方式是:Unity菜單欄Window > Analysis > Entitiy Debugger02 C:創建Component
下面來創建Component,這個Component和原來MonoBehaviour繼承的Component不是一個東西。
ECS中的Component需要使用一個結構體,實現 [IComponentData] 接口。
[GenerateAuthoringComponent]public struct RotationSpeed_ForEach : IComponentData{ // 旋轉的速度 public float RadiansPerSecond;}這個結構體中定義了一個float類型的數據,代表旋轉速度。
那上面的那個 [GenerateAuthoringComponent] 是做什麼的呢?
正常情況下,ECS中的Component並不能直接拖到物體上跟物體綁定。但是加了 [GenerateAuthoringComponent] 屬性後,可以將這個Component拖到GameObject上,並在腳本 [ConvertToEntity] 轉換時,自動將Component和轉換出來的Entities綁定。
現在寫好了就把這個RotationSpeed_ForEach組件添加到Cube上面吧。
03 S:用System控制Cube旋轉using Unity.Entities;using Unity.Mathematics;using Unity.Transforms;
public class RotationSpeedSystem_ForEach : SystemBase{ protected override void OnUpdate() { float deltaTime = Time.DeltaTime;
Entities .WithName("RotationSpeedSystem_ForEach") .ForEach((ref Rotation rotation, in RotationSpeed_ForEach rotationSpeed) => { rotation.Value = math.mul( math.normalize(rotation.Value), quaternion.AxisAngle(math.up(), rotationSpeed.RadiansPerSecond * deltaTime)); }) .ScheduleParallel(); }} 首先注意命名空間的引用,在ECS中並沒有引用比如 [UnityEngine] 這種在Mono中常見的命名空間。using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms; 實現一個class,繼承SystemBase,然後重寫父類SystemBase裡的 [OnUpdate] 方法。[OnUpdate] 方法和Mono中的Update方法類似,都是每幀執行一次,然們可以在裡面做更新的操作。
以下代碼用來獲取當前幀的時間,但是要注意這裡面的Time並不是[UnityEngine.Time] ,而是父類中定義的的Time。一定不要用混了。
float deltaTime = Time.DeltaTime;Entities.WithName僅僅是調試使用,調試信息或者Profiler中會顯示這個名字,方便你找到對應的代碼。
核心代碼是Entities.ForEach中的代碼,ForEach的參數是一個lambda匿名方法。其中ref的參數表示會寫入,in的參數表示是只讀的參數。注意這些參數的修飾一定要準確使用,這樣Job才能正確的判斷每種數據的用途。
ECS中有實體查詢(entity query),可以根據傳入的參數類型,找到所有同時擁有這些Component的實體。比如上面代碼就會找到同時擁有Rotation和RotationSpeed_ForEach組件的所有實體。
lambda中的方法執行具體的內容。在這需要注意需要使用新的數學庫 [Unity.Mathematics] 而不是原來的 [UnityEngine.Mathf] 。上面代碼中是用原來的旋轉,乘以需要旋轉的四元數,得到旋轉後的結果。
咱們場景中只有一個Cube,所以查詢到的Entity就只有一個。如果有多個Entity都符合條件,那麼這個System就可以同時處理這些Entity。
好了,到這咱們的ECS Hello World就完成了,但是其中很多代碼為什麼這麼寫,以及背後的原理都沒有講清楚。後面咱們詳細拆解一下每一部分代碼,掌握ECS的核心。
如果你喜歡本文的話,在官網 unity.cn 或 Unity Connect App 搜索關鍵詞「ECS」 就可以找到這篇文章,還可以收藏起來,慢慢學習哦。想要你的創意被更多人看見嗎?快快加入Unity社區,在社區內分享經驗,你也有機會獲得Unity官方推薦哦! 博客發布入口:unity.cn/articles - 「寫文章"
Unity線上技術大會將於11月16日盛大開啟,大咖精講Unity在遊戲、工業、傳媒娛樂三大領域的最前沿技術,報名即可免費參與。屆時,首屆MWU中國榜單年度獎項將於開幕式頒發,作品徵集10月30日截止。
長按關注
第一時間了解Unity引擎動向,學習最新開發技巧