一、遊戲專案中的資源池
在一款遊戲中,隨著遊戲的進行,我們會不斷的建立和銷毀一些角色,比如我們玩一款射擊遊戲,我們需要不斷的發射子彈,一般的情況下,我們會不斷的建立子彈,然後發射出去,在擊中物體後銷毀。分析整個設計的過程,我們會不斷的建立子彈,然後發射出去,最後銷毀它。這兒,其實就可以引入資源池的概念來解決子彈的反覆建立和銷毀。
如果只是反覆的建立和銷毀子彈,那麼每次的效能點主要在子彈的建立上,在場景中有較多角色頻繁操作射擊的時候,不斷執行建立,會帶來效能的較大消耗,從而讓遊戲卡幀。如果我們把這些子彈預先建立出來,塞入到乙個彈夾,然後每次在射擊發射子彈的時候,從預先建立的彈夾中取出來發射,每次在銷毀的時候,又將其還原到彈夾中,這樣迴圈反覆的利用,可以避免每次射擊子彈的時候的建立操作帶來的效能消耗。將彈夾拓展一步,就是資源池的概念了。
二、不同設計下的資源池
1、簡單lua版本的資源池
基於前文子彈的闡述,我就寫乙個簡單版本的資源池的lua版本,首先,是資源池的定義:
functionbulletpool:initialize()
--快取子彈的table
self.mbulletpool ={}
end
是不是覺得很簡單,是的,lua版本的資源池可以只需要用乙個table就簡單的表示,接下來,我們只需要維護好這個table即可。首先是取子彈的介面:
functionbulletpool:getbullet()
--如果沒有定義,則執行一次兜底定義
ifnot self.mbulletpool then
self.mbulletpool ={}
end--
如果池子裡面沒有可以取的了,則返回nil
ifnext(self.mbulletpool) == nil
then
return
nilend
local bulletobj = self.mbulletpool[#self.mbulletpool]
table.remove(self.mbulletpool, #self.mbulletpool)
return
bulletobj
end
有了設計的介面,接下來,我們可以繼續設計歸還的介面,所謂有借有還再借不難,不能只從池子裡面取,不歸還,那池子早晚會乾涸的 :d
functionbulletpool:insertbullet(bullet)
ifnot bullet then
return
endif
not self.mbulletpool then
self.mbulletpool ={}
end--
子彈歸還前的釋放操作,可以不在意這一步操作
bullet:release()
table.insert
(self.mbulletpool, bullet)
end
好了,有了整體的獲取和歸還的操作,池子的基本介面就有了,有的同學會說,如果我們想重置一遍池子怎麼辦?那就再寫乙個清除池子的操作吧 :b
functionbulletpool:release()
for k, v in
pairs(self.mbulletpool) do
v:release()
endfor k, v in
pairs(self.mbulletpool) do
self.mbulletpool[k] = nil
endend
這下介面都有了,讓我們來應用這些介面吧 :d
首先給角色掛載乙個子彈的資源池的獲取介面吧:
--獲取介面
function
character:getbullet()
return
bulletpool:getbullet()
end--
塞入介面
function
character:removebullet(bullet)
bulletpool:insertbullet(bullet)
end
因為每個角色都會射出一堆的子彈,所以我們是直接掛在角色身上,就不在整個場景管理器中去管理子彈了,可以通過場景管理器的更新來執行角色的更新,從而執行所有子彈的更新,這樣每個角色的子彈更新和角色更新一致。這種設計模式下,不會出現先更新角色,然後再更新子彈的帶來的一些問題。
有了這兩個介面,下面就是讓角色呼叫這2個介面:
...--獲取子彈
local bullet =mchar:getbullet()
--沒有則新建,有則重新初始化相關引數
if bullet == nil
then
bullet =bullet:new(...)
else
bullet:initialize(...)
end--
塞入到角色身上的乙個table中維護
mchar:addbullet()
...--
移除子彈,比較簡單
if bullet:update() then
mchar:removebullet(bullet)
end
到這兒,我們完成了乙個簡單的lua版本的資源池的設計和實現,通過這幾個介面,對資源池有乙個簡單的入門理解了。接下來,我們進一步編寫乙個c#版本的資源池吧。
2、c#版本的資源池
在有了lua版本的資源池入門之後,接下來我們可以進一步的設計乙個c#版本的資源池了。在unity的c#中,會有各種各樣的資源需要資源池來進行管理,所以我們不能單獨的做某個類的資源池了,我們需要引入泛型來指代各種型別的資源池。
先寫乙個簡單的資源池,就實現乙個獲取和歸還介面吧:
usingsystem.collections;
using
system.collections.generic;
public
class objectpoolwhere t:class
return
null
; }
public
void
returnobj(t obj)
} }
有了簡化版本的資源池,我們可以進一步的拓展這個池子的設計。首先,我們可以將鍊錶改為堆疊,用乙個棧來代替鍊錶,相對會比較容易控制,只需要管理入棧和出棧即可。其次,在池子已經被榨乾,取完的時候,前面是直接返回乙個null,我們可以繼續拓展,在沒有的時候,就進行一次建立操作,這個可以通過委託來實現,在池子的初始化的時候就註冊相關的委託。同理,進一步的拓展出取完後的操作和歸還釋放時的操作委託,這樣就把我們前面lua中歸還池子時候釋放子彈的操作封裝為乙個事件。說完思路,下面讓我們開始吧:
usingsystem;
using
system.collections.generic;
public
class objectpoolwhere t:class
//獲取介面
public
t get()
else
//執行**
if(m_acitononget != null
)
return
obj;
}//釋放介面
public
void
release(t obj)
m_stack.push(obj);
}//clear介面
public
void
clear()
}
寫到這兒,乙個基本的資源池的構建算是完成了,大家可以在這個版本的基礎上進一步的衍生出資源池的使用,比如給資源池的物件新增乙個計時的功能,當資源計時超過一定的時間後,就將其從資源池中去除,避免資源池不斷擴大。諸如此類種種,都是後續可以操作的,好了,這篇文章就寫到這兒,也祝提前祝大家2023年新年快樂!
遊戲引擎 資源管理 記憶體池設計(1)
資源管理包括兩個部分 記憶體管理 資源的記憶體分配 日誌管理 資源的資訊,記憶體資訊都將被記錄在日誌中 資源管理 統一資源 很簡單的記憶體池設計 ifndef cmemorypool h h define cmemorypool h h define null 0 templateclass cme...
遊戲中的資源包
現在的遊戲中一般都有自己的資源包。早期看到很多2d遊戲都沒有資源包的,資源都是分散著的,當然可以直接看到其中每個檔案的內容。後來發現很多遊戲都有資源包了,像天下貳 劍網三等等。下面說說一些遊戲的資源包 1.天龍八部on line 天龍八部的資源在沒有加密前是很容易提取出來的。天龍八部是我最早知道使用...
Unity 提取遊戲資源之ktx轉換
從雨松的博文 unity3d研究院之mac上從.ipa中提取unity3d遊戲資源 六十六 可以學到提取unity的遊戲資源,其中有用到乙個工具 pvrtextool 提取出來的資源,其中的ktx資源,用pvrtextoolgui.exe可以開啟檢視,可以發現都是上下顛倒,且被拉伸 直接轉為png格...