Unity3d资源管理模块
對于Unity3d的資源管理已經研究了很久,大概是從大學畢業到現在,依然在不斷的探索著,這期間不斷的在網上查看各位大神們的講解,然后自己就研究,也做部分實驗,發現其實要很好地管理起來是很容易的,資源更新,加載,卸載對于一款游戲來說是十分重要的,首先我從資源更新說起。
一、資源更新現在有很多的辦法,Unity3d提供了很多種資源管理方式。1、你可以將資源存放在工程目錄的Resource文件夾下面,這個文件夾下面的資源會隨著你導出平臺安裝包的時候加密到你的安裝包里面,unity程序在運行的時候會根據自己的資源加載思路將場景里面用到的資源進行加載,但是這部分資源是不能夠及時更新的,也就是說,資源跟新不能考慮這個文件夾;2、unity工程下面還有一個特殊的文件夾,就是StreamingAssets文件夾,這個文件夾會在你導出的時候原封不動的考到安裝包里面,在釋放到平臺上面,注意一點,他是原封不動的,這就需要你采用自己的加密方式,要不會很容易被破解的,這部分資源在各個平臺上是可以訪問到,安卓手機上面用WWW類進行讀取,PC,以及iPhone可以用File類進行讀取,很方便。上述兩個文件夾是unity提供給我們的,很方便,哈哈。
我自己在研究了那么久之后,決定將大部分用到的,可能需要經常更新的資源存放到了StreamingAssets目錄下面,有用到的ngui的圖集,以及預設等等,由于iPhone不支持代碼更新,我們就在腳本中運用了lua代碼,我們采用的是ulua,這都是跟著群里面的大神學習的,首先游戲安裝到設備上頭一回運行的時候,會將StreamingAssets下面的資源進行復制,釋放到平臺上面我們自己指定的目錄,需要獲得讀寫權限,這個路徑Application.streamingAssetsPath就是平臺上面的StreamingAssets所在的位置,然后在安卓手機上面訪問內置sd卡或sd卡1的路徑為/mnt/sdcard,在4.1以后也可用路徑/storage/sdcard0這個路徑,最后在這個歷經下面建立文件夾,存放自己的資源。在iPhone以及PC上面完全可以使用Application.persistentDataPath這個目錄進行資源的存放。資源存放好了就可以準備更新了,www可以訪問你自己的資源服務器,游戲資源存放得當之后便可以調用new WWW(地址);來進行下載,我們的做法是資源釋放到了本地,然后會從服務器上面下載最新的資源配置文件,lua太偉大了,既可以寫程序也可以作為配置文件,哈哈,我就將資源的名稱以及他們的md5值存放在lua的table里面,然后就是表的遍歷了,方法很多,ulua在這方面已經完全可以勝任,支持安卓PC以及iPhone,wp推薦用nlua,nlua我不會,哈哈,怎樣打assetbundle類型的資源包網上教程很多,也很詳細,如果資源包過大,也可以考慮一下采用壓縮,有7z,網上有宣雨松的例子,很好。遍歷配置表格,進行md5比對,不同的就進行下載,最終進入游戲。建議是資源盡量分的細一些,這樣既方便局部資源的整體替換,同時也有利于團隊分工開發,后期的更新維護也會很簡單,你可以參考一下別人的安裝包,解壓看看里面的資源是怎么布置的,看看就好呀,哈哈。共同學習。
二、下面就是資源的加載了,建議大家對Resource類進行適當的利用然后寫出一個自己能夠方便使用的資源加載類,首先可以從Resource目錄下面方便的加載,然后還要很方便的從assetbundle里面進行加載,assetbundle里面的資源你想要用的時候要提前加載,建議做在loading界面里面,這樣用戶體驗會好一些,因為此時用戶的耐心是最大的,你一卡一卡的,老板都會揍你,哈哈,這個加載類可以加載assetbundle里面的東西,并將加載的assetbundle交給全局的加載對象管理器,以便進行及時的釋放,關于assetbundle的完全釋放,網上講的很多,也很好,我這里面總結一下整體的過程,僅供參考:
1.首先記錄下已經加載的assetbundle,以便你好釋放;
2.將預設或者圖集,圖片從里面加載出來,記錄;
3.將在第2步里面加載的東西放到場景的某個對象上面,或者直接實例化預設,將這個放到場景里面的這個對象記錄下來,因為它上面有對asser的引用;
4.在一個assetbundlle里面所有的用到的資源都加在出來之后,執行語句Resources.UnloadUnusedAssets();會將不用了的asset占用的內存釋放出來;
5.場景中通過某一個assetbundle創建的對象或者依附的對象沒什么用處的時候,將對象進行Destroy(對象);這個方法,這樣對象會從場景里面消失,同時它所引用的資源就沒有存在的意義了;
6.將銷毀的對象所用的assetbundle執行assetbundle.Unload(false);,這樣就會將已經記錄的資源包所占用的內存鏡像會完全卸載;
7.Resources.UnloadUnusedAssets();卸載沒有用到的資源;
8.將記錄的加載過的預設,等資源設置為null;
9.Resources.UnloadUnusedAssets();釋放資源,
10.調用系統的垃圾回收站清理函數GC.Collect();
通過上面十個步驟,就可以將引用的assetbundle進行徹底的釋放,由于在代碼里面我與用到了lua腳本,就可能會存在lua的引用,這時需要在第8個步驟里面調用一下lua自身的垃圾回收函數collectgarbage();然后再進行第9步,實驗證明是可以的。
我在實際的過程中就是采用的如此的資源更新,加載,以及釋放的過程,很方便,沒有提到的就是工程里面要有一個對象管理器,就是對象池,需要你對對象進行比較明確的管理,時刻明白場景里面哪些是有用的,哪些是可以釋放卸載掉的,這樣,unity3d的游戲在平臺上才不會內存一直飆高,可能引起的游戲閃退等現象,卡頓也會避免。
最后,大家加油呀!快過年了,程序員還沒放假,哈哈
下面是我自己的部分代碼,很簡單的,只供參考,嘿嘿
改日把我的GameObjectMgr也加進來,供大家參考,周末愉快,下周末我也就放假啦,哈哈哈,開心的等待著
using UnityEngine; using System.Collections; using System.Collections.Generic;public class GameObjectMgr{public static Dictionary<string,GameObject> loadedPerfabList =null; //存放已經加載的預設資源public static Dictionary<string,AssetBundle> loadedAssetList =null; //存放AB包public static Dictionary<string,GameObject> createdObjList =null; //存放創建的對象public static string[] destoryPerfabList =null; //銷毀的預設public static string[] destoryAssetList =null; //銷毀的AB包,unload(false);public static string[] destoryObjNameList =null; //銷毀的對象;//設置是否顯示public static void SetObjActivePority(string _name,bool _active){if (createdObjList == null) {} else {foreach(string key in createdObjList.Keys){if(key==_name){if(createdObjList[key]!=null){createdObjList[key].SetActive(_active);}else{createdObjList.Remove(_name);}} } }}//獲得一個已經創建的對象public static GameObject GetGameObjectByName(string _name){ if (createdObjList == null) {return null;} else {foreach(string key in createdObjList.Keys){if(key==_name){if(createdObjList[key]!=null){return createdObjList[key];}else{createdObjList.Remove(_name);return null;}} } }return null;}//獲得一個已經加載的預設public static GameObject GetPrefabByName(string _name){ if (loadedPerfabList == null) {return null;} else {foreach(string key in loadedPerfabList.Keys){if(key==_name){if(loadedPerfabList[key]!=null){return loadedPerfabList[key];}else{loadedPerfabList.Remove(_name);return null;}} } }return null;}//查看預設是否加載public static bool IsPerfabLoaded(string _name){if (loadedPerfabList == null) {return false;} else {foreach(string key in loadedPerfabList.Keys){if(key==_name){if(loadedPerfabList[key]!=null)return true;else{loadedPerfabList.Remove(_name);return false;}} } }return false;}//對象是否已經被創建public static bool IsObjCreated(string _name){if (createdObjList == null) {return false;} else {foreach(string key in createdObjList.Keys){if(key==_name){if(createdObjList[key]!=null){return true;}else{createdObjList.Remove(_name);return false;}} } }return false;}//添加已經創建public static void AddCreatedObjList(string _name, GameObject _obj){if (createdObjList == null) {createdObjList = new Dictionary<string, GameObject>(); }if(createdObjList.ContainsKey(_name)){return ;}createdObjList.Add (_name,_obj);}//添加已經加載的assetbundlepublic static void AddloadedAssetList(string _name, AssetBundle _obj){if (loadedAssetList == null) {loadedAssetList = new Dictionary<string, AssetBundle>(); }if(loadedAssetList.ContainsKey(_name)){return ;}loadedAssetList.Add (_name,_obj);}//添加已經加載的預設public static void AddloadedPerfabList(string _name, GameObject _obj){if (loadedPerfabList == null) {loadedPerfabList = new Dictionary<string, GameObject>(); }if(loadedPerfabList.ContainsKey(_name)){return ;}loadedPerfabList.Add (_name,_obj);}//添加預設名字public static void AdddestoryPerfabList(string _name){if (destoryPerfabList == null) {destoryPerfabList = new string[1];destoryPerfabList[0] = _name;return;} else {int j = destoryPerfabList.Length;destoryPerfabList[j] = _name;return;}}//添加對象名字public static void AdddestoryObjNameList(string _name){if (destoryObjNameList == null) {destoryObjNameList = new string[1];destoryObjNameList[0] = _name;return;} else {int i=destoryObjNameList.Length;destoryObjNameList[i] = _name;return;}}//添加assetbundle名字public static void AdddestoryABList(string _name){if (destoryAssetList == null) {destoryAssetList = new string[1];destoryAssetList[0] =_name;return;} else {int j = destoryAssetList.Length;destoryAssetList[j] = _name;return;}}//清理內存public static void FreeMemory(){if (destoryObjNameList == null&&destoryPerfabList.Length== null&&destoryAssetList== null) {Debug.Log("不需要釋放資源"); return;}int i = 0;if (destoryObjNameList != null) {i = destoryObjNameList.Length;for(int j = i-1;j>=0;j--){if(destoryObjNameList[j]!=null)if(createdObjList.ContainsKey(destoryObjNameList[j])){GameObject obj=createdObjList[destoryObjNameList[j]];createdObjList.Remove(destoryObjNameList[j]);GameObject.Destroy(obj);}destoryObjNameList[j]=null;} }destoryObjNameList = null;if (destoryPerfabList != null) {i = destoryPerfabList.Length;for(int j = i-1;j>=0;j--){if(destoryPerfabList[j]!=null)if(loadedPerfabList.ContainsKey(destoryPerfabList[j])){loadedPerfabList[destoryPerfabList[j]]=null;loadedPerfabList.Remove(destoryPerfabList[j]);}destoryPerfabList[j]=null;} }destoryPerfabList = null;if (destoryAssetList == null || destoryAssetList.Length == 0) {} else {i = destoryAssetList.Length;for(int j =i-1;j>=0;j--){if(destoryAssetList[j]!=null)if(loadedAssetList.ContainsKey(destoryAssetList[j]))AssetBundle asset = loadedAssetList[destoryAssetList[j]];loadedAssetList.Remove(destoryAssetList[j]);asset.Unload(false);}destoryAssetList[j]=null;}}destoryAssetList = null;Resources.UnloadUnusedAssets ();System.GC.Collect ();} }總結
以上是生活随笔為你收集整理的Unity3d资源管理模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10 个最佳 GIS 软件应用程序
- 下一篇: CAD中的形及线型