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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DOTS介绍+Unity DOTS-MAN小游戏项目实战

發(fā)布時(shí)間:2023/12/8 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DOTS介绍+Unity DOTS-MAN小游戏项目实战 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 前言
  • 一、1. What is DOTS and why we use it?
    • 1.DOTS包含的主要元素(三件套)
    • 2.Why we use it?
    • 3.Where we use it? (摘自Unity官方)
      • (1)對(duì)于AEC(工程建設(shè))應(yīng)用
      • (2) 對(duì)于汽車應(yīng)用
      • (3) 對(duì)于游戲獨(dú)立開發(fā)者和自由職業(yè)者
      • (4)對(duì)于游戲工作室
    • 4.DOTS的優(yōu)劣(機(jī)遇以及風(fēng)險(xiǎn))
      • 機(jī)遇
      • 風(fēng)險(xiǎn)
  • 二、DOTS-Man小游戲項(xiàng)目實(shí)戰(zhàn)
    • 1.環(huán)境配置
    • 2.游戲設(shè)計(jì)
      • 需求分析
    • 3.正式開發(fā)
      • 一些自帶腳本
      • Component
      • Mono Behaviour
      • System
    • 最后需要進(jìn)行的一些操作
    • 太棒啦!
  • 3. 參考文檔


前言

DOTS是Unity在17年左右提出的一個(gè)概念,其核心是ECS。


提示:以下是本篇文章正文內(nèi)容,下面案例可供參考

一、1. What is DOTS and why we use it?

全稱:(Multi-Thread)Data-Oriented-Tech-Stack
(多線程式)數(shù)據(jù)導(dǎo)向型技術(shù)堆棧

1.DOTS包含的主要元素(三件套)

  • 實(shí)體組件系統(tǒng)(ECS) - 提供使用面向數(shù)據(jù)的方法進(jìn)行編碼的框架。在Unity中它通過Entities軟件包進(jìn)行分發(fā),您可以通過Package Manager來添加編輯器。
  • C#作業(yè)系統(tǒng) (JobSystem)- 提供一種生成多線程代碼的簡(jiǎn)單方法。它通過Jobs軟件包進(jìn)行分發(fā)。
  • Burst編譯器 - 可生成快速、優(yōu)化的本機(jī)代碼。它通過Burst軟件包進(jìn)行分發(fā),可通過Package Manager在編輯器中使用。
  • 本機(jī)容器 - 屬于ECS數(shù)據(jù)結(jié)構(gòu),可提供對(duì)內(nèi)存的控制,值得注意的是Unity專門對(duì)內(nèi)存管理進(jìn)行了一部分優(yōu)化以降低MissCache。
  • 2.Why we use it?

  • 許多并行編程范式,尤其是SIMD(單指令多數(shù)據(jù))型范式,更傾向于使用SoA(結(jié)構(gòu)體數(shù)組)。在CUDA C編程中也普遍傾向于SoA,一維數(shù)據(jù)元素是為全局內(nèi)存的有效合并訪問而預(yù)先準(zhǔn)備好的,而相同內(nèi)存操作引用的同字段元素在存儲(chǔ)時(shí)時(shí)彼此相鄰的,使用SoA能夠顯著減少M(fèi)issCache。
  • 實(shí)體組件系統(tǒng)(ECS)提供了一種面向數(shù)據(jù)的編碼設(shè)計(jì)方法。利用面向數(shù)據(jù)的方法,可以對(duì)數(shù)據(jù)結(jié)構(gòu)加以組織,以免出現(xiàn)高速緩存未命中的情況,從而令隨后的數(shù)據(jù)訪問更加高效、快捷。由于面向?qū)ο蟮脑O(shè)計(jì)并不專注于數(shù)據(jù)的組織,因此高速緩存未命中的情況很常見,這樣就減慢了CPU訪問數(shù)據(jù)的速度,因?yàn)樗仨氼l繁地返回訪問主內(nèi)存中的數(shù)據(jù)。
  • C#作業(yè)系統(tǒng)可以輕松地用C#編寫快速、并行化的代碼,以充分利用當(dāng)今的多核處理器。
  • Burst編譯器會(huì)生成高度優(yōu)化的代碼,而這些代碼可以利用您要編譯的平臺(tái)硬件。
  • Tips:

  • jobsystem和ecs是兩個(gè)不同的東西,但是配合起來使用會(huì)有1+1>2的效果
  • burst與ecs的高度適配也使得ecs運(yùn)行效率很高
  • 3.Where we use it? (摘自Unity官方)

    除非您在尋求短期或中期的性能改進(jìn),否則很難判定是否需要過渡到DOTS或何時(shí)過渡到DOTS。
    DOTS幾乎可以為每個(gè)應(yīng)用程序帶來一定程度的性能改進(jìn)。這其中包括性能、電池使用壽命、迭代及項(xiàng)目可擴(kuò)展性。過渡到DOTS不會(huì)造成任何性能的下降,但評(píng)估過渡到DOTS所增加的費(fèi)用卻至關(guān)重要,尤其是對(duì)于那些僅帶來較小改進(jìn)的項(xiàng)目。
    對(duì)于所有應(yīng)用程序而言,DOTS適合處理大量數(shù)據(jù),例如開放式環(huán)境或使用大量相同材料的復(fù)雜結(jié)構(gòu)。通過在實(shí)例之間共享公共數(shù)據(jù)以減少內(nèi)存訪問,DOTS也同樣適用于重復(fù)的元素。
    DOTS將來會(huì)幫助您開發(fā)高質(zhì)量的內(nèi)容,而不使用DOTS的Unity卻很難做到,這一點(diǎn)務(wù)必要考慮清楚。例如,當(dāng)今的標(biāo)準(zhǔn)游戲和Unity項(xiàng)目已經(jīng)取代了過去的AAA游戲。放眼未來,您需要采用DOTS來保持競(jìng)爭(zhēng)力。
    針對(duì)不同的垂直行業(yè),DOTS可以適用于不同的解決方案:

    (1)對(duì)于AEC(工程建設(shè))應(yīng)用

    • DOTS適合處理大型數(shù)據(jù)集并確保內(nèi)容的可擴(kuò)展性。
    • DOTS非常適合進(jìn)行大型交互式地圖和具有大量模型和重復(fù)內(nèi)容(例如建筑物和道路)的環(huán)境設(shè)計(jì)。
    • DOTS適用于復(fù)雜的工程可視化,可大規(guī)模地模擬現(xiàn)實(shí)環(huán)境。例如,DOTS非常適合進(jìn)行粒度級(jí)工廠和基礎(chǔ)架構(gòu)設(shè)計(jì)。

    (2) 對(duì)于汽車應(yīng)用

    • 自動(dòng)駕駛的仿真和可視化
    • DOTS非常適合進(jìn)行大型交通和行人模擬,這需要成千上萬的志愿Agent以逼真的方式移動(dòng)和交互。

    (3) 對(duì)于游戲獨(dú)立開發(fā)者和自由職業(yè)者

    • DOTS可以幫助您減輕游戲中一些高成本操作的負(fù)擔(dān),并有助于提高性能,尤其是對(duì)于一些重復(fù)性進(jìn)程。
    • 許多輕量級(jí)游戲(例如用于移動(dòng)設(shè)備的游戲)并不能最大限度地提高硬件性能。即使有些游戲能夠做到這一點(diǎn),但這可能并不是它的主要關(guān)注點(diǎn)。不過,隨著游戲的不斷發(fā)展和硬件需求的持續(xù)增加,明智的做法是為將來使用DOTS做好準(zhǔn)備。同樣,Project Tiny也提供了使用DOTS開發(fā)較小應(yīng)用程序和游戲的解決方案。
    • 如果您沒有使用DOTS的迫切需求,那么最好先未雨綢繆,提高自己的DOTS技能,以便在DOTS成為Unity開發(fā)的標(biāo)準(zhǔn)方法時(shí)能夠整裝待發(fā)。

    (4)對(duì)于游戲工作室

    • 當(dāng)前格式的DOTS可以幫助您逐步達(dá)到Unity或其他方式所無法達(dá)到的規(guī)模和性能。具體而言,更長(zhǎng)的電池使用壽命、溫度控制以及DOTS所提供的代碼可重用性是其主要優(yōu)勢(shì)所在。這些方面的性能改進(jìn)還使您可以開發(fā)更多的低端設(shè)備,尤其是在西方市場(chǎng)以外的地區(qū),這些設(shè)備會(huì)受到一定的硬件限制。
    • 通過讓研發(fā)團(tuán)隊(duì)以DOTS開展工作,可以幫助您逐步了解所能采取的最佳方法,以及哪些最新的功能和領(lǐng)域最具性能優(yōu)勢(shì)和發(fā)展影響力。
    • DOTS并非要取代引擎團(tuán)隊(duì)的作用,而是讓工程師騰出更多精力在自己的專業(yè)領(lǐng)域(例如陰影或著色器)進(jìn)行創(chuàng)新。

    4.DOTS的優(yōu)劣(機(jī)遇以及風(fēng)險(xiǎn))

    在改善Unity項(xiàng)目的績(jī)效方面,DOTS有著巨大的潛力。 但是,在使用DOTS時(shí)需要做出一些考量,它們會(huì)影響到項(xiàng)目的時(shí)間表、預(yù)算和開發(fā)團(tuán)隊(duì)。以下是一些需要與項(xiàng)目?jī)?yōu)先事項(xiàng)進(jìn)行比較和對(duì)比的事項(xiàng)。這些事項(xiàng)可以歸類為風(fēng)險(xiǎn)與機(jī)遇。

    機(jī)遇

  • 改進(jìn)性能。默認(rèn)情況下,我們經(jīng)常使用“性能”一詞來描述DOTS。這是什么意思呢?借助面向數(shù)據(jù)的設(shè)計(jì)和多線程,DOTS可以顯著提升內(nèi)存、運(yùn)行時(shí)間和電池性能。隨著游戲中顯示的項(xiàng)目數(shù)量不斷增加,提高性能的潛力也隨之上升。相反,對(duì)于項(xiàng)目較少的游戲,您會(huì)發(fā)現(xiàn)游戲性能的改善程度卻不太明顯。
  • 代碼控制。隨著項(xiàng)目規(guī)模的不斷增大,DOTS可以更好地控制代碼的復(fù)雜性。為DOTS編寫的代碼通??梢愿玫胤蛛x關(guān)注點(diǎn)。因此,使用DOTS工作時(shí),代碼重構(gòu)、編寫單元測(cè)試以及在開發(fā)人員之間分配工作就變得更加容易。
  • 風(fēng)險(xiǎn)

  • 學(xué)習(xí)成本。如果您不熟悉DoD,那么面對(duì)DOTS時(shí)就會(huì)有一個(gè)學(xué)習(xí)曲線。盡管DoD在計(jì)算機(jī)科學(xué)領(lǐng)域有著良好的根基并已存在數(shù)年,而且DoD方法與OOP方法也有很大的不同,但DoD本質(zhì)上并不比OOP復(fù)雜。ECS是一種不同于當(dāng)前Unity MonoBehaviour方法的代碼體系架構(gòu),因此學(xué)習(xí)需要一定的時(shí)間。目前,我們認(rèn)為一名普通的Unity專業(yè)開發(fā)人員平均需要1個(gè)月才能熟練使用DOTS。這一準(zhǔn)備時(shí)間可以被使用DOTS時(shí)的代碼質(zhì)量和性能改進(jìn)所抵消。當(dāng)然,具體要取決于項(xiàng)目。
  • 有限支持。DOTS當(dāng)前僅與Unity中一組有限的功能兼容。 最終,DOTS將與Unity的所有功能完全兼容,但我們目前尚無實(shí)現(xiàn)完全兼容的時(shí)間表。不過,DOTS允許在單個(gè)項(xiàng)目中同時(shí)使用游戲?qū)ο蠛虳OTS,因此您可以將DOTS用于最頻繁的處理任務(wù),而將非DOTS Unity用于其余任務(wù)。
  • 過渡。如果之前的項(xiàng)目是基于Mono開發(fā),那么跟ECS之間的轉(zhuǎn)換可能比較簡(jiǎn)單,使用Unity自帶的一些Hybrid工具就可以較為簡(jiǎn)單的做到,但是想要把ECS轉(zhuǎn)化為目前常用的Mono的話,我們認(rèn)為可以做到,但是十分困難,而且也不建議這么做(為什么要嘗試把高效率轉(zhuǎn)為低效率呢)。目前比較推薦的是HybridECS開發(fā),ECS與Mono混合在一起,ECS再配合Jobsystem處理最需要多線程的那一部分。
  • 隨著時(shí)間的推移,晶體管電路逐漸接近性能極限,在摩爾定律逐漸失效的今天,人們面臨的數(shù)據(jù)也呈幾何倍數(shù)暴增,我們有理由去發(fā)明并且學(xué)習(xí)使用一種效率更高,更能完全發(fā)揮硬件性能的軟件編程方式,目前看來也許ECS也許能做到。

    二、DOTS-Man小游戲項(xiàng)目實(shí)戰(zhàn)

    想要熟悉DOTS以及ECS框架,最好還是要上手做一個(gè)小項(xiàng)目,使用部分基礎(chǔ)組件,想要熟悉以及精通還需要大量的練習(xí)以及使用,開發(fā)過程中要配合官方Entities文檔使用。
    Entities最新版本0.17的官方說明文檔

    1.環(huán)境配置

    • 如果是Unity2020.X以下版本:
    • windows -> package manager
    • advanced -> show preview package
    • install三件套 (Entities,Jobs,Burst)
    • install其他組件(Hybrid Renderer,Mathematics)

    • 如果是Unity2020.X及以上版本(推薦,作者使用2020.3.26f1c1):

      • 進(jìn)入package manager
      • 點(diǎn)擊 + 號(hào)點(diǎn)擊add package from gir url手動(dòng)添加三件套以及其他組件
        • com.unity.dots.editor
        • com.unity.physics
        • com.unity.entities
        • com.unity.rendering.hybrid

    2.游戲設(shè)計(jì)

    我們準(zhǔn)備做一個(gè)類似Pac-Man的小游戲,主要熟悉Physics包以及Entities的基本使用,所以不會(huì)開發(fā)怪物AI之類的,因?yàn)槭褂肈OTS開發(fā)所以就叫DOTS-MAN好了。

    需求分析

    主要功能有:玩家移動(dòng),鏡頭跟隨,分?jǐn)?shù)顯示,因?yàn)槿绻肊CS來修改UGUI的TEXT可能比較麻煩,這里選擇使用HybridECS開發(fā),使用MonoBehaviours開發(fā)一些基礎(chǔ)功能比如鏡頭跟隨以及物體生產(chǎn)之類。

    3.正式開發(fā)

    一些自帶腳本

    在開發(fā)過程中,因?yàn)槭占镆约巴婕疫€有地形之類的都要有碰撞,但是ECS無法使用object上面的collider之類的組件,所以就要用Entities包自帶的一些腳本。

    記得在掛Entities腳本之前刪掉不用的Object腳本,避免混淆以及無意義的空間占用

    把Object轉(zhuǎn)化成Entity的腳本:

    一般配合一起使用的腳本就是PhysicsShape和PhysicsBody,一個(gè)控制物理碰撞的類型,一個(gè)控制entity的物理性質(zhì)(例如重力之類的),各個(gè)屬性的作用都有明確說明:

    添加physicsbody之后碰到List越界報(bào)錯(cuò)問題解決方案:
    go into YOURPROJECTLibrary/PackageCache/
    copy com.unity.collections@0.15.0-preview.21 into YOURPROJECT/Packages/
    open com.unity.collections@0.15.0-preview.21\Unity.Collections\NativeList.cs
    change line 599 from Allocator.None to Allocator.Invalid

    Component

    組件只有三個(gè),兩個(gè)存儲(chǔ)分別存儲(chǔ)移動(dòng)和旋轉(zhuǎn)的速度,一個(gè)負(fù)責(zé)標(biāo)記收集物(所以里面沒有數(shù)據(jù))
    要記得把Serializable屬性改為GenerateAuthoringComponent,這樣把component掛上object之后就會(huì)把他變成entity。
    創(chuàng)建component和system都可以直接使用右鍵 -> create -> ECS進(jìn)行快速選擇自帶模板

    using Unity.Entities;[GenerateAuthoringComponent] public struct MoveComponent : IComponentData {public float moveSpeed; } using Unity.Entities;[GenerateAuthoringComponent] public struct RotationComponent : IComponentData {public float rotateSpeed; }

    Component配置:
    玩家:

    墻體和收集物:

    要注意在腳本中配置Collision Filter相關(guān)以及Collision Response相關(guān),即某個(gè)entity屬于哪個(gè)標(biāo)簽,他能與其他哪些標(biāo)簽的entity發(fā)生碰撞


    搭建一個(gè)使用場(chǎng)景(renderer相關(guān)的根據(jù)自己喜好來整):

    因?yàn)閙ono和ECS是相互穿插的,所以如果mono中有需要的system可以直接先去看看system的代碼,配合官方文檔理解為何這么做,這樣才能把整個(gè)流程梳理清楚(至少我學(xué)習(xí)的時(shí)候是這樣的)

    Mono Behaviour

    這里需要一個(gè)全局的mono behaviour來控制游戲,例如entity與object的連接,這里我們換一種方式,把之前的玩家小球弄成prefab,然后在這個(gè)全局mono控制玩家的生成,起名就叫做GameManager吧(具體說明看注釋):

  • GameManager:
  • using System.Collections; using UnityEngine; using Unity.Entities; using Unity.Mathematics; using Unity.Physics; using UnityEngine.UI; using Unity.Transforms;public class GameManager : MonoBehaviour {public static GameManager instance;public bool insaneMode;//在實(shí)體object世界中的prefabpublic GameObject ballPrefab;public GameObject cubePrefab;public Text scoreText;public int maxScore;public int cubesPerFrame;public float cubeSpeed = 3f;private int curScore;private Entity ballEntityPrefab;private Entity cubeEntityPrefab;private EntityManager entityManager;private BlobAssetStore blobAssetStore;//private bool insaneMode;private void Awake(){if (instance != null && instance != this){Destroy(gameObject);return;}instance = this;//初始化EntityManagerentityManager = World.DefaultGameObjectInjectionWorld.EntityManager;blobAssetStore = new BlobAssetStore();//從object世界獲得setting//即inspector中可以獲取的prefabGameObjectConversionSettings settings = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld, blobAssetStore);//通過GameObjectConversionUtility的ConvertGameObjectHierarchy來把object變成entity//參數(shù)(GameObject root, World dstEntityWorld)ballEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(ballPrefab, settings);cubeEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(cubePrefab, settings);}private void OnDestroy(){//重置BlobAssetStore中的blobasset緩存,釋放清空blobAssetStoreblobAssetStore.Dispose();}private void Start(){curScore = 0;insaneMode = false;//顯示分?jǐn)?shù),這個(gè)函數(shù)在每一幀都會(huì)調(diào)用DisplayScore();//創(chuàng)建初始球球SpawnBall();}private void Update(){//如果符合條件就開啟insanemode瘋狂造方塊,這里改成手動(dòng)開啟//if (!insaneMode && curScore >= maxScore)if (insaneMode){//開啟協(xié)程造方塊//insaneMode = true;StartCoroutine(SpawnLotsOfCubes());}}//回調(diào),造方塊IEnumerator SpawnLotsOfCubes(){while (insaneMode){//每一幀造cubesPerFrame量的方塊for (int i = 0; i < cubesPerFrame; i++){SpawnNewCube();}yield return null;}}void SpawnNewCube(){//使用entityManager造方塊并且給予屬性Entity newCubeEntity = entityManager.Instantiate(cubeEntityPrefab);Vector3 direction = Vector3.up;Vector3 speed = direction * cubeSpeed;PhysicsVelocity velocity = new PhysicsVelocity(){Linear = speed,Angular = float3.zero};//最后記得往entity添加component數(shù)據(jù)entityManager.AddComponentData(newCubeEntity, velocity);}public void IncreaseScore(){curScore++;DisplayScore();}private void DisplayScore(){scoreText.text = "Score: " + curScore;}//造第一個(gè)球void SpawnBall(){Entity newBallEntity = entityManager.Instantiate(ballEntityPrefab);Translation ballTrans = new Translation{//初始位置Value = new float3(0f, 0.5f, 0f)};//還是要記得添加componententityManager.AddComponentData(newBallEntity, ballTrans);//設(shè)置鏡頭跟隨的對(duì)象CameraFollow.instance.ballEntity = newBallEntity;} }
  • CameraFollow:
    相機(jī)跟隨的mono腳本:
  • using Unity.Entities; using Unity.Transforms; using Unity.Mathematics; using UnityEngine;public class CameraFollow : MonoBehaviour {public static CameraFollow instance;public Entity ballEntity;//設(shè)置一個(gè)偏移量用來調(diào)整相機(jī)位置public float3 offset;private EntityManager manager;private void Awake(){if (instance != null && instance != this){Destroy(gameObject);return;}instance = this;manager = World.DefaultGameObjectInjectionWorld.EntityManager;}private void LateUpdate(){if (ballEntity == null) { return; }Translation ballPos = manager.GetComponentData<Translation>(ballEntity);transform.position = ballPos.Value + offset;} }

    記得把相機(jī)腳本掛到main camera上!

    System

  • MoveSystem:
    控制玩家移動(dòng),獲取玩家輸入放入一個(gè)float2中,具體的Mathematics相關(guān)class可以看官方文檔,這是一個(gè)用起來比vector要快的東西(因?yàn)镋CS是數(shù)據(jù)驅(qū)動(dòng),不用特別關(guān)注object):
  • using Unity.Entities; using Unity.Jobs; using Unity.Mathematics; using Unity.Physics; using UnityEngine;public class MoveSystem : SystemBase {protected override void OnUpdate(){float deltaTime = Time.DeltaTime;float2 curInput = new float2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));Entities.ForEach((ref PhysicsVelocity vel, ref MoveComponent speedData) =>{float2 newVel = vel.Linear.xz;newVel += curInput * speedData.moveSpeed * deltaTime;vel.Linear.xz = newVel;}).Run();} }

    相關(guān)要點(diǎn):
    ForEach就是對(duì)包含參數(shù)相關(guān)Component的entity在每一幀都進(jìn)行一定的操作,其中ref關(guān)鍵字表示對(duì)數(shù)據(jù)進(jìn)行讀取也可以修改,而in關(guān)鍵字表示對(duì)數(shù)據(jù)只讀,而且in一定要全部放在ref后面。
    后面的的.Run()表示在主線程中運(yùn)行,如果要在子線程可以使用Schedule。

  • RotateSystem:
    控制收集物旋轉(zhuǎn)的system,具體的quaternion用法可以參考官方文檔:
  • using Unity.Entities; using Unity.Jobs; using Unity.Mathematics; using Unity.Transforms;public class RotateSystem : SystemBase {protected override void OnUpdate(){float deltaTime = Time.DeltaTime;Entities.ForEach((ref Rotation rotation, in RotationComponent rotationSpeed) =>{rotation.Value = math.mul(rotation.Value, quaternion.RotateX(math.radians(rotationSpeed.rotateSpeed * deltaTime)));rotation.Value = math.mul(rotation.Value, quaternion.RotateY(math.radians(rotationSpeed.rotateSpeed * deltaTime)));rotation.Value = math.mul(rotation.Value, quaternion.RotateZ(math.radians(rotationSpeed.rotateSpeed * deltaTime)));}).Run();} }

    記得這時(shí)候往你的object上面掛component!如果想讓玩家移動(dòng)就掛movecomponent,讓收集物旋轉(zhuǎn)就掛上rotationcomponent??梢韵胍幌?#xff0c;如果你往收集物上掛了movecomponent會(huì)發(fā)生什么?為什么會(huì)這樣?

    這時(shí)候你的收集物應(yīng)該是旋轉(zhuǎn)的,玩家小球可以通過wasd或者方向鍵控制移動(dòng):

    3. CollectSystem:
    然后就是最難的碰撞收集系統(tǒng)了!本來在mono中兩三行就可以解決的問題,現(xiàn)在要寫幾十行才能解決!但是對(duì)于后期優(yōu)化以及性能上的提升,這些困難都不算什么!
    相關(guān)的解釋說明都在注釋中了:

    using Unity.Entities; using Unity.Collections; using Unity.Physics; using Unity.Physics.Systems;[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))] public class CollectSystem : SystemBase { //用bufferSystem來處理這些碰撞事件private EndFixedStepSimulationEntityCommandBufferSystem bufferSystem;//初始化entity的物理世界private BuildPhysicsWorld buildPhysicsWorld;private StepPhysicsWorld stepPhysicsWorld;protected override void OnCreate(){bufferSystem = World.GetOrCreateSystem<EndFixedStepSimulationEntityCommandBufferSystem>();buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();}protected override void OnUpdate(){//每一幀都添加一個(gè)triggerjob來進(jìn)行碰撞判斷,因?yàn)樾枰袛嗟氖怯蠱oveComponent的玩家//以及有DeleteTag的收集物,所以就要在job中進(jìn)行選擇Dependency = new TriggerJob{speedEntities = GetComponentDataFromEntity<MoveComponent>(),entitiesToDelete = GetComponentDataFromEntity<DeleteTag>(),commandBuffer = bufferSystem.CreateCommandBuffer(),}.Schedule(stepPhysicsWorld.Simulation, ref buildPhysicsWorld.PhysicsWorld, Dependency);//把job傳遞到buffer中bufferSystem.AddJobHandleForProducer(Dependency);}//創(chuàng)建一個(gè)triggerjob來進(jìn)行碰撞處理private struct TriggerJob : ITriggerEventsJob{ //初始化處理的entitypublic ComponentDataFromEntity<MoveComponent> speedEntities;[ReadOnly] public ComponentDataFromEntity<DeleteTag> entitiesToDelete;public EntityCommandBuffer commandBuffer;public void Execute(TriggerEvent triggerEvent){TestEntityTrigger(triggerEvent.EntityA, triggerEvent.EntityB);TestEntityTrigger(triggerEvent.EntityB, triggerEvent.EntityA);}//處理碰撞,如果被碰撞的物品沒有DeleteTag,就把DeleteTag掛上去,移除它的物理組件private void TestEntityTrigger(Entity entity1, Entity entity2){if (speedEntities.HasComponent(entity1)){if (entitiesToDelete.HasComponent(entity2)) { return; }commandBuffer.AddComponent<DeleteTag>(entity2);commandBuffer.RemoveComponent<PhysicsCollider>(entity2);}}} }
  • DeleteSystem:
    控制刪除有deletetag的entity的system:
  • using Unity.Entities;[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))] //這里添加一個(gè)屬性,就是在collectionsystem發(fā)生之后再更新,因?yàn)橐扰鲎仓笤龠M(jìn)行處理 [UpdateAfter(typeof(CollectSystem))] public class DeleteSystem : SystemBase {private EndFixedStepSimulationEntityCommandBufferSystem _endSimulationECBSystem;protected override void OnStartRunning(){_endSimulationECBSystem = World.GetOrCreateSystem<EndFixedStepSimulationEntityCommandBufferSystem>();}protected override void OnUpdate(){var ecb = _endSimulationECBSystem.CreateCommandBuffer();Entities.WithAll<DeleteTag>().WithoutBurst().ForEach((Entity entity) =>{ //修改分?jǐn)?shù)GameManager.instance.IncreaseScore();ecb.DestroyEntity(entity);}).Run();_endSimulationECBSystem.AddJobHandleForProducer(Dependency);} }

    這里ForEach之前有一系列限定條件,比如.WithAll()的意思就是對(duì)帶有deletetag的entity執(zhí)行下面的操作,這樣能更加方便的進(jìn)行處理,所以大部分情況下entity都會(huì)被打一個(gè)標(biāo)簽來區(qū)別其他entity

    最后需要進(jìn)行的一些操作

    • 創(chuàng)建一個(gè)空物體放入GameManager,并且進(jìn)行相關(guān)配置(可以在play模式下打開insaneMode看看ECS的強(qiáng)大性能提升):
    • 在play模式下調(diào)整Camera中的相機(jī)跟隨參數(shù),讓鏡頭舒服:

    太棒啦!

    太棒啦!你成功的使用了目前領(lǐng)先的開發(fā)模式開發(fā)了一個(gè)小游戲,雖然這個(gè)小游戲的功能在mono中實(shí)現(xiàn)的話可以很簡(jiǎn)單的實(shí)現(xiàn),但是隨著工程規(guī)模的擴(kuò)大以及性能需求的提高,ECS只會(huì)愈發(fā)強(qiáng)大!因?yàn)槟壳癉OTS相關(guān)教程不完善,所以如果在上述開發(fā)中碰到問題主要需要參考官方文檔以及一些論壇大牛的解答,想要更深入的理解還需要更多項(xiàng)目的磨練。

    3. 參考文檔

    Entities最新版本0.17的官方說明文檔:
    https://docs.unity3d.com/Packages/com.unity.entities@0.17/api/Unity.Entities.html
    油管ECS大神Turbo的說明文檔:
    https://www.tmg.dev/tuts/roll-a-ball-entities-0-17/

    總結(jié)

    以上是生活随笔為你收集整理的DOTS介绍+Unity DOTS-MAN小游戏项目实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。