日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unity的Dots技术入门

發布時間:2023/12/8 编程问答 84 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity的Dots技术入门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

看過Dots技術宣傳片,當時確實被震驚到了,腦袋里閃過一句話:時代變了!大人。DOTS是Data-Oriented Technology Stack(數據導向的技術棧):借助Unity全新高性能多線程式數據導向型技術堆棧(DOTS),充分利用當今的多核處理器。游戲的運行速度會變得更快。

1.Unity的Dots由來

這種技術在游戲領域最先成功的案例來自守望先鋒,各位可以去看看《守望先鋒》架構設計與網絡同步,ECS全稱是Entity Component System,即實體、組件和系統。

  • 實體一般用途的對象,可以用唯一ID來標識。
  • 組件是一組數據,可以是實體一部分,也可以是實體和世界交互的中間數據(注意:沒有功能)。實體由若干組件組成的,否則它是空盒子。
  • 系統基于實體中的特定組件來實現特定功能,但是系統是集中批量處理所有的實體的。

ECS這種架構有什么好處呢?相比OOP方式實現Component,ECS中相同組件的數據是連續的,System集中處理這些組件,可以方便利用CPU Cache提升效率。由于System處理的可能是幾個組件,ECS將組件盡量的最小化(否則會有很多數據冗余),這樣就實現數據的扁平化。同時System間禁止相互調用,最大程度的實現代碼解耦。而OOP最被詬病的調用層次深,結構復雜等問題都被解決了。
Dots就是由實體組件系統(ECS)、任務系統(Job System)、Burst Compiler編譯器三部分組成。DOTS保證相同類型組件在內存中都是順序排列,極大程度增加緩存的命中率,此外配合任務系統(Job System)讓開發者無需頭疼多線程同時訪問數據需要手動加解鎖的麻煩,最終加持Burst Compiler讓性能飛起來。

2.與OOP編程對比

在對比之前,需要了解CPU相關概念:

  • 1.CPU處理數據速度非常快,內存條和硬盤跟不上它的速度。
  • 2.CPU自身有三級緩存,用來提高CPU獲取數據速度。n級緩存最快(n是1->3),但容量最小。
  • 3.內存是指CPU拿取數據的最開始的地方,CPU訪問內存速率遠小于三級緩存速率。
  • 4.CPU操作數據會從三級緩存中取得數據,速度非常快,但有些情況下數據不在三級緩存中(缺頁中斷),就需要尋址到內存中,并且把目標數據重新放到三級緩存中,提高下一次訪問速度。

很多傳統游戲引擎是基于面向對象來設計的,游戲世界中的東西都是對象(GameObject),每個對象都有叫做Update方法,游戲引擎遍歷所有對象,依次調用其Update方法。有些引擎甚至定義多種Update方法,在同一幀的不同時機去調用(Unity通過反射機制調用這些Update函數)。 OOP編程模式其實是有極大的缺陷的。因為游戲對象由很多部分聚合而成,引擎的功能模塊很多,不同模塊關注的部分往往互不相關。比如音效模塊數據并不需要關心物理碰撞數據、渲染模塊數據不關心游戲邏輯數據,對于某種模塊沒有必要的數據保存到CPU中,我們可以稱為垃圾數據。從自然意義上說,把游戲對象屬性聚合是很正常的事情,對象生命期管理也是最合理的方式。但這種對象大量存在時就會嚴重性能問題,接下來展示Unity的MonoBehaviour所繼承的Component子類。

其實MonoBehaviour繼承關系是這樣的,Behaviour->Component->Object,這些子類全部加起來的數據、屬性可不是以上這么點,有興趣可以進去看看這些子類都定義了什么數據、屬性、方法。MonoBehaviour對象過多會導致大量無用數據占據CPU的緩存(比如控制transform旋轉,里面卻有音效、物理、相機等等屬性),結論是傳統引擎的設計思路對CPU緩存不太友好導致利用率不高,出現CPU缺頁中斷情況會比較頻繁,下面給出圖解:

使用Ecs技術對CPU緩存利用率有質的提高,因為保存到CPU緩存的數據都比較純凈(ECS中的實體、組件),這樣可以有效降低CPU缺頁中斷,所以Dots相對于OOP編程有以下優點:

  • 1.ECS對CPU緩存友好,減少CPU缺頁中斷,防止CPU獲取數據慢,從而CPU出現等待情況。
  • 2.JobSystem編寫多線程代碼可以提供高性能,顯著提高幀速率和延長移動設備的電池壽命。
  • 3.Burst Compiler,用于生成高度優化的本地代碼。

3.Dots官方案例

拉取Unity官方案例AngryBots_ECS,博主使用Unity2020.2.0a打開案例工程,發現一大堆的問題和報錯(剩下渲染管線方面問題無法解決,但不影響運行),接下來分析如何一步步解決這些問題。首先是Hybrid Renderer版本問題,看報錯好像依賴了High Definition RP包(但是下載RP后還是不行),所以這里嘗試把Hybrid Renderer更新到最新的版本,于是第一個報錯就消失了。出現了以下報錯就和接龍一樣…Job System不存在OnCreateManager接口,可以進入到基類ComponentSystemBase里,發現了OnCreate生命周期函數,可以重寫它來代替報錯函數。World.Active去代替World.DefaultGameObjectInjectionWorld,可能Active是老版本的命名方式,GameObjectConversionUtility.ConvertGameObjectHierarchy接口所需參數也不一致,可以改成一下代碼段:

var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);manager = World.DefaultGameObjectInjectionWorld.EntityManager;bulletEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(bulletPrefab, settings);

最后TimeData.deltaTime改成大寫開頭即可,全部報錯改好后會發現運行時還有問題,可能是Burst Compiler的問題,重啟Unity后所有問題都得到解決了。
如果你終于走到這步,可能會很高興。但啟動游戲后會發現看不到子彈和敵人…不使用Ecs是可以看到子彈的,如下圖所示:

ps:莫名其妙死亡的話,只是看不到的敵人將主角殺死,上面說過可能是渲染管線的問題,經過在下長時間努力,大概知道問題所在了。嘗試Edit/Project Settings/Graphics下將Scriptable Render Pipeline Settings設置成none,可以看到一下畫面(可以看到子彈、敵人)。

具體解決方案不太清楚,如果有人知道麻煩下面留言,萬分感謝~
感覺GameObjectConversionSettings或Hybrid Rendering問題,但不知道如何修改。
案例演示視頻

4.實戰DOTS技術

使用Unity2020.2.0a創建新工程后,需要導入hybrid、entities(entities依賴jobs、burst),如下圖所示:低版本Unity可能不存在此文件,并且manifest.json也不存在jobs、burst這些依賴包,這時需要手動拉取。接下來講述下3種拉取方式:

  • 使用Package Manager拉取需要包(可能搜索不出來)。
  • 打開Package Manager后,窗口左上角有個加號,點開有三個選項Add package from xxx(有時低版本不出現Package Manager)。
  • 在manifest.json里添加兩個依賴包(最穩定的方法):
    “com.unity.entities”: “0.14.0-preview.18”,
    “com.unity.rendering.hybrid”: “0.8.0-preview.18”,

依賴包全部導入后,接下來先嘗試用DOTS技術寫多個Cube旋轉吧。

  • 1.創建旋轉方塊組件:
using Unity.Entities;public struct RotationCubeComponent : IComponentData {public float speed; }

注意必須是結構體,以后文章會分析為什么是結構體,如何才可以使用類,結構體比類的優點等等。

  • 2.創建旋轉方塊事件
using Unity.Entities; using Unity.Mathematics; using Unity.Transforms; using Unity.Jobs;public class RotationCubeSystem : SystemBase {protected override void OnUpdate(){float deltaTime = Time.DeltaTime;Entities.WithName("RotationCubeSystem").ForEach((ref RotationCubeComponent rotationSpeed, ref Rotation rotation) =>{rotation.Value = math.mul(math.normalize(rotation.Value),quaternion.AxisAngle(math.up(), rotationSpeed.speed * deltaTime));}).ScheduleParallel();} }

ScheduleParallel已經使用Job System多線程技術了,不使用多線程處理可以自行百度。

  • 3.創建實體管理器
using Unity.Entities; using UnityEngine;public class EntitiesManger : MonoBehaviour, IConvertGameObjectToEntity {public float FloCubeSpeed = 10f;public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem){var data = new RotationCubeComponent { speed = FloCubeSpeed };dstManager.AddComponentData(entity,data);} }

GameObject轉Entity,繼承IConvertGameObjectToEntity重寫Convert函數。

  • 4.批量生成實體
using Unity.Entities; using Unity.Mathematics; using Unity.Transforms; using UnityEngine;public class EntitiesBuilder : MonoBehaviour {public GameObject cube;void Start(){var settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, null);var prefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(cube, settings);var entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;for (var x = 0; x < 100; x++){for (var y = 0; y < 100; y++){var instance = entityManager.Instantiate(prefab);var position = transform.TransformPoint(new float3(x * 1.3F, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * 1.3F));entityManager.SetComponentData(instance, new Translation { Value = position });}}} }

將EntitiesManger和Convert To Entity掛載到Cube之后,制作成Prefab即可。然后將EntitiesBuilder隨便掛載到場景的物體。
具體原理分析和DOTS深度的東西后面文章會說明,至于官方案例子彈為什么不顯示,博主知道具體原因也會更新的。

5.總結

既然DOTS這么牛逼,為啥還沒普及?很簡單,DOTS現階段在完成度上就是接近廢品的殘次品,雖然經過Unity長達近三年的宣傳,DOTS到今天完成度依然極低,基本上處于不可用的狀態,一款游戲引擎必不可少的部分可簡單列為下面八個,要把Dots技術推動起來,游戲引擎要進行大量重構,或者保留傳統的MonoBehaviour將Dots技術插接進去,接下來看看Unity對這八大模塊完成情況。

  • Physics-3分?物理自然是游戲引擎不可或缺的部分,DOTS配套的Unity Physics處于非常早期的狀態,Authoring工具幾乎為零,甚至Joint或者CharacterConroller都要從Sample里找代碼,由于它提供了一套新的API,開發過程只能用極難使用來形容,來看看Trigger事件代碼就知道了,而使用過程中也是Bug層出不窮,經常會遇到類似Mesh Collider Bake錯誤,而與之同期宣傳的Havok Physics for Unity更是奇妙,在長達半年的時間里,只是單純引入Havok便會導致HDRP的渲染出問題.而更進階的布料、粒子、地形等也處于幾乎為零的狀態。
  • Graphics-3分?DOTS與之配套的是圖形系統是Hybrid Renderer,不過目前也只支持Mesh Renderer,什么Particle、Trail、VFX都還沒影兒,更可惜的是官方現在優先關注于HDRP兼容性(雖然也不怎么樣),URP或者Built-In Pipeline就基本別想了,遇到了問題也只能雙手一攤。
  • Audio-0分?Unity目前只開發了底層的 DSP 系統,上層的DOTS Audio說了一兩年了連影子都沒有,完成度接近于零。
  • Animation-0分?Unity Animation依然處于極早期的開發中,DOTS Sample展示了些最基本的使用,類似 Animator 這樣的高層方案現在還沒影兒。
  • Network-2分?也是Unity吹了兩年的東西,DOTS Sample中用的NetCode只不過把FPSSample中的部分代碼挪過去了,目前版本號 0.0.4,意思就是太早期了別用。
  • UI-0分?IMGUI,UI Element和UGUI三個Unity的產品均不支持DOTS。
  • AI-0分?Navmesh,Ml-Agent,Ai Planner三個Unity的產品均不支持DOTS。
  • Input-2分?老的Input System相對簡單與DOTS沒啥關系,可新的Input System居然也不支持DOTS,幸運的是InputSystem相對獨立,嫁接進DOTS并不困難。

對于游戲引擎模塊全部改成DOTS是有難度的,不然Unity公司對于DOTS支持程度就不是如此了(畢竟對游戲行業算是革命),在下大膽預言未來有某個天才或Unity公司完全實現了DOTS并且達到可以商用的地方,將會是巨大的利潤和商機。大家可能比較關心的是目前DOTS能不能接入游戲,只能說部分模塊可以使用(某些經典批處理場景),個人建議不要把還沒成型的技術接入到項目中,現在DOTS還有很多限制,知道有這個東西即可。參考資料和案例:DOTS開源案例、DOTS參考資料、DOTS實用案例

總結

以上是生活随笔為你收集整理的Unity的Dots技术入门的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。