Unity學習記錄/ #5 工廠模式與對象池
一、前言
????Hello大家好,這里是我的Unity學習簡單筆記,前4期專欄都是講到了一些Unity內(nèi)置的功能,所以這期想來寫寫有關于游戲編程設計模式的東西。
????程序員為什么需要設計模式呢?簡單來說,我們的游戲需要 架構 和 性能。這就像整理你的房間一樣,你總不能讓你的游戲架構和你的房間一樣亂糟糟的吧?合理有效地使用設計模式,就能夠把我們的房間(也就是游戲)變得整潔干凈,還能讓你裝下更多的東西。這也能很好地解耦你的代碼,讓他們變得更加模塊化且方便調(diào)試。
那種代碼庫看上去是間豪華酒店,里面的門房隨時準備滿足你心血來潮的需求。

二、簡單工廠模式
????在你學習Unity游戲制作的過程中,你肯定會接觸到這一個API "Instantiate();"?。它往往出現(xiàn)在我們需要去直接生成某個預制體(Prefab)的時候,可以讓我們直接指定生成。
????假如我們現(xiàn)在有一個藍色史萊姆的預制體,當我們需要將它生成在廣袤的草原上時,就可以使用到 Instantiate 并給定要生成的具體位置。

????勇士在草原上進行冒險的時候,只會有一種藍色史萊姆嗎?當然還會有紅色、綠色的史萊姆,甚至還會有會飛的、跑得更快的史萊姆等等。最簡單的方式就是我們一個一個去制作相關的預制體,但那樣太浪費時間了而且根本不像我們程序員的風格,這時我們就可以搬出工廠模式了。
????工廠模式(Factory Pattern),它就像一座工廠一樣基于原型并根據(jù)不同需求,能夠制造出不同的產(chǎn)品進行出售,這樣一來我們就能通過代碼來產(chǎn)出不同的內(nèi)容了。


????簡單分享一種泛型的抽象工廠模式(工廠模式,每個人可能都會有不同的寫法,基于原理其實都是一樣的效果)。

????思路就是先寫一個 IFactory 的泛型 T 接口(interface),它包含一個泛型 T 的Create方法。接著讓抽象類 abstract Factory 繼承接口,同樣包含泛型 T Create方法 不進行具體的實現(xiàn)。當我們需要特定的工廠時,再編寫一個對應的工廠類(也可以寫成單例,SO的寫法也是一種解耦),在那個特定的工廠類中實現(xiàn) Create 方法,賦予預制體,外部引用工廠SO從而制作出不同的物體。

三、對象池
????在了解完 Instantiate?和 工廠模式?后,我們對Unity生成物體就有一個基本的方法了。興趣高漲的我們迫不及待地打開Unity在一個簡單場景中利用學過的知識瘋狂點擊生成物體,隨著物品產(chǎn)生的越來越多,電腦君不堪重負地倒下了。沒錯,Instantiate?生成物品到場景中的方法其實是非常消耗電腦內(nèi)存的一個方法,我們每次利用它生成一個物體的時候,這個物體就會占用到一格電腦內(nèi)存,而當我們不再需要這個物體將它 Destroy?銷毀掉,原本占用的內(nèi)存則會產(chǎn)生垃圾回收,也就是GC。這是我們非常不愿意看到的一見事情,它將損耗電腦大量的內(nèi)存,導致我們的游戲掉幀甚至死機。為解決這種問題,偉大的前人為我們創(chuàng)造了 對象池模式(Object Pool)。

????首先,你需要了解我們何時需要對象池。游戲開發(fā)師?Bob Nystrom 說:
這個模式廣泛應用于可見的事物上,比如游戲?qū)嶓w和視覺效果, 但是它也可在不那么視覺化的數(shù)據(jù)結(jié)構上使用,比如正在播放的聲音。 在以下情況中使用對象池:
需要頻繁創(chuàng)建和銷毀對象。
對象大小相仿。
在堆上進行對象內(nèi)存分配十分緩慢或者會導致內(nèi)存碎片。
每個對象都封裝了像數(shù)據(jù)庫或者網(wǎng)絡連接這樣很昂貴又可以重用的資源
????對象池模式,簡單來說就是我們在一開始就生成好我們所有所需要的物體,讓他們一開始就站好各自在內(nèi)存中的位置,在我們需要的時候就將物體啟用 gameObject.SetActive(true);?而在當我們不再需要它時,選擇?gameObject.SetActive(false); 這樣一來在游戲的后續(xù)這些物體就不會因為產(chǎn)生和銷毀而大量損耗性能產(chǎn)生GC。我們可以選擇創(chuàng)建簡單的對象池來使用,在Unity 2021.1版本以后,Unity官方也在API中為我們提供了可選擇對象池的寫法。

????基本對象池寫法,要確定數(shù)據(jù)結(jié)構類型(List、Queue、Stack等)、對象、預先實例化次數(shù),在運行的一開始預先實例化好所有的物體并將他們按數(shù)據(jù)結(jié)構存進對象池,可以將對象池寫成單例或SO。

????其次還需要一個返回對應對象的 GetFromPool 方法,讓外界能夠獲取到還沒處于啟用狀態(tài)的對象。這里就可以結(jié)合之前的工廠模式,工廠從對象池里獲取到對象后進行二次加工并啟用的一個流程。

????在2021.1版本以后,我們就可以選擇使用Unity官方提供的對象池API,其中還提供了很多的方法來優(yōu)化和方便使用對象池,是個非常不錯的選擇,具體的使用方法我們就不深究下去了,本篇目的也只是簡單介紹一下這兩種設計模式。

????設計模式其實也是一個大坑,從前的編程員不斷試錯積累經(jīng)驗方法,為我們留下了許許多多的設計模式,只要我們合理運用它就能為我們的游戲架構創(chuàng)造出不一樣的精彩。
本篇推薦教程:
????1.游戲編程模式 (tkchu.me)
????2.阿嚴的對象池:
????https://www.bilibili.com/video/BV14T4y197bW?share_source=copy_web
????3.咖喱飯游戲的工廠模式和對象池:
????https://www.bilibili.com/video/BV1Ty4y1p7WS?share_source=copy_web
????https://www.bilibili.com/video/BV1af4y1674L?share_source=copy_web
(以上,祝好胃口)