//清除某个资源在对象池中的所有对象 public void ClearPoolObject(uint crc) { List <GameObjectItem> st = null; if (m_gameObjectItemPoolDict.TryGetValue(crc, out st) == false || st == null) { return; } for (int i = st.Count - 1; i >= 0; --i) { GameObjectItem item = st[i]; if (item.Clear) { st.Remove(item); int tempId = item.Obj.GetInstanceID(); GameObject.Destroy(item.Obj); item.Reset(); m_gameObjectItemDict.Remove(tempId); m_gameObjectItemClassPool.Recycle(item); } } if (st.Count <= 0) { m_gameObjectItemPoolDict.Remove(crc); } }
//异步加载GameObject public void InstantiateAsync(string path, OnAsyncResourceObjFinished dealFinish, LoadAssetPriority priority, bool setSceneObject = false, object param1 = null, object param2 = null, object param3 = null, bool bClear = true) { if (string.IsNullOrEmpty(path)) { return; } uint crc = CrcHelper.StringToCRC32(path); GameObjectItem gameObjectItem = GetGameObjectItemFromPool(crc); if (gameObjectItem != null) { if (setSceneObject) { gameObjectItem.Obj.transform.SetParent(m_sceneGos, false); } if (dealFinish != null) { dealFinish(path, gameObjectItem.Obj, param1, param2, param3); } return; } gameObjectItem = m_gameObjectItemClassPool.Spawn(true); gameObjectItem.Crc = crc; gameObjectItem.SetSceneParent = setSceneObject; gameObjectItem.Clear = bClear; gameObjectItem.DealFinishCallback = dealFinish; gameObjectItem.Param1 = param1; gameObjectItem.Param2 = param2; gameObjectItem.Param3 = param3; //调用ResourceManager异步加载接口 ResourceMgr.Instance.AsyncLoadGameObjectItem(path, gameObjectItem, OnAsyncLoadGameObjectFinish, priority); }
public void Reset() { m_resourceObjDealFinished = null; m_gameObjDealFinished = null; m_param1 = m_param2 = m_param3 = null; m_gameObjectItem = null; }
//GameObject异步加载资源ResourceItem成功后的回调 private void OnAsyncLoadGameObjectFinish(string path, GameObjectItem gameObjectItem, object param1 = null, object param2 = null, object param3 = null) { if (gameObjectItem == null) { return; } if (gameObjectItem.ResourceItem.Obj == null) { #if UNITY_EDITOR Debug.Log("异步资源加载的资源为空: " + path); #endif } else { gameObjectItem.Obj = GameObject.Instantiate(gameObjectItem.ResourceItem.Obj) as GameObject; } if (gameObjectItem.Obj != null && gameObjectItem.SetSceneParent) { gameObjectItem.Obj.transform.SetParent(m_sceneGos, false); } if (gameObjectItem.DealFinishCallback != null) { gameObjectItem.DealFinishCallback(path, gameObjectItem.Obj, gameObjectItem.Param1, gameObjectItem.Param2, gameObjectItem.Param3); } }
//清空对象池 public void ClearCache() { List <uint> tempList = new List <uint>(); foreach (uint key in m_gameObjectItemPoolDict.Keys) { List <GameObjectItem> list = m_gameObjectItemPoolDict[key]; for (int i = list.Count - 1; i >= 0; --i) { GameObjectItem item = list[i]; if (System.Object.ReferenceEquals(item.Obj, null) && item.Clear) { list.Remove(item); GameObject.Destroy(item.Obj); m_gameObjectItemDict.Remove(item.Obj.GetInstanceID()); item.Reset(); m_gameObjectItemClassPool.Recycle(item); } } if (list.Count <= 0) { tempList.Add(key); } } for (int i = 0; i < tempList.Count; i++) { uint temp = tempList[i]; if (m_gameObjectItemPoolDict.ContainsKey(temp)) { m_gameObjectItemPoolDict.Remove(temp); } } tempList.Clear(); tempList = null; }
//取消异步加载 public bool CancelAsyncLoad(GameObjectItem item) { AsyncLoadAssetParam param = null; if (m_loadingAssetDict.TryGetValue(item.Crc, out param) && param != null && m_loadingAssetList[(int)param.m_priority].Contains(param)) { for (int i = param.m_callbackList.Count - 1; i >= 0; --i) { AsyncCallBack callback = param.m_callbackList[i]; if (callback != null && item == callback.m_gameObjectItem) { callback.Reset(); m_asyncCallBackPool.Recycle(callback); param.m_callbackList.Remove(callback); } } if (param.m_callbackList.Count <= 0) { param.Reset(); m_loadingAssetList[(int)param.m_priority].Remove(param); m_asyncLoadAssetParamPool.Recycle(param); m_loadingAssetDict.Remove(item.Crc); return(true); } } return(false); }
public void AsyncLoadGameObjectItem(string path, GameObjectItem gameObjectItem, OnAsyncGameObjFinished dealFinished, LoadAssetPriority priority) { ResourceItem item = GetAssetFromAssetCache(gameObjectItem.Crc); if (item != null) { gameObjectItem.ResourceItem = item; if (dealFinished != null) { dealFinished(path, gameObjectItem); } return; } //判断是否在加载中 AsyncLoadAssetParam para = null; if (!m_loadingAssetDict.TryGetValue(gameObjectItem.Crc, out para) || para == null) { para = m_asyncLoadAssetParamPool.Spawn(true); para.m_crc = gameObjectItem.Crc; para.m_path = path; para.m_priority = priority; m_loadingAssetDict.Add(gameObjectItem.Crc, para); m_loadingAssetList[(int)priority].Add(para); } AsyncCallBack callback = m_asyncCallBackPool.Spawn(true); callback.m_gameObjDealFinished = dealFinished; callback.m_gameObjectItem = gameObjectItem; para.m_callbackList.Add(callback); }
//从对象池中获取对象 public GameObjectItem GetGameObjectItemFromPool(uint crc) { List <GameObjectItem> list = null; if (m_gameObjectItemPoolDict.TryGetValue(crc, out list) && list != null && list.Count > 0) { ResourceMgr.Instance.IncrementResourceRef(crc, 1); GameObjectItem gameObjectItem = list[0]; list.RemoveAt(0); GameObject go = gameObjectItem.Obj; if (!System.Object.ReferenceEquals(go, null)) { //离线数据还原 if (!System.Object.ReferenceEquals(gameObjectItem.OfflineData, null)) { gameObjectItem.OfflineData.ResetProperty(); } gameObjectItem.AlreadyRelease = false; #if UNITY_EDITOR if (go.name.EndsWith("(Recycle)")) { go.name = go.name.Replace("(Recycle)", ""); } #endif } return(gameObjectItem); } return(null); }
//参数3:资源在跳转场景是否需要清空 public GameObject Instantiate(string path, bool setSceneObj = false, bool bClear = true) { uint crc = CrcHelper.StringToCRC32(path); //先尝试从缓存中取实例化Obj GameObjectItem gameObjectItem = GetGameObjectItemFromPool(crc); if (gameObjectItem == null) { gameObjectItem = m_gameObjectItemClassPool.Spawn(true); gameObjectItem.Crc = crc; gameObjectItem.Clear = bClear; ResourceMgr.Instance.LoadGameObjectItem(path, gameObjectItem); if (gameObjectItem.ResourceItem.Obj != null) { gameObjectItem.Obj = GameObject.Instantiate(gameObjectItem.ResourceItem.Obj) as GameObject; gameObjectItem.OfflineData = gameObjectItem.Obj.GetComponent <OfflineData>(); } } if (setSceneObj) { gameObjectItem.Obj.transform.SetParent(m_sceneGos, false); } gameObjectItem.Guid = gameObjectItem.Obj.GetInstanceID(); if (!m_gameObjectItemDict.ContainsKey(gameObjectItem.Guid)) { m_gameObjectItemDict.Add(gameObjectItem.Guid, gameObjectItem); } return(gameObjectItem.Obj); }
//卸载资源,针对GameObject public void UnLoadGameObjectItem(GameObjectItem gameObjectItem, bool destoryCache = false) { if (gameObjectItem == null) { return; } UnLoadAsset(gameObjectItem.ResourceItem.Obj, destoryCache); }
//获取离线数据OfflineData public OfflineData FindOfflineData(GameObject obj) { OfflineData offlineData = null; GameObjectItem item = null; if (m_gameObjectItemDict.TryGetValue(obj.GetInstanceID(), out item) && item != null) { offlineData = item.OfflineData; } return(offlineData); }
//取消某个GameObject的异步加载 public void CancelAsyncLoad(long guid) { GameObjectItem item = null; if (m_asyncGameObjectItemDict.TryGetValue(guid, out item) && item != null && ResourceMgr.Instance.CancelAsyncLoad(item)) { m_asyncGameObjectItemDict.Remove(guid); item.Reset(); m_gameObjectItemClassPool.Recycle(item); } }
//同步加载资源,针对GameObject public GameObjectItem LoadGameObjectItem(string path, GameObjectItem gameObjectItem) { if (gameObjectItem == null) { return(null); } uint crc = gameObjectItem.Crc == 0 ? CrcHelper.StringToCRC32(path) : gameObjectItem.Crc; ResourceItem resouceItem = GetAssetFromAssetCache(crc); if (resouceItem != null) { gameObjectItem.ResourceItem = resouceItem; return(gameObjectItem); } Object obj = null; #if UNITY_EDITOR if (!m_loadFromAssetBundle) { resouceItem = AssetBundleManager.Instance.FindResourceItem(crc); if (resouceItem.Obj != null) { obj = resouceItem.Obj as Object; } else { obj = LoadAssetByEditor <Object>(path); } } #endif if (obj == null) { resouceItem = AssetBundleManager.Instance.LoadResourceItem(crc); if (resouceItem != null && resouceItem.Ab != null) { if (resouceItem.Obj != null) { obj = resouceItem.Obj as Object; } else { obj = resouceItem.Ab.LoadAsset <Object>(resouceItem.AssetName); } } } CacheAsset2AssetCache(path, ref resouceItem, crc, obj); resouceItem.Clear = gameObjectItem.Clear; gameObjectItem.ResourceItem = resouceItem; return(gameObjectItem); }
//GameObject异步加载资源ResourceItem成功后的回调 private void OnAsyncLoadGameObjectFinish(string path, GameObjectItem gameObjectItem, object param1 = null, object param2 = null, object param3 = null) { if (gameObjectItem == null) { return; } if (gameObjectItem.ResourceItem.Obj == null) { #if UNITY_EDITOR Debug.LogError("异步资源加载的资源为空: " + path); #endif } else { gameObjectItem.Obj = GameObject.Instantiate(gameObjectItem.ResourceItem.Obj) as GameObject; gameObjectItem.OfflineData = gameObjectItem.Obj.GetComponent <OfflineData>(); } //加载完成, 就从正在加载的异步中移除 if (m_asyncGameObjectItemDict.ContainsKey(gameObjectItem.Guid)) { m_asyncGameObjectItemDict.Remove(gameObjectItem.Guid); } if (gameObjectItem.Obj != null && gameObjectItem.SetSceneParent) { gameObjectItem.Obj.transform.SetParent(m_sceneGos, false); } if (gameObjectItem.DealFinishCallback != null) { int guid = gameObjectItem.Obj.GetInstanceID(); if (!m_gameObjectItemDict.ContainsKey(guid)) { m_gameObjectItemDict.Add(guid, gameObjectItem); } gameObjectItem.DealFinishCallback(path, gameObjectItem.Obj, gameObjectItem.Param1, gameObjectItem.Param2, gameObjectItem.Param3); } }
//同步加载GameObject, 参数3:资源在跳转场景是否需要清空 public GameObject Instantiate(string path, bool bClear = true) { uint crc = CrcHelper.StringToCRC32(path); //先尝试从缓存中取实例化Obj GameObjectItem gameObjectItem = GetGameObjectItemFromPool(crc); if (gameObjectItem == null) { gameObjectItem = m_gameObjectItemClassPool.Spawn(true); gameObjectItem.Crc = crc; gameObjectItem.Clear = bClear; ResourceMgr.Instance.LoadGameObjectItem(path, gameObjectItem); if (gameObjectItem.ResourceItem.Obj != null) { gameObjectItem.Obj = GameObject.Instantiate(gameObjectItem.ResourceItem.Obj) as GameObject; } } gameObjectItem.Guid = gameObjectItem.Obj.GetInstanceID(); if (!m_gameObjectItemDict.ContainsKey(gameObjectItem.Guid)) { m_gameObjectItemDict.Add(gameObjectItem.Guid, gameObjectItem); } return(gameObjectItem.Obj); }
//GameObject实例化的时候,需要对资源引用计数-1 public int DecrementResourceRef(GameObjectItem gameObjectItem, int refCount = 1) { return(gameObjectItem == null ? 0 : DecrementResourceRef(gameObjectItem.Crc, refCount)); }
//异步加载资源协程 IEnumerator AsyncLoadAssetCoroutine() { List <AsyncCallBack> callbackList = null; long lastYieldTime = System.DateTime.Now.Ticks; while (true) { bool haveYield = false; for (int i = 0; i < (int)LoadAssetPriority.NUM; i++) { List <AsyncLoadAssetParam> loadingList = m_loadingAssetList[i]; if (loadingList.Count <= 0) { continue; } //取出第一个要加载的资源参数 AsyncLoadAssetParam param = loadingList[0]; loadingList.RemoveAt(0); callbackList = param.m_callbackList; Object obj = null; ResourceItem item = null; #if UNITY_EDITOR if (!m_loadFromAssetBundle) { obj = LoadAssetByEditor <Object>(param.m_path); //模拟异步加载 yield return(new WaitForSeconds(0.5f)); item = AssetBundleManager.Instance.FindResourceItem(param.m_crc); } #endif if (obj == null) { item = AssetBundleManager.Instance.LoadResourceItem(param.m_crc); if (item != null && item.Ab != null) { AssetBundleRequest request = null; if (param.m_Sprite) //图片资源需要特殊处理,因为object不能转Sprite { request = item.Ab.LoadAssetAsync <Sprite>(item.AssetName); } else { request = item.Ab.LoadAssetAsync <Object>(item.AssetName); } yield return(request); if (request.isDone) { obj = request.asset; } lastYieldTime = System.DateTime.Now.Ticks; } } CacheAsset2AssetCache(param.m_path, ref item, param.m_crc, obj, callbackList.Count); for (int j = 0; j < callbackList.Count; j++) { AsyncCallBack callback = callbackList[j]; if (callback != null && callback.m_gameObjDealFinished != null) { GameObjectItem gameObjectItem = callback.m_gameObjectItem; gameObjectItem.ResourceItem = item; callback.m_gameObjDealFinished(param.m_path, gameObjectItem, gameObjectItem.Param1, gameObjectItem.Param2, gameObjectItem.Param3); callback.m_gameObjDealFinished = null; } if (callback != null && callback.m_resourceObjDealFinished != null) { callback.m_resourceObjDealFinished(param.m_path, obj, callback.m_param1, callback.m_param2, callback.m_param3); callback.m_resourceObjDealFinished = null; } callback.Reset(); m_asyncCallBackPool.Recycle(callback); } obj = null; callbackList.Clear(); m_loadingAssetDict.Remove(param.m_crc); param.Reset(); m_asyncLoadAssetParamPool.Recycle(param); if (System.DateTime.Now.Ticks - lastYieldTime > MAXLOADASSETTIME) { yield return(null); lastYieldTime = System.DateTime.Now.Ticks; haveYield = true; } } //下边的yield return null, 作用于没有异步加载资源请求时 if (!haveYield || System.DateTime.Now.Ticks - lastYieldTime > MAXLOADASSETTIME) { lastYieldTime = System.DateTime.Now.Ticks; yield return(null); } } }
//判断是否GameObject是否是ObjectManager创建,是否是对象池形式创建的. public bool IsObjectManagerCreated(GameObject go) { GameObjectItem item = m_gameObjectItemDict[go.GetInstanceID()]; return(item != null); }
//卸载资源 public void ReleaseGameObjectItem(GameObject obj, int maxCacheCount = -1, bool destoryCache = false, bool recycleParent = true) { if (obj == null) { return; } GameObjectItem gameObjectItem = null; int tempGuid = obj.GetInstanceID(); if (!m_gameObjectItemDict.TryGetValue(tempGuid, out gameObjectItem) || gameObjectItem == null) { Debug.Log(obj.name + "并非对象池技术创建,不能回收到对象池!"); return; } if (gameObjectItem.AlreadyRelease) { Debug.LogError(obj.name + "该对象已经放回对象池, 检查是否清空该对象的引用!"); return; } #if UNITY_EDITOR obj.name += "(Recycle)"; #endif if (maxCacheCount == 0) //表示不缓存 { m_gameObjectItemDict.Remove(tempGuid); GameObject.Destroy(gameObjectItem.Obj); ResourceMgr.Instance.UnLoadGameObjectItem(gameObjectItem, destoryCache); gameObjectItem.Reset(); m_gameObjectItemClassPool.Recycle(gameObjectItem); } else { //回收到对象池 List <GameObjectItem> list = null; if (!m_gameObjectItemPoolDict.TryGetValue(gameObjectItem.Crc, out list) || list == null) { list = new List <GameObjectItem>(); m_gameObjectItemPoolDict.Add(gameObjectItem.Crc, list); } if (gameObjectItem.Obj) { if (recycleParent) { gameObjectItem.Obj.transform.SetParent(m_goPool); } else { gameObjectItem.Obj.SetActive(false); } } if (maxCacheCount < 0 || list.Count < maxCacheCount) //<0表示可以无限缓存, <maxCacheCount表示需要放入缓存 { list.Add(gameObjectItem); gameObjectItem.AlreadyRelease = true; ResourceMgr.Instance.DecrementResourceRef(gameObjectItem, 1); } else //不需要缓存GameObject到对象池 { m_gameObjectItemDict.Remove(tempGuid); GameObject.Destroy(gameObjectItem.Obj); ResourceMgr.Instance.UnLoadGameObjectItem(gameObjectItem); gameObjectItem.Reset(); m_gameObjectItemClassPool.Recycle(gameObjectItem); } } }