/* ******************************************************************************** *Copyright(C),coolae.net *Author: chenbin *Version: 2.0 *Date: 2017-01-09 *Description: 资源对象池基类 *Others: *History: ********************************************************************************* */ using UnityEngine; using System.Collections; using XLua; namespace Coolape { [LuaCallCSharp] public abstract class CLAssetsPoolBase where T: UnityEngine.Object { public CLDelegate OnSetPrefabCallbacks4Borrow = new CLDelegate (); public CLDelegate OnSetPrefabCallbacks = new CLDelegate (); // public static ListPool listPool = new ListPool (); public bool isFinishInitPool = false; public Hashtable poolMap = new Hashtable (); public Hashtable prefabMap = new Hashtable (); public Hashtable isSettingPrefabMap = new Hashtable (); public void _clean () { isFinishInitPool = false; poolMap.Clear (); prefabMap.Clear (); } public virtual void initPool () { if (isFinishInitPool) return; isFinishInitPool = true; //TODO: } /// /// Wraps the path. 包装路径,以便支持 dir1/dir2/test.unity3d /// /// The path. /// Base path. /// Thing name. public static string wrapPath (string basePath, string thingName) { string tmpStr = thingName.Replace (".", "/"); string[] strs = tmpStr.Split ('/'); string path = basePath; int len = strs.Length; for (int i = 0; i < len - 1; i++) { path = PStr.begin (path).a ("/").a (strs [i]).end (); } path = PStr.begin (path).a ("/").a (CLPathCfg.self.platform).a ("/").a (strs [len - 1]).a (".unity3d").end (); return path; } #region 设置预设 //设置预设=========== public bool _havePrefab (string name) { return prefabMap.Contains (name); } public virtual bool isAutoReleaseAssetBundle { get { return true; } } /// /// Gets the asset path.需要在扩展类中,实在该方法,调用时会用到doSetPrefab /// /// The asset path. /// Name. public abstract string getAssetPath (string name); public virtual void _setPrefab (string name, object finishCallback, object orgs, object progressCB) { string path = getAssetPath (name); OnSetPrefabCallbacks.add (name, finishCallback, orgs); doSetPrefab (path, name, (Callback)onFinishSetPrefab, name, progressCB); } public virtual void onFinishSetPrefab (object[] paras) { if (paras != null && paras.Length > 1) { T unit = paras [0] as T; string name = paras [1].ToString (); ArrayList list = OnSetPrefabCallbacks.getDelegates (name); int count = list.Count; ArrayList cell = null; object cb = null; object orgs = null; for (int i = 0; i < count; i++) { cell = list [i] as ArrayList; if (cell != null && cell.Count > 1) { cb = cell [0]; orgs = cell [1]; if (cb != null) { Utl.doCallback (cb, unit, orgs); } } } list.Clear (); OnSetPrefabCallbacks.removeDelegates (name); } } public void doSetPrefab (string path, string name, object finishCallback, object args, object progressCB) { if (name == null) return; if (MapEx.getBool (isSettingPrefabMap, name)) { return; } if (_havePrefab (name)) { if (finishCallback != null) { Utl.doCallback (finishCallback, prefabMap [name], args); } } else { isSettingPrefabMap [name] = true; Callback cb = onGetAssetsBundle; CLVerManager.self.getNewestRes (path, CLAssetType.assetBundle, cb, isAutoReleaseAssetBundle, finishCallback, name, args, progressCB); } } public void finishSetPrefab (T unit) { if (unit != null) { prefabMap[unit.name] = unit; } isSettingPrefabMap.Remove (unit.name); } public virtual void onGetAssetsBundle (params object[] paras) { string name = ""; string path = ""; try { if (paras != null) { path = (paras [0]).ToString (); AssetBundle asset = (paras [1]) as AssetBundle; object[] org = (object[])(paras [2]); object cb = org [0]; name = (org [1]).ToString (); object args = org [2]; object progressCB = org [3]; if (asset == null) { Debug.LogError("get asset is null. path =" + path); finishSetPrefab(null); Utl.doCallback (cb, null, args); return; } GameObject go = null; T unit = null; if (typeof(T) == typeof(AssetBundle)) { unit = asset as T; unit.name = name; } else { if (typeof(T) == typeof(GameObject)) { // Debug.Log ("11111name====" + name); unit = asset.mainAsset as T; unit.name = name; } else { // Debug.Log ("22222name====" + name); go = asset.mainAsset as GameObject; if (go != null) { go.name = name; unit = go.GetComponent (); } else { // Debug.Log ("33333name====" + name); unit = asset.mainAsset as T; unit.name = name; } } } CLAssetsManager.self.addAsset (getAssetPath (name), name, asset, realseAsset); sepcProc4Assets (unit, cb, args, progressCB); } else { Debug.LogError ("Get assetsbundle failed!"); } } catch (System.Exception e) { Debug.LogError ("path==" + path + "," + e + name); } } /// /// Sepcs the proc4 assets. /// /// Unit. /// Cb. /// Arguments. public virtual void sepcProc4Assets (T unit, object cb, object args, object progressCB) { GameObject go = null; if (typeof(T) == typeof(GameObject)) { go = unit as GameObject; } else if (unit is MonoBehaviour) { go = (unit as MonoBehaviour).gameObject; } if (go != null) { CLSharedAssets sharedAsset = go.GetComponent (); if (sharedAsset != null) { NewList param = ObjPool.listPool.borrowObject (); param.Add (cb); param.Add (unit); param.Add (args); sharedAsset.init ((Callback)onGetSharedAssets, param, progressCB); } else { finishSetPrefab (unit); Utl.doCallback (cb, unit, args); } } else { finishSetPrefab (unit); Utl.doCallback (cb, unit, args); } } public virtual void onGetSharedAssets (params object[] param) { if (param == null) { Debug.LogWarning ("param == null"); return; } NewList list = (NewList)(param [0]); if (list.Count >= 3) { object cb = list [0]; T obj = list [1] as T; object orgs = list [2]; finishSetPrefab (obj); if (cb != null) { Utl.doCallback (cb, obj, orgs); } } else { Debug.LogWarning ("list.Count ====0"); } ObjPool.listPool.returnObject (list); } //释放资源 public virtual void realseAsset (params object[] paras) { string name = ""; try { name = paras [0].ToString (); object obj = poolMap [name]; ObjsPubPool pool = null; T unit = null; MonoBehaviour unitObj = null; if (obj != null) { pool = obj as ObjsPubPool; } if (pool != null) { while (pool.queue.Count > 0) { unit = pool.queue.Dequeue (); if (unit != null) { if (unit is MonoBehaviour) { unitObj = unit as MonoBehaviour; GameObject.DestroyImmediate (unitObj.gameObject, true); } else if (unit is GameObject) { GameObject.DestroyImmediate ((unit as GameObject), true); } } unit = null; } pool.queue.Clear (); } unit = (T)(prefabMap [name]); prefabMap.Remove (name); if (unit != null) { if (unit is AssetBundle) { //do nothing, CLAssetsManager will unload assetbundle } else { if (unit is MonoBehaviour) { unitObj = unit as MonoBehaviour; CLSharedAssets sharedAsset = unitObj.GetComponent (); if (sharedAsset != null) { sharedAsset.returnAssets (); } GameObject.DestroyImmediate (unitObj.gameObject, true); } else if (unit is GameObject) { CLSharedAssets sharedAsset = (unit as GameObject).GetComponent (); if (sharedAsset != null) { sharedAsset.returnAssets (); } GameObject.DestroyImmediate ((unit as GameObject), true); } else { //UnityEngine.Resources.UnloadAsset ((Object)unit); GameObject.DestroyImmediate (unit, true); } } } unit = null; } catch (System.Exception e) { Debug.LogError ("name==" + name + ":" + e); } } #endregion public ObjsPubPool getObjPool (string name) { object obj = poolMap [name]; ObjsPubPool pool = null; if (obj == null) { pool = new ObjsPubPool (prefabMap); poolMap [name] = pool; } else { pool = (ObjsPubPool)obj; } return pool; } public virtual T _borrowObj (string name) { return _borrowObj (name, false); } public virtual T _borrowObj (string name, bool isSharedResource) { T r = null; if (isSharedResource) { r = (T)(prefabMap [name]); } else { object obj = poolMap [name]; ObjsPubPool pool = getObjPool (name); r = pool.borrowObject (name); poolMap [name] = pool; } if (_havePrefab (name)) { CLAssetsManager.self.useAsset (getAssetPath (name)); } return r; } /// /// Borrows the texture asyn. /// 异步取得texture /// /// The texture asyn. /// Path. /// On get texture. /// 回调函数 /// Org. /// 透传参数 public virtual void _borrowObjAsyn (string name, object onGetCallbak) { _borrowObjAsyn (name, onGetCallbak, null, null); } public virtual void _borrowObjAsyn (string name, object onGetCallbak, object orgs) { _borrowObjAsyn (name, onGetCallbak, orgs, null); } public virtual void _borrowObjAsyn (string name, object onGetCallbak, object orgs, object progressCB) { if (string.IsNullOrEmpty (name)) { Debug.LogWarning ("The name is null"); return; } if (_havePrefab (name)) { CLMainBase.self.StartCoroutine(_doBorrowObj(name, onGetCallbak, orgs)); } else { OnSetPrefabCallbacks4Borrow.add (name, onGetCallbak, orgs); _setPrefab (name, (Callback)onFinishSetPrefab4Borrow, name, progressCB); } } IEnumerator _doBorrowObj(string name, object onGetCallbak, object orgs) { yield return null; T unit = _borrowObj(name); Utl.doCallback(onGetCallbak, name, unit, orgs); } public virtual void onFinishSetPrefab4Borrow (object[] paras) { if (paras != null && paras.Length > 1) { T unit = paras [0] as T; string name = paras [1].ToString (); ArrayList list = OnSetPrefabCallbacks4Borrow.getDelegates (name); int count = list.Count; ArrayList cell = null; object cb = null; object orgs = null; for (int i = 0; i < count; i++) { cell = list [i] as ArrayList; if (cell != null && cell.Count > 1) { cb = cell [0]; orgs = cell [1]; if (cb != null) { unit = _borrowObj (name); Utl.doCallback (cb, name, unit, orgs); } } } list.Clear (); OnSetPrefabCallbacks4Borrow.removeDelegates (name); } } /// /// Returns the object. 当参数unit是null时,说明是共享资源 /// /// Name. /// Unit. public virtual void _returnObj (string name, T unit, bool inActive = true, bool setParent = true) { if (unit != null) { object obj = poolMap [name]; ObjsPubPool pool = getObjPool (name); pool.returnObject (unit); poolMap [name] = pool; if (unit is MonoBehaviour) { MonoBehaviour unitObj = unit as MonoBehaviour; if (inActive) { unitObj.gameObject.SetActive (false); } if (setParent) { unitObj.transform.parent = null; } } else if (unit is GameObject) { GameObject unitObj = unit as GameObject; if (inActive) { unitObj.SetActive (false); } if (setParent) { unitObj.transform.parent = null; } } } CLAssetsManager.self.unUseAsset (getAssetPath (name)); } public class ObjsPubPool : AbstractObjectPool { Hashtable prefabMap = null; public ObjsPubPool (Hashtable prefabMap) { this.prefabMap = prefabMap; } public override T createObject (string key) { T unit = (prefabMap [key]) as T; if (unit != null) { Object go = GameObject.Instantiate (unit) as Object; go.name = key; T ret = null; if (go is T) { ret = go as T; } else { ret = ((GameObject)go).GetComponent (); } return ret; } return null; } public override T resetObject (T t) { return t; } } } }