《炉石传说》架构设计赏析(4):Asset管理
話說(shuō),經(jīng)過(guò)這段時(shí)間的學(xué)習(xí)和摸索,對(duì)于Unity3D的開(kāi)發(fā)思路已經(jīng)基本清晰了。唯獨(dú)還剩下一個(gè)AssetBundle機(jī)制還沒(méi)有搞透,這個(gè)涉及到前期項(xiàng)目的資源規(guī)劃、資源管理代碼的寫(xiě)法,以及自動(dòng)更新機(jī)制的實(shí)現(xiàn)。
所以,還是想先把游戲邏輯的進(jìn)一步分析押后,先來(lái)看一下《爐石傳說(shuō)》Asset管理。必須得說(shuō)一下的是,目前分析都是PC版的程序集,對(duì)于移動(dòng)端不一定完全合適,且當(dāng)做一個(gè)案例分析吧。
本文主要講述《爐石傳說(shuō)》的AssetBundle的管理機(jī)制。它的機(jī)制比較簡(jiǎn)單清晰,中規(guī)中矩,中間的分析過(guò)程就不講了,直接展現(xiàn)其架構(gòu)設(shè)計(jì)和代碼邏輯組織。先從Asset管理相關(guān)的類講起。
class Asset:資源信息描述
?
Asset類,并不管理直接的資源對(duì)象,而是保存的一個(gè)Asset相關(guān)的信息,具體請(qǐng)看上圖。
另外,它還有一個(gè)“paths”變量,這是一個(gè)Dictionary,key是AssetFamily枚舉,value是Assetbundle的路徑和資源路徑。下面的AssetFamily一節(jié)詳細(xì)解釋。
enum AssetFamily-資源分類
?
如上圖所示:
?
- 爐石根據(jù)資源的不同類型進(jìn)行分別的AssetBundle打包,一類資源對(duì)應(yīng)一個(gè)或者多個(gè)資源包;(一類資源分多個(gè)包的規(guī)則不得而知);
- 有的資源包真的本地化單獨(dú)打包,例如“fonts0.unity3d”==》“fontszhCN0.unity3d”;
- 在程序中,資源包的分類對(duì)應(yīng)枚舉類型“AssetFamily”;
- 資源包的具體路徑信息,存儲(chǔ)在Asset.paths,這是一個(gè)靜態(tài)變量;在初始化時(shí),手動(dòng)填寫(xiě)必要的信息,類似這樣:
- 另外,還有一個(gè)class AssetBundleInfo是記錄了每種AssetBundle對(duì)應(yīng)的主文件名,以及包文件的個(gè)數(shù)、對(duì)應(yīng)的對(duì)象類型等信息;詳見(jiàn)下圖:
class AssetLoader:資源加載
?
游戲運(yùn)行時(shí)需要加載各種資源,基本上都是通過(guò)AssetLoader(也有個(gè)別情況適用了Resources.Load())。接下來(lái)我們就重點(diǎn)看一下AssetLoader的實(shí)現(xiàn)思路。
AssetLoader對(duì)上層提供資源對(duì)象加載接口,對(duì)于每種類型的資源都提供一組函數(shù),例如LoadCardPrefab,LoadActor等等。對(duì)于對(duì)象加載完成、加載進(jìn)度等提供回調(diào)函數(shù)。這些函數(shù)只是一些簡(jiǎn)單的包裝,其內(nèi)部都調(diào)用到LoadCachedGameObject()或LoadCachedObject()這兩個(gè)核心函數(shù)。
從這兩個(gè)函數(shù)的流程可以看到,資源加載使用到了Cache機(jī)制:
1.首先從AssetCache中查找,如果找到了,則更新Cache項(xiàng)的時(shí)間戳,并調(diào)用回調(diào);
2.如果沒(méi)有找到,則向AssetCache添加一個(gè)Request,然后啟動(dòng)Coroutine:CreateCachedAsset(),它的調(diào)用步驟是:
?
- 調(diào)用AssetCache.StartLoading();
- 啟動(dòng)Coroutine:CreateCachedAsset_FromBundle<RequestType>():
- 使用AssetLoader.GetBundleForAsset()找到資源所屬的AssetBundle;
- 調(diào)用AssetBundle.LoadAsync()來(lái)真正加載資源;
- 在加載的過(guò)程中,根據(jù)處理的結(jié)果調(diào)用:AssetCache.CacheRequest的OnLoadFailed()、OnLoadSucceeded()、OnProgressUpdate()等函數(shù);
- 在AssetCache查找此資源,如果找到了,則加載成功,調(diào)用回調(diào)函數(shù);
調(diào)用AssetCache.StopLoading();
我們都知道在開(kāi)發(fā)過(guò)程中,不能使用AssetBundle(每次啟動(dòng)都要打包,肯定收不了)。懷疑它的Editor模式相關(guān)的代碼是用預(yù)編譯宏處理來(lái)實(shí)現(xiàn)的,所以未出現(xiàn)在發(fā)布出來(lái)的程序集當(dāng)中,類似這樣:
?
class AssetCache:資源的Cache機(jī)制
前面在AssetLoader一節(jié)我們已經(jīng)講到了AssetCache機(jī)制,這里再做一個(gè)詳細(xì)的闡述。
?
前面我們已經(jīng)講到:
?
- AssetCache中的資源項(xiàng)的時(shí)間戳,由AssetLoader在資源加載請(qǐng)求時(shí)維護(hù);
- AssetCache主要負(fù)責(zé)管理Cache數(shù)據(jù),而真正的資源加載動(dòng)作還是在AssetLoader中執(zhí)行;
AssetCache的資源淘汰主要由外部的各個(gè)模塊根據(jù)自己認(rèn)為需要的時(shí)機(jī)去調(diào)用,例如:
?
- SceneMgr.ClearCachesAndFreeMemory()
- LoadingScreen.ClearAssets()
- SoundMgr.UnloadSoundBundle()
- 等等
另外,程序啟動(dòng)時(shí)會(huì)自動(dòng)更新資源包(在Login.OnAssetsVersion()中啟動(dòng)),主要是通過(guò)UpdateManager和Downloader兩個(gè)類來(lái)處理。
OK,總結(jié)一下?tīng)t石的資源管理機(jī)制:
?
- 對(duì)游戲資源按照類型分包,買(mǎi)二手游戲每一類資源包可以有多個(gè);
- 在游戲運(yùn)行時(shí)使用Cache機(jī)制;
總結(jié)
以上是生活随笔為你收集整理的《炉石传说》架构设计赏析(4):Asset管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 《轩辕传奇手游》主程序带你拆解MMORP
- 下一篇: 《炉石传说》架构设计赏析(3):Game