1概述
先用一張簡要的模組圖來幫助大家了解遊戲架構設計,了解物件管理在架構中所處的位置和他的作用是。實際的模組圖會比本圖的內容詳細,並且對模組的分割有其他的方式,這張圖只是為了幫助大家了解物件管理,做了很多精簡。
要想講清楚物件管理,還得從下層的「資源管理器」說起。
1.1資源管理
資源管理主要有兩個重要的功能:資源載入和資源釋放。
資源載入指的是把需要的資源(如prefab,材質,貼圖等,從磁碟載入到記憶體中),供上層模組呼叫。這些資源通常以某種形式進行打包。unity3d通常是用assetbundle打包。舉例來說,想在遊戲中顯示乙個角色需要的資源就是穿過多個模組後,最後達到資源管理模組,從這裡獲得。
資源釋放是與其對應的,就是把不用的資源從記憶體中解除安裝。那問題來了,什麼時候資源什麼時候不用?通常有兩種情形。場景切換和角色不在螢幕時。難道此時我們就應該把資源從記憶體中釋放?這樣做也不是不可以,但這樣就意味著做出來的遊戲是低效的。腦補下策劃,製作人的表情:) 道理很簡單,角色是非常常見的,如果每次不用了就從記憶體釋放,那就意味著每次用的時候都要從磁碟載入。這樣就引出了物件管理這個概念。
1.2 物件管理
物件管理是資源管理和上層模組的乙個中間層,快取。他主要為那些暫時不用的資源提供記憶體快取作用。角色首次需要的時候確實從資源管理從獲取,並且快取在物件管理中,暫時不用時不從資源管理器釋放,而是由物件管理來接管。當下次再用的時候,就從物件管理來取角色。都是在記憶體中,速度自然比從資源管理中快。
2 物件管理模組設計
既然作為快取,那當然對速度有要求。比如場景中需要10個相同的npc,那麼我們快取乙個npc顯然是不夠的,而是需要多個。不然物件管理的世界意義就會大打折扣。多個重複的物件(npc),這種情形下,「物件池」出場了。物件池就是用於儲存重複物件的。
npc可能有多種,「物件池」就會有多個。既然是多個物件池,就需乙個「物件池管理器」來管理這些「物件池」。比如npc分為npc1....npcn,那麼就會有n個物件池。我們不太可能遍列這些物件池。而是需要提供o(1)的查詢效率,找到對應的物件池。在c#裡採用dictionary這個資料結構是最合適的了。他的key就是「物件池」的名字(或者是型別),value就是物件池的指標。而持有這個dictionary的就是物件池管理器。
物件從哪個「物件池」取的問題貌似就解決了。那找到了對應的「物件池」,那怎麼以o(1)的效率從「物件池」中找到物件呢?我們還是採用dictionary這個資料結構。因為在客戶端顯示的npc都是在伺服器中有唯一編號的,entityid(事實上player也是)。他是乙個唯一的編號,通常是個int或者無符號的int型別的值。是伺服器和客戶端雙方都認可的,而且雙方還約定了型別。也就是還有乙個entitytype.這個entitytype就是拿來對應物件池名字的。通過entitytype,找到對應的物件池,然後通過entityid找到對應物件。
無論是本圖和上圖都乙個叫「快取」的模組。這究竟是怎麼回事?事實上是,整個物件管理除了「物件池管理器」和「物件池」之外,還有「快取」。"物件池"和「快取」都是儲存重複物件的,但他們兩點本質的區別。
第一,「快取」中的物件是已經被用過的(分配了entityid),用於相同物件(entityid)相同的物件可以重複使用。而「物件池」中的物件可能是被用過的,也可能沒被用過。當上層邏輯暫時不用時,是把物件還給「物件池」,而避免下次使用同型別的物件從資管管理器中從磁碟讀取。當物件被還給「物件池」時,物件上雖然有entityid,但他是無效的。舉例來說,當乙個「坦克1」物件第一次被伺服器發出指令出現在螢幕上,做出乙個「攻擊」動作。那麼「坦克1」是從「物件池」取到「快取」中,然後取出,執行「攻擊」。如果伺服器又發出指令要求「坦克1」做出乙個「受擊」動作。這時「坦克1」是直接從「快取」中取出,做出受擊動作。如果「坦克1」過一會兒,移動出螢幕了,這時需要把「坦克1」從「快取」移除,並還回「物件池」。然後這時伺服器要求「坦克2」做出執行「攻擊」。這個「坦克2」除了enityid和之前的「坦克1」不同之外,其他都一樣。那麼這時從「物件池」中取出的物件,很有可能是之前用過的「坦克1」。沒關係,我們把他的entityid重新賦值即可。「快取」和「物件池」兩者配合,就實現真正的物件重複使用。也可以簡單理解,快取中的物件是遊戲中正在活動的物件,有身份證的(entityid),而物件池中的物件是預先從資源管理中讀取的物件,要麼沒有身份證,要麼身份證已經過期。
第二,兩者的資料結構不同。「快取」中的物件是存在以entityid為key儲存的dictionary中。而「物件池」不能用dictionary儲存。因為「物件池」種物件必須是當前沒有使用的。相當於有個狀態。而且這個狀態只有兩個取值,要麼正在被用,要麼沒有用。那他到底採用什麼樣的資料結構呢?先買個關子,下篇再講。下面是物件資料的時序圖,比上面的流程圖更容易看懂整個過程。重要的是先訪問「快取」再訪問「物件池」。
使用 Unity 3D 開發遊戲的架構設計難點
unity 3d 引擎對於開發者來說,入手非常快,因為它採用的是 c 作為開發語言,這也大大降低了開發者的門檻。但凡只要懂一門程式語言的人都能使用 unity 3d 引擎開發,另外 unity 3d 的內部架構設計非常好,採用的是元件開發,開發者能快速通過元件堆積出乙個遊戲。既然使用 unity 3...
使用 Unity 3D 開發遊戲的架構設計難點
unity 3d 引擎對於開發者來說,入手非常快,因為它採用的是 c 作為開發語言,這也大大降低了開發者的門檻。但凡只要懂一門程式語言的人都能使用 unity 3d 引擎開發,另外 unity 3d 的內部架構設計非常好,採用的是元件開發,開發者能快速通過元件堆積出乙個遊戲。既然使用 unity 3...
使用 Unity 3D 開發遊戲的架構設計難點
unity 3d 引擎對於開發者來說,入手非常快,因為它採用的是 c 作為開發語言,這也大大降低了開發者的門檻。但凡只要懂一門程式語言的人都能使用 unity 3d 引擎開發,另外 unity 3d 的內部架構設計非常好,採用的是元件開發,開發者能快速通過元件堆積出乙個遊戲。既然使用 unity 3...