創作內容

24 GP

【學習日誌】自己了弄個 ECS 8/14

作者:迷茫小呈│2021-08-14 17:46:34│巴幣:1,094│人氣:295
備審寫一寫還是忍不住手癢了,又去研究了一下 DOD,從頭用寫 ECS 架構做出簡單的遊戲 (簡單到連 game loop 都沒有)

之前有說過了 DOD 了,這次的重點也是在 ECS 上,所以稍微帶過 DOD

資料導向程式設計 Data Oriented Design
簡單來說就是透過改變資料結構的方式,減少 CPU 讀取資料時的快取未命中 cache miss,在巨量的遊戲實體中回收出可觀的效能。

基本上工廠類遊戲都得用這種方式做,光資料讀取時發生的大量 cache miss 就把效能拖垮ㄌ。
像異星工廠 factorio 就是開發者自己寫的 DOD 引擎 (沒記錯的話),

還有前陣子超強的那個戴森球計畫 dyson sphere program 就是在 Unity 裡自己搞 DOD,然後搭配 Compute Shader 用 CPU 並行 Update,所以遊戲才支撐的住 10 萬多個物件。

終於看的懂這張圖了ㄏㄏ

資料導向和物件導向差距很大,基本上相反了吧?
幹 DOD 是什麼有夠反人類的設計方法阿,現在看 OOP 真的有夠和藹

實體、組件、系統 Entity Component System
ECS 就是一種符合 DOD 規則的設計方法
  • 實體 Entity,組件的容器,不具有任何狀態與邏輯,基本上一個 int 存 index 就算 Entity 了
  • 組件 Component,儲存實體的各種狀態 State,像 Transform(position、rotation、scale)、RigidBody(mass、drag、velocity),但不具有邏輯和行為。這也是和常規 OOP 組件模式不同的地方。
  • 系統 System,行為和邏輯的部分就是 System 負責的,System 會尋找自己需要的組件,執行 Update 工作。系統自己也不會儲存任何狀態(變數),而系統與系統之間也不會互相溝通。
system have no state, component has no behaviour

與常規 OOP 不同的地方在於,OOP 通常都是一整條陣列存遊戲物件,然後
gameObject.Update()
{
    RigidBody.Update();
    Transform.Update();
    Renderer.Render();
}

ECS 變成用好幾條陣列個別存 Component,實體只是 index,更新會由 System 找出需要的組件,直線遍歷陣列。

ECS 模式有幾個好處
第一就是 DOD 的效能優勢,因為組件都擺在一起,資料結構的很緊湊,所以減少 cache miss 的的效能開銷 (但只有在實體數量大到一定量級才會顯現)

再來是並行有好,因為 System 不保存狀態,基本上同時對好幾個實體做 Update 也不會有問題。或是兩個需求 Component 不同的 System 也可以同時進行更新。

第三則是程式架構上的優勢,雖然 Component 裡所有變數都是 public 的,但 ECS 的架構方法不容易產生 OOP 那種亂七八糟的耦合。

缺點,主要都是 DOD 規範引起ㄉ
第一就是不夠直覺(DOD),OOP 之所以最廣泛就是因為他的邏輯相對貼近現實ㄌ

不允許多形(DOD),多型的抽象調用會產生 cache miss,但如果不要求效能應該沒差

再來是物件的生命週期不好處理...牽涉到一堆東東,我還沒辦法解釋難在哪裡

最後是溝通困難,實體之間要交互變的比較困難,畢竟規範嚴格...也可能是我還不夠熟悉吧

學藝不精,如果理解有有任何錯誤情麻煩指正 Orz

總之為了深入研究,我從頭搞了一個 ECS 架構的遊戲,參考 Unity ECS 的做法。弄了個躲球球的遊戲,光這樣就弄好幾天==


實體基本沿用 Unity GameObject,只是其他組件都用 ECS 模式做。然後我的組件和 MonoComponent 混用,要和 Unity Component 完全隔離太難ㄌ。

實體 EntityBase
兩個組件陣列,Unity 的和自己的,基本上是初始化要給 System 檢測用的,後續 Update 都不會從 Entity 接觸 Components



組件 IComponent
基本上就是繼承特定 intrface 的 struct,用來確保多型 <T> 不會吃到奇怪的東西。


系統 SystemBase
初始化的時候系統會掃過一次整個實體陣列,找哪些是要被自己更新的,然後存入 system 自己的的索引陣列。等更新的時候就根據 index array 跳著找A。



更新方法 GameEnities
比較尷尬的是我得手動建立每種組件的陣列,找不出適合的方法自動產生各種類型的陣列(如果要避免多型)


System 結果還是用多型搞ㄌ,我弄了一個可以用字串找出 subclass 的自訂編輯器,還可以排序執行順序。白色正常、黃色是重複、紅色是找不到 class



Update 的時候,就讓 System 照順序更新而已,比較大的問題還是 System 得和 GameEnities 直接接觸,不知道 Unity ECS 那個 Entities.Foreach(ref Component)是怎麼做到ㄉ

其實我原本想讓玩家可以射子彈ㄉ,但做不出來,所以免強改成敵人跑來跑去讓玩家躲的樣子
開始懂為甚麼 Unity DOTS 毛一堆了,有夠難做 ==

渲染和碰撞都還是用 unity 原生程式做的,除非自己完成這兩項,不然不可能和 monobehaviour 分離

專案放 github 上,有興趣自己看 code ㄅ

我覺得我該找時間整頓下我的 github

就醬
這陣子都在忙備審和主專案山鴨,一段時間沒研究新東西我整個人都不好了,所以搞了這東東來回復些能量

繼續寫備審 _(:3 」∠ )_

引用網址:https://home.gamer.com.tw/TrackBack.php?sn=5237859
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:Unity|遊戲開發

留言共 2 篇留言

矮鵝
你以後上大學考試的時候就可以像這些資工系的大學生一樣 : https://www.facebook.com/arbu.bhunkerzs/videos/230934532249580

08-14 21:31

迷茫小呈
笑死,成績 \|/08-14 22:44
KK
小呈加油!幫你集氣回復能量!你的文章也一直是我的動力來源。[e1]

08-24 18:28

迷茫小呈
一起加油 ><08-24 19:28
我要留言提醒:您尚未登入,請先登入再留言

24喜歡★angus945 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:【教學】距離場教學 結語... 後一篇:【閒聊】改變一下發日誌的...

追蹤私訊切換新版閱覽

作品資料夾

ki308431大家
歡迎參觀我的小屋,主要是美食開箱跟動漫推薦,歡迎留言交流或打個招呼YO~看更多我要大聲說昨天16:24


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】