Re: [請益] Unity想實現輕量化碰撞,發現效率輸內建
※ 引述《MasterDoggo (狗狗我的朋友)》之銘言:
: 因為遊戲內單位挺多的,想說可以不使用collision,做一個輕量化的碰撞功能
: 結果不管怎麼調整,效率都慘輸預設collider
: 還有索敵我原本也是想每段時間調用一次Physics.OverlapSphere搜索就好
: 但後來嘗試的結果也是不如一個Collider設置IsTrigger省事又有效率
: 像這類嘗試優化卻徒勞無功的狀況是經常發生的嗎?XD
: 我對優化沒有經驗,不太懂算法
: 這算是我第一次嘗試優化,板上大大有沒有什麼可以建議的呢
: 或者繼續調適內建collider就好?
: 這是我嘗試做的推開功能,只要OnTriggerEnter範圍內就賦予Rb.AddForce:
: https://i.imgur.com/WduPFDU.png
先說兩件事:
-無論什麼事情都是測數字才算數,所以我給的建議我沒測數字也不確定當參考就好
-這段程式中有太多微妙的寫法讓統一給改進建議很困難,我會流水帳點過去
總之輕鬆看過去參考就好:
32 行
看到你用 collidersToPush.Keys 應該代表你用的是 Dictionary?
Dictionary.Keys 的 forloop 遍歷速度很慢,要速度的時候不要用他。
實務上這邊的資料結構用法很奇怪,因為至少這段程式中你永遠都只指派 = true,而在離
開的時候直接用 Dictionary.RemoveKey。
這部分延伸到 62 行就變得很奇怪,因為既然這邊有 key 完全等於 true,實際上這個判
斷式是冗餘的。
建議改 List 或 Array 存就好,畢竟你只在乎有或沒有在清單裡面?
56 行
既然每個 PushAway 都要做一次時間判定,看起來時間也是全域的,而不是分開物件的,
應該把 56-58 行直接拿到 32 行前比較實際,就連進入 32 行的 forloop 都不用。
同時 Unity 其實會自動幫你修好所以不太需要在意,但這邊因為是 FixedUpdate 所以理
論上要用 Time.fixedTime 而不是 Time.time。
補充:其實看起來這邊應該寫法是本質上錯誤?
照你原本的寫法的話 collidersToPush 永遠只會推動第一個物件,剩下物件沒機會推到。
60、67 行
距離只要小於 0.7 就推的話,與其再另外 FixedUpdate 中判斷距離,從一開始就只搜索
這個距離範圍內比較合理。(球、圓形 Collider 設定半徑 0.7 或 OverlapSphere 直接
抓 0.7)
65 行
雖然在這邊沒到很重要,但 Vector3.magnitude 要多開根號。
用 Vector3.sqrMagnitude 不用開根號算起來比較快,量多的時候會影響不小
40 行
與其抓到 Collider 後假設可能會拿不到 Enemy 或 PlayerAlly,直接調整 Layer 確保只
有掛這兩個 Layer 的東西會判定到比較實際。
GetComponent 效能開銷不低盡量少做。
參考:
https://docs.unity3d.com/2022.3/Documentation/Manual/LayerBasedCollision.html
其他流水效能節省的碰撞判定方式提供參考的話大概這些:
-能假設物體是球或圓的碰撞範圍的話只要做距離判定就好,根本不用使用物理系統。甚
至如果物體根本就不在乎高度差的話做 XZ 的距離判定就好,省下一軸的計算。
-考慮你說的是 OverlapSphere,不確定你知不知道有 OverlapSphereNonAlloc,頻繁觸
發的話建議使用後者。寫法稍微不直覺一點點但因為不會每次都生成新的 Collider[],表
示比較不容易觸發 GC。不清楚 GC 是什麼的話參考:
https://docs.unity3d.com/6000.0/Documentation/Manual/
performance-garbage-collector.html
網址太長只能斷兩截......
-判斷目標真的很多的時候可以用 Spatial Hash Grid 做先抓大概有哪些有機會碰撞,再
只針對這些物體做精密碰撞判定(不過這 Unity 物理可能本身就有實作不確定)。
參考:https://youtu.be/sx4IIQL0x7c
然後一些關於最佳化的建議:
-先用乾淨好懂的寫法,等效能真的有瓶頸再考慮去做這些細緻的最佳化,早期就在做這
些最佳化反而干擾後續的開發順暢度,最後發現效能瓶頸根本不在這裡的話得不償失。尤
其考慮你的寫法應該代表你對 Unity 或者程式撰寫都還不夠熟練,先增加熟悉度再來考慮
繞過引擎功能去做更好就好。
精神上參考:https://youtu.be/NAVbI1HIzCE
基本上就是「先用方便的方式寫,但隨時注意留下可以改寫成更理想版本的空間」,但只
要還不是真的開發上有瓶頸就不要先過早動工處理。
-測試的時候要注意編輯器很可能會跟實際建出來的遊戲測出不同結果,不要太拘泥於編
輯器內測出的效能問題,除非干擾到開發。
例如說我隨便網路上查到有人做過相關測試:
https://www.reddit.com/r/Unity3D/comments/eye8yk/comment/fgh1tyn/
測出來編輯器內 Trigger 比較快,但是建出來反而比較慢。
-可以多使用 Profiler.BeginSample 跟 Profiler.EndSample 來標記效能測試範圍,能
明確看到每段程式的相對效能需求。要注意這個動作本身會帶來額外的效能開銷,所以要
注意解讀實際意義。
-補充:因為注意到推文中提起關於問 AI 這件事情,要小心問 AI 的時候的誘導性問句
問題(現行 AI 對話機器人相對容易肯定你的說法)。整體來說要自己寫出比 Unity 內建
更精省快速的物理計算是可行的,基本上就奠基於不做不必要的計算或假設性簡化。
而如果你問對問題的話,AI 確實可以給你正確答案:
https://chatgpt.com/share/67033fbb-8af0-800e-88e3-4a3cbf6bea67
同時老實說不建議不熟悉程式與 Unity 時做這麼細緻的程式處理時仰賴 AI,並不是要提
說 AI 不好,AI 給出正確答案的時候確實可以一口氣給出很大塊的正確的程式,但是前提
是自己要有能力驗證這個答案是對的。長遠下來反而容易造成程式架構的難以維護,也讓
其他人提供協助的難度大幅提升。
老實說我在巴哈就已經看過一次你的求救文,但因為要完整回答才能提供有效幫助,需要
點出的問題太多到回答的成本很高而放棄回覆,看到這篇才覺得不出來寫清楚不行。
大概這樣提供參考。
--
(開發中)《自動混亂》https://store.steampowered.com/app/1274830/
帶有部分類 Rogue 要素的極簡風雙搖桿射擊遊戲。
https://imgur.com/TQLbXfC.gif
(已推出)《自動混亂:零式》https://store.steampowered.com/app/1423670/
極簡風生存射擊遊戲,著重在 10 分鐘一場的極簡循環。
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.230.75.77 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/GameDesign/M.1728239503.A.0E3.html
留言