|
最近在写一本童话故事,欢迎点赞收藏,非常重要。给自己打个广告。以后会根据这本书开发一款游戏,文章有帮到你的话,请给书点个收藏。感谢。
1.ResourceManager 提供非gameobject 类资源加载(同步/异步)/释放 及ObjectManager加载Gameobject的加载接口
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ABFrame
{
/// <summary>
/// 资源加载优先级
/// </summary>
public enum LoadResPriority
{
Res_Heigh = 0,//最高优先级
Res_Middle,//一般优先级
Res_Slow,//低优先级
Res_Num,//优先级数量
}
/// <summary>
/// 非实例化资源异步加载完回调委托
/// </summary>
public delegate void OnAsyncObjFinishDele(string path, Object obj, object param1 = null, object param2 = null, object param3 = null);
/// <summary>
/// 实例化资源异步加载完回调委托
/// </summary>
public delegate void OnAsyncInstanceFinishDele(string path, ResourceObj obj, object param1 = null, object param2 = null, object param3 = null);
public class ResourceManager : Singleton<ResourceManager>
{
protected int m_Guid = 0;
public bool m_IsLoadFromAssetBundle = false;
/// <summary>
/// 缓存正在使用的资源池
/// </summary>
public Dictionary<uint, ResourceItem> m_UsingAssetDic { get; set; } = new Dictionary<uint, ResourceItem>();
/// <summary>
/// 缓存引用计数为零的资源列表 达到缓存最大的时候 释放这个列表中最早没有使用的资源
/// </summary>
protected CMapList<ResourceItem> m_noRefResourceMapList = new CMapList<ResourceItem>();
//==================================================异步=======================
/// <summary>
/// 使用Mono 开启协程进行异步加载
/// </summary>
protected MonoBehaviour m_asyncMono;
///正在异步加载的资源列表包含优先级
protected List<AsyncLoadResInfo>[] m_AsyncLoadingAssetList = new List<AsyncLoadResInfo>[(int)LoadResPriority.Res_Num];
///正在异步加载的资源Dic 用来做重复判断
protected Dictionary<uint, AsyncLoadResInfo> m_asnycloadingAssetDic = new Dictionary<uint, AsyncLoadResInfo>();
/// <summary>
/// 资源加载完成回调信息对象池
/// </summary>
protected ClassObjectPool<AsnycCallBackInfo> m_asyncCallBackInfoPool = new ClassObjectPool<AsnycCallBackInfo>(50);
/// <summary>
/// 异步加载资源信息对象池
/// </summary>
protected ClassObjectPool<AsyncLoadResInfo> m_asyncResInfoPool = new ClassObjectPool<AsyncLoadResInfo>(50);
///最长连续卡着的加载时间 微秒
private const float MAXLOADRESTIME = 200000;
/// <summary>
/// 资源最大缓存个数 可以根据手机高低配置进行设置
/// </summary>
private const int MAXCACHECOUNT = 500;
/// <summary>
/// 异步加载初始化
/// </summary>
public void InitAsync(MonoBehaviour asyncMono)
{
for (int i = 0; i < (int)LoadResPriority.Res_Num; i++)
{
m_AsyncLoadingAssetList = new List&t;AsyncLoadResInfo>();
}
this.m_asyncMono = asyncMono;
this.m_asyncMono.StartCoroutine(AsyncLoadCor());
}
/// <summary>
/// 创建唯一的Guid
/// </summary>
/// <returns></returns>
public int CreateGuid()
{
return this.m_Guid++;
}
//==============================================同步====================================
/// <summary>
/// 加载ResourceObj 针对ObjManager的接口
/// </summary>
/// <returns></returns>
public ResourceObj LoadRecource(string path, ResourceObj resobj)
{
if (resobj == null) return null;
uint crc = resobj.m_Crc == 0 ? Crc32.GetCrc32(path) : resobj.m_Crc;
ResourceItem item = GetCatchResourceItem(crc);
if (item != null)
{
resobj.m_ResItem = item;
return resobj;
}
Object obj = null;
#if UNITY_EDITOR
if (!m_IsLoadFromAssetBundle)
{
item = ABManager.Instance.FinResourceItemByCrc(crc);
if (item != null && item.m_Obj != null)
obj = item.m_Obj as Object;
else
{
if (item == null)
{
item = new ResourceItem();
item.m_Crc = crc;
}
obj = LoadAssetByEditor<Object>(path);
}
}
#endif
if (obj == null)
{
item = ABManager.Instance.LoadResourceAssetBundle(crc);
if (item != null && item.m_AssetBundle != null)
{
if (item.m_Obj != null) obj = item.m_Obj as Object;
else
obj = item.m_AssetBundle.LoadAsset<Object>(item.m_AssetName);
}
}
CacheResource(path, ref item, crc, obj);
resobj.m_ResItem = item;
item.m_Clear = resobj.m_bClear;
return resobj;
}
/// <summary>
/// 同步加载资源 外部直接调用 仅加载不需要实例化的资源 例如texture,音频等等
/// </summary>
/// <typeparam name=&#34;T&#34;></typeparam>
/// <param name=&#34;path&#34;></param>
/// <returns></returns>
public T LoadResource<T>(string path) where T : UnityEngine.Object
{
if (string.IsNullOrEmpty(path)) return null;
uint crc = Crc32.GetCrc32(path);
ResourceItem item = GetCatchResourceItem(crc);
if (item != null)
{
return item.m_Obj as T;
}
T obj = null;
#if UNITY_EDITOR
if (!m_IsLoadFromAssetBundle)
{
item = ABManager.Instance.FinResourceItemByCrc(crc);
if (item == null)
Debug.LogError(&#34;not found assets &#34; + path);
else
{
if (item.m_Obj != null) obj = item.m_Obj as T;
else obj = LoadAssetByEditor<T>(path);
}
}
#endif
if (obj == null)
{
item = ABManager.Instance.LoadResourceAssetBundle(crc);
if (item != null && item.m_AssetBundle != null)
{
if (item.m_Obj != null) obj = item.m_Obj as T;
else
obj = item.m_AssetBundle.LoadAsset<T>(item.m_AssetName);
}
}
CacheResource(path, ref item, crc, obj);
return obj;
}
/// <summary>
/// 根据ResourceObj 卸载资源
/// </summary>
/// <returns></returns>
public bool ReleaseResource(ResourceObj obj, bool destoryobj = false)
{
if (obj == null) return false;
ResourceItem item = null;
if (!m_UsingAssetDic.TryGetValue(obj.m_Crc, out item) || item == null)
Debug.LogError(&#34;m_UsingAssetDic 里不存在该资源:&#34; + obj.m_CloneObj.name + &#34; 可能释放了多次&#34;);
GameObject.Destroy(obj.m_CloneObj);
item.RefCount--;
DestoryResourceItem(item, destoryobj);
return true;
}
/// <summary>
/// 不需要实例化的资源的卸载
/// </summary>
/// <param name=&#34;obj&#34;></param>
/// <param name=&#34;destoryObj&#34;></param>
/// <returns></returns>
public bool ReleaseResource(Object obj, bool destoryObj = false)
{
if (obj == null) return false;
ResourceItem item = null;
foreach (ResourceItem res in m_UsingAssetDic.Values)
{
if (res.m_Guid == obj.GetInstanceID())
item = res;
}
if (item == null)
{
Debug.LogError(&#34;AssetDic 不存在该资源:&#34; + obj.name + &#34; 可能释放了多次&#34;);
return false;
}
item.RefCount--;
DestoryResourceItem(item, destoryObj);
return true;
}
/// <summary>
/// 释放资源 根据资源路径
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;destoryObj&#34;></param>
/// <returns></returns>
public bool ReleaseResource(string path, bool destoryObj = false)
{
if (string.IsNullOrEmpty(path)) return false;
uint crc = Crc32.GetCrc32(path);
ResourceItem item = null;
if (!m_UsingAssetDic.TryGetValue(crc, out item) || item == null)
{
Debug.LogError(&#34;AssetDic 里不存在该资源:&#34; + path + &#34; 可能释放了多次&#34;);
return false;
}
item.RefCount--;
DestoryResourceItem(item, destoryObj);
return true;
}
/// <summary>
/// 清空缓存 一般在跳场景时候使用
/// </summary>
public void ClearCache()
{
List<ResourceItem> tempList = new List<ResourceItem>();
foreach (ResourceItem item in m_UsingAssetDic.Values)
{
if (item.m_Clear)
tempList.Add(item);
}
foreach (var item in tempList)
{
DestoryResourceItem(item, true);
}
tempList.Clear();
}
/// <summary>
/// 根据obj 增加引用计数
/// </summary>
/// <returns></returns>
public int IncreaseResourceRef(ResourceObj resobj, int count = 1)
{
return resobj == null ? 0 : IncreaseResourceRef(resobj.m_Crc, count);
}
/// <summary>
/// 根据path 增加引用计数
/// </summary>
/// <param name=&#34;crc&#34;></param>
/// <param name=&#34;count&#34;></param>
/// <returns></returns>
public int IncreaseResourceRef(uint crc, int count = 1)
{
ResourceItem item = null;
if (!m_UsingAssetDic.TryGetValue(crc, out item) || item == null) return 0;
item.RefCount += count;
item.m_LastUseTime = Time.realtimeSinceStartup;
return item.RefCount;
}
/// <summary>
/// 减少引用计数
/// </summary>
/// <returns></returns>
public int DecreaseResourceRef(ResourceObj resobj, int count = 1)
{
return resobj == null ? 0 : DecreaseResourceRef(resobj.m_Crc, count);
}
/// <summary>
/// 根据路径减少引用计数
/// </summary>
/// <param name=&#34;crc&#34;></param>
/// <param name=&#34;count&#34;></param>
/// <returns></returns>
public int DecreaseResourceRef(uint crc, int count = 1)
{
ResourceItem item = null;
if (!m_UsingAssetDic.TryGetValue(crc, out item) || item == null) return 0;
item.RefCount -= count;
return item.RefCount;
}
/// <summary>
///取消异步加载
/// </summary>
public bool CancelAsyncLoad(ResourceObj res)
{
AsyncLoadResInfo asyinfo = null;
if (m_asnycloadingAssetDic.TryGetValue(res.m_Crc, out asyinfo) && m_AsyncLoadingAssetList[(int)asyinfo.m_Priority].Contains(asyinfo))
{
//取消所有加载完成回调
for (int i = asyinfo.m_DeleFinishCallBacks.Count - 1; i >= 0; i--)
{
AsnycCallBackInfo tempcallback = asyinfo.m_DeleFinishCallBacks;
if (tempcallback != null && res == tempcallback.m_ResObj)
{
tempcallback.Reset();
m_asyncCallBackInfoPool.Recycle(tempcallback);
asyinfo.m_DeleFinishCallBacks.Remove(tempcallback);
}
}
if (asyinfo.m_DeleFinishCallBacks.Count <= 0)
{
asyinfo.Reset();
m_AsyncLoadingAssetList[(int)asyinfo.m_Priority].Remove(asyinfo);
m_asyncResInfoPool.Recycle(asyinfo);
m_asnycloadingAssetDic.Remove(res.m_Crc);
return true;
}
}
return false;
}
/// <summary>
/// 预加载资源 贴图音效等资源
/// </summary>
/// <param name=&#34;path&#34;></param>
public void PreLoadRes(string path)
{
if (string.IsNullOrEmpty(path)) return;
uint crc = Crc32.GetCrc32(path);
//预加载不需要引用计数
ResourceItem item = GetCatchResourceItem(crc, 0);
if (item != null) return;
Object obj = null;
#if UNITY_EDITOR
if (!m_IsLoadFromAssetBundle)
{
item = ABManager.Instance.FinResourceItemByCrc(crc);
if (item.m_Obj != null) obj = item.m_Obj;
else
{
obj = LoadAssetByEditor<Object>(path);
}
}
#endif
if (obj == null)
{
item = ABManager.Instance.LoadResourceAssetBundle(crc);
if (item != null && item.m_AssetBundle != null)
{
if (item.m_Obj != null) obj = item.m_Obj;
else
obj = item.m_AssetBundle.LoadAsset<Object>(item.m_AssetName);
}
}
CacheResource(path, ref item, crc, obj);
//跳场景不清除缓存
item.m_Clear = false;
ReleaseResource(obj, false);
}
/// <summary>
/// 缓存加载的资源
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;item&#34;></param>
/// <param name=&#34;crc&#34;></param>
/// <param name=&#34;obj&#34;></param>
/// <param name=&#34;addrefcount&#34;></param>
void CacheResource(string path, ref ResourceItem item, uint crc, Object obj, int addrefcount = 1)
{
if (item == null)
{
Debug.LogError(&#34;ResourceItem Load Fail path:&#34; + path);
return;
}
//当缓存达到最大数量时 清空缓存
WashOut();
if (obj == null)
Debug.LogError(&#34;ResourceLoad Fail path:&#34; + path);
item.m_Obj = obj;
item.m_Guid = obj.GetInstanceID();
item.m_LastUseTime = Time.realtimeSinceStartup;
item.m_Crc = crc;
item.RefCount += addrefcount;
ResourceItem oldItem = null;
if (m_UsingAssetDic.TryGetValue(crc, out oldItem))
{
m_UsingAssetDic[item.m_Crc] = item;
}
else
{
m_UsingAssetDic.Add(item.m_Crc, item);
}
}
/// <summary>
/// 缓存太多 清除最早没有使用的资源 当内存不足的时候进行清除缓存操作 根据手机内存大小进行判断
/// </summary>
protected void WashOut()
{
//当大于缓存个数时 进行一般资源释放
if (m_noRefResourceMapList.Size() > MAXCACHECOUNT)
{
for (int i = 0; i < MAXCACHECOUNT / 2; i++)
{
ResourceItem item = m_noRefResourceMapList.Back();
DestoryResourceItem(item, true);
}
}
}
/// <summary>
/// 回收资源
/// </summary>
/// <param name=&#34;item&#34;></param>
/// <param name=&#34;destory&#34;></param>
protected void DestoryResourceItem(ResourceItem item, bool destoryCache = false)
{
//判断引用计数 是否还在被其他资源使用
if (item == null || item.RefCount > 0) return;
//缓存
if (!destoryCache)
{
//加入到双向链表表头
m_noRefResourceMapList.InsertToHead(item);
return;
}
if (!m_UsingAssetDic.Remove(item.m_Crc)) return;
//从双向链表中移出
m_noRefResourceMapList.Remove(item);
//不缓存 清空assetbundle 引用
ABManager.Instance.ReleaseAssetBundle(item);
//清空资源对应的对象池
ObjectManager.Instance.ClearPoolObject(item.m_Crc);
if (item.m_Obj != null) item.m_Obj = null;
#if UNITY_EDITOR
Resources.UnloadUnusedAssets();
#endif
}
#if UNITY_EDITOR
protected T LoadAssetByEditor<T>(string path) where T : UnityEngine.Object
{
return UnityEditor.AssetDatabase.LoadAssetAtPath<T>(path);
}
#endif
ResourceItem GetCatchResourceItem(uint crc, int addrefcount = 1)
{
ResourceItem item = null;
if (m_UsingAssetDic.TryGetValue(crc, out item))
{
if (item != null)
{
item.RefCount += addrefcount;
item.m_LastUseTime = Time.realtimeSinceStartup;
//if (item.RefCount<=1)
//{
// m_resourceMapList.Remove(item);
//}
}
}
return item;
}
}
/// <summary>
/// 双向链表封装
/// </summary>
/// <typeparam name=&#34;T&#34;></typeparam>
public class CMapList<T> where T : class, new()
{
public DoubleLinkList<T> m_DLinkList = new DoubleLinkList<T>();
/// <summary>
/// 要用到的值 和它所在链表中的节点
/// </summary>
Dictionary<T, DoubleLinkListNode<T>> m_findNodeDic = new Dictionary<T, DoubleLinkListNode<T>>();
/// <summary>
///析构函数 销毁时会调用
/// </summary>
~CMapList()
{
Clear();
}
/// <summary>
/// 插入节点到头部
/// </summary>
/// <param name=&#34;t&#34;></param>
public void InsertToHead(T t)
{
DoubleLinkListNode<T> node = null;
if (m_findNodeDic.TryGetValue(t, out node) && node != null)
{
m_DLinkList.AddToHead(node);
return;
}
m_DLinkList.AddToHead(t);
m_findNodeDic.Add(t, m_DLinkList.m_HeadNode);
}
/// <summary>
/// 从表尾取出一个节点
/// </summary>
public void Pop()
{
if (m_DLinkList.m_TailNode != null)
Remove(m_DLinkList.m_TailNode.m_CurrentValue);
}
/// <summary>
///移除
/// </summary>
public void Remove(T t)
{
DoubleLinkListNode<T> node = null;
if (!m_findNodeDic.TryGetValue(t, out node) || node == null)
return;
m_DLinkList.RemoveNode(node);
m_findNodeDic.Remove(t);
}
/// <summary>
/// 清空链表
/// </summary>
public void Clear()
{
while (m_DLinkList.m_TailNode != null)
{
Remove(m_DLinkList.m_TailNode.m_CurrentValue);
}
}
/// <summary>
/// 获取尾部节点
/// </summary>
/// <returns></returns>
public T Back()
{
return m_DLinkList.m_TailNode == null ? null : m_DLinkList.m_TailNode.m_CurrentValue;
}
/// <summary>
/// 节点个数
/// </summary>
/// <returns></returns>
public int Size()
{
return m_findNodeDic.Count;
}
/// <summary>
/// 查找节点是否存在
/// </summary>
/// <param name=&#34;t&#34;></param>
/// <returns></returns>
public bool Find(T t)
{
DoubleLinkListNode<T> node = null;
if (!m_findNodeDic.TryGetValue(t, out node) || node == null)
return false;
return true;
}
/// <summary>
/// 刷新某个节点 把节点移动到前面去
/// </summary>
/// <param name=&#34;t&#34;></param>
/// <returns></returns>
public bool Reflesh(T t)
{
DoubleLinkListNode<T> node = null;
if (!m_findNodeDic.TryGetValue(t, out node) || node == null)
return false;
m_DLinkList.MoveToHead(node);
return true;
}
}
}
2.ObjectManager 提供Gameobject类 预制体的加载 卸载
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace ABFrame
{
public class ObjectManager : Singleton<ObjectManager>
{
/// <summary>
/// 对象池节点
/// </summary>
protected Transform m_RecycleTs;
/// <summary>
/// 场景节点
/// </summary>
protected Transform m_SceneTs;
/// <summary>
/// 使用中的对象 对象池
/// </summary>
protected Dictionary<uint, List<ResourceObj>> m_ObjectPoolDic = new Dictionary<uint, List<ResourceObj>>();
/// <summary>
/// 暂存的Resourceobj Dic
/// </summary>
protected Dictionary<int, ResourceObj> m_RescourceObjDic = new Dictionary<int, ResourceObj>();
/// <summary>
/// ResourceObj 对象池
/// </summary>
protected ClassObjectPool<ResourceObj> m_ResourceObjPool = null;
/// <summary>
/// 根据异步的guid 存储ResourceObj 来判断是否时异步加载
/// </summary>
protected Dictionary<int, ResourceObj> m_AsyncResObjs = new Dictionary<int, ResourceObj>();
/// <summary>
/// 初始化
/// </summary>
/// <param name=&#34;recyclets&#34;></param>
public void Init(Transform recyclets,Transform scenets)
{
m_ResourceObjPool = ObjectManager.Instance.GetOrCreateClassPool<ResourceObj>( 500);
this.m_RecycleTs = recyclets;
this.m_RecycleTs.gameObject.SetActive(false);
this.m_SceneTs = scenets;
}
/// <summary>
/// 清空对象池
/// </summary>
public void ClearCache()
{
List<uint> tempList = new List<uint>();
foreach (uint key in m_ObjectPoolDic.Keys)
{
List<ResourceObj> resobjlist = m_ObjectPoolDic[key];
for (int i = resobjlist.Count-1; i >=0; i--)
{
ResourceObj obj=resobjlist;
//可以克隆 且 可以被清除
if (!System.Object.ReferenceEquals(obj.m_CloneObj,null)&&obj.m_bClear)
{
resobjlist.Remove(obj);
m_RescourceObjDic.Remove(obj.m_CloneObj.GetInstanceID());
GameObject.Destroy(obj.m_CloneObj);
obj.Reset();
m_ResourceObjPool.Recycle(obj);
}
}
///判断资源是否全部被清除
if (resobjlist.Count<=0)
{
tempList.Add(key);
}
}
///清除已经卸载 的资源对象池
for (int i = 0; i < tempList.Count; i++)
{
uint tempcrc = tempList;
if (m_ObjectPoolDic.ContainsKey(tempcrc))
{
m_ObjectPoolDic.Remove(tempcrc);
}
}
tempList.Clear();
}
/// <summary>
/// 清除某个资源再对象池中所有的资源
/// </summary>
public void ClearPoolObject(uint crc)
{
List<ResourceObj> reslist = null;
if (!m_ObjectPoolDic.TryGetValue(crc, out reslist) || reslist == null) return;
for (int i = reslist.Count-1; i >=0; i--)
{
ResourceObj resobj = reslist;
//资源可以被清除
if (resobj.m_bClear)
{
reslist.Remove(resobj);
int tempId = resobj.m_CloneObj.GetInstanceID();
GameObject.Destroy(resobj.m_CloneObj);
resobj.Reset();
m_RescourceObjDic.Remove(tempId);
m_ResourceObjPool.Recycle(resobj);
}
}
//对象池中的资源为0进行删除
if (reslist.Count<=0)
{
m_ObjectPoolDic.Remove(crc);
}
}
/// <summary>
/// 根据对象实例直接获取离线数据
/// </summary>
/// <param name=&#34;obj&#34;></param>
/// <returns></returns>
public OffLineData FindOffLineData(GameObject obj)
{
OffLineData offLineData = null;
ResourceObj resobj = null;
m_RescourceObjDic.TryGetValue(obj.GetInstanceID(),out resobj);
if (resobj!=null)
{
offLineData = resobj.m_offLineData;
}
return offLineData;
}
/// <summary>
/// 从对象池里面取对象
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;bclear&#34;></param>
/// <returns></returns>
protected ResourceObj GetResourceObjFromPool(uint crc)
{
List<ResourceObj> list = null;
if (this.m_ObjectPoolDic.TryGetValue(crc,out list)&&list!=null&&list.Count>0)
{
///resourceManager 的引用计数
ResourceManager.Instance.IncreaseResourceRef(crc);
ResourceObj resourceObj = list[0];
list.RemoveAt(0);
GameObject obj = resourceObj.m_CloneObj;
if (!System.Object.ReferenceEquals(obj,null))
{
if (!System.Object.ReferenceEquals(resourceObj.m_offLineData,null))
{
resourceObj.m_offLineData.ResetPrpo();
}
resourceObj.m_Already = false;
#if UNITY_EDITOR
if (obj.name.EndsWith(&#34;(Recycle)&#34;))
{
obj.name = obj.name.Replace(&#34;(Recycle)&#34;,&#34;&#34;);
}
#endif
}
return resourceObj;
}
return null;
}
/// <summary>
/// 取下异步加载
/// </summary>
public void CancelAsyncLoad(int guid)
{
ResourceObj resobj = null;
if (m_AsyncResObjs.TryGetValue(guid,out resobj)&&ResourceManager.Instance.CancelAsyncLoad(resobj))
{
m_AsyncResObjs.Remove(guid);
resobj.Reset();
m_ResourceObjPool.Recycle(resobj);
}
}
/// <summary>
/// 是否正在异步加载
/// </summary>
/// <returns></returns>
public bool IsAsyncLoading(int guid)
{
return m_AsyncResObjs.ContainsKey(guid);
}
/// <summary>
/// 该对象是否是对象池创建的
/// </summary>
/// <param name=&#34;obj&#34;></param>
/// <returns></returns>
public bool IsObjectManangerCreate(GameObject obj)
{
int guid = obj.GetInstanceID();
return m_RescourceObjDic.ContainsKey(guid);
}
/// <summary>
/// 预加载路径
/// </summary>
/// <param name=&#34;path&#34;>路径</param>
/// <param name=&#34;count&#34;>预加载个数</param>
/// <param name=&#34;clear&#34;>场景跳转是否清除</param>
public void PreLoadGameobject(string path,int count=1,bool clear=false)
{
List<GameObject> tempGameobjectList = new List<GameObject>();
for (int i = 0; i < count; i++)
{
GameObject obj = InstantiateObject(path,false,clear);
tempGameobjectList.Add(obj);
}
for (int i = 0; i < count; i++)
{
GameObject obj = tempGameobjectList;
ReleaseObject(obj);
obj = null;
}
tempGameobjectList.Clear();
}
/// <summary>
/// 同步加载
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;bclear&#34;></param>
/// <returns></returns>
public GameObject InstantiateObject(string path, bool isSceneObj=false,bool bclear = true)
{
uint crc = Crc32.GetCrc32(path);
ResourceObj resourceObj = GetResourceObjFromPool(crc);
if (resourceObj==null)
{
resourceObj = m_ResourceObjPool.Spwan(true);
resourceObj.m_Crc = crc;
resourceObj.m_bClear = bclear;
//resourcemanager提供加载方法
resourceObj= ResourceManager.Instance.LoadRecource(path, resourceObj);
if (resourceObj.m_ResItem.m_Obj != null)
{
resourceObj.m_CloneObj = GameObject.Instantiate(resourceObj.m_ResItem.m_Obj) as GameObject;
///赋值离线加载数据
resourceObj.m_offLineData = resourceObj.m_CloneObj.GetComponent<OffLineData>();
}
}
if (isSceneObj) resourceObj.m_CloneObj.transform.SetParent(this.m_SceneTs, false);
int tempId = resourceObj.m_CloneObj.GetInstanceID();
if (!m_RescourceObjDic.ContainsKey(tempId))
m_RescourceObjDic.Add(tempId,resourceObj);
return resourceObj.m_CloneObj;
}
/// <summary>
/// 异步资源加载
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;finishCallback&#34;>加载完成回调</param>
/// <param name=&#34;loadResPriority&#34;></param>
/// <param name=&#34;isSceneObj&#34;></param>
/// <param name=&#34;param1&#34;></param>
/// <param name=&#34;param2&#34;></param>
/// <param name=&#34;param3&#34;></param>
/// <param name=&#34;bclear&#34;>跳场景是否删除</param>
/// <returns></returns>
public long InstantiateObjectAsync(string path, OnAsyncObjFinishDele finishCallback, LoadResPriority loadResPriority, bool isSceneObj = false, object param1 = null, object param2 = null, object param3 = null, bool bclear=true)
{
if (string.IsNullOrEmpty(path)) return 0;
uint crc = Crc32.GetCrc32(path);
ResourceObj obj = GetResourceObjFromPool(crc);
if (obj!=null)
{
if (isSceneObj)
obj.m_CloneObj.transform.SetParent(this.m_SceneTs,false);
finishCallback?.Invoke(path, obj.m_CloneObj, param1, param2, param3);
return obj.m_Guid;
}
int guid = ResourceManager.Instance.CreateGuid();
obj = m_ResourceObjPool.Spwan(true);
obj.m_Crc = crc;
obj.m_bClear = bclear;
obj.m_setSceneParent = isSceneObj;
obj.m_FinishCallback = finishCallback;
obj.m_Guid = guid;
obj.Param1 = param1;
obj.Param2 =param2;
obj.Param3 = param3;
//调用resourmanager 异步加载
ResourceManager.Instance.AsnycLoadInstanceResource(path,obj, OnLoadInstanceObjFinish, loadResPriority,param1,param2,param3,crc);
return guid;
}
/// <summary>
/// 当实例化资源加载完毕时的回调
/// </summary>
/// <param name=&#34;path&#34;>路径</param>
/// <param name=&#34;obj&#34;>中间类</param>
/// <param name=&#34;param1&#34;></param>
/// <param name=&#34;param2&#34;></param>
/// <param name=&#34;param3&#34;></param>
protected void OnLoadInstanceObjFinish(string path, ResourceObj resobj, object param1 = null, object param2 = null, object param3 = null)
{
if (resobj == null) return;
if (resobj.m_ResItem.m_Obj==null)
{
#if UNITY_EDITOR
Debug.LogError(&#34;异步加载实例化资源错误:&#34;+path);
#endif
}
else
{
resobj.m_CloneObj = GameObject.Instantiate(resobj.m_ResItem.m_Obj) as GameObject;
///赋值离线加载数据
resobj.m_offLineData = resobj.m_CloneObj.GetComponent<OffLineData>();
}
if (resobj.m_CloneObj!=null&&resobj.m_setSceneParent)
{
resobj.m_CloneObj.transform.SetParent(this.m_SceneTs,false);
}
///加载完成从正在加载的异步中移除
if (m_AsyncResObjs.ContainsKey(resobj.m_Guid))
{
m_AsyncResObjs.Remove(resobj.m_Guid);
}
if (resobj.m_FinishCallback!=null)
{
int tempId = resobj.m_CloneObj.GetInstanceID();
if (!m_RescourceObjDic.ContainsKey(tempId))
{
m_RescourceObjDic.Add(tempId,resobj);
}
resobj.m_FinishCallback(path,resobj.m_CloneObj,param1,param2,param3);
}
}
/// <summary>
///回收资源
/// </summary>
/// <param name=&#34;obj&#34;></param>
/// <param name=&#34;maxCacheCount&#34;></param>
/// <param name=&#34;destorycache&#34;></param>
/// <param name=&#34;recycleParent&#34;></param>
public void ReleaseObject(GameObject obj,int maxCacheCount=-1,bool destorycache=false,bool recycleParent=true)
{
if (obj == null) return;
int guid = obj.GetInstanceID();
ResourceObj resobj = null;
if (!m_RescourceObjDic.TryGetValue(guid,out resobj))
{
Debug.LogError(&#34;对象不是ObjectManager 创建的&#34; +obj.name);
return;
}
if (resobj==null)
{
Debug.LogError(&#34;缓存的ResourceObj为空&#34;);
return;
}
if (resobj.m_Already)
{
Debug.LogError(&#34;该对象已经放回对象池了 检查自己是否清空引用!&#34;);
return;
}
#if UNITY_EDITOR
obj.name += &#34;(Recycle)&#34;;
#endif
List<ResourceObj> list = null;
///不缓存
if (maxCacheCount==0)
{
m_RescourceObjDic.Remove(guid);
ResourceManager.Instance.ReleaseResource(resobj,destorycache);
resobj.Reset();
m_ResourceObjPool.Recycle(resobj);
}
//回收到对象池
else
{
if (!m_ObjectPoolDic.TryGetValue(resobj.m_Crc,out list)||list==null)
{
list = new List<ResourceObj>();
m_ObjectPoolDic.Add(resobj.m_Crc,list);
}
if (resobj.m_CloneObj)
{
if (recycleParent)
resobj.m_CloneObj.transform.SetParent(this.m_RecycleTs);
else
resobj.m_CloneObj.SetActive(false);
}
if (maxCacheCount < 0 || list.Count < maxCacheCount)
{
list.Add(resobj);
resobj.m_Already = true;
//resourceManager 做一个引用计数
ResourceManager.Instance.DecreaseResourceRef(resobj);
}
//达到最大缓存个数
else
{
m_RescourceObjDic.Remove(guid);
ResourceManager.Instance.ReleaseResource(resobj, destorycache);
resobj.Reset();
m_ResourceObjPool.Recycle(resobj);
}
}
}
#region 类对象池使用
protected Dictionary<Type, object> m_ClassPoolDic = new Dictionary<Type, object>();
/// <summary>
/// 创建类对象池
/// </summary>
/// <typeparam name=&#34;T&#34;></typeparam>
/// <param name=&#34;max&#34;></param>
/// <returns></returns>
public ClassObjectPool<T> GetOrCreateClassPool<T>(int max) where T : class, new()
{
Type type = typeof(T);
object outobj = null;
if (!m_ClassPoolDic.TryGetValue(type, out outobj)|| outobj==null)
{
ClassObjectPool<T> pool = new ClassObjectPool<T>(max);
m_ClassPoolDic.Add(type,pool);
return pool;
}
return outobj as ClassObjectPool<T>;
}
/// <summary>
/// 创建对象池且获取一个对象
/// </summary>
/// <typeparam name=&#34;T&#34;></typeparam>
/// <param name=&#34;maxcount&#34;></param>
/// <returns></returns>
public T NewClassObjectFromPool<T>(int maxcount) where T : class, new()
{
ClassObjectPool<T> pool = new ClassObjectPool<T>(maxcount);
if (pool == null) return null;
return pool.Spwan(true);
}
#endregion
}
}
Orville&#39;s Ideas and Interestsusing System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
namespace ABFrame
{
public class ObjectManager : Singleton<ObjectManager>
{
/// <summary>
/// 对象池节点
/// </summary>
protected Transform m_RecycleTs;
/// <summary>
/// 场景节点
/// </summary>
protected Transform m_SceneTs;
/// <summary>
/// 使用中的对象 对象池
/// </summary>
protected Dictionary<uint, List<ResourceObj>> m_ObjectPoolDic = new Dictionary<uint, List<ResourceObj>>();
/// <summary>
/// 暂存的Resourceobj Dic
/// </summary>
protected Dictionary<int, ResourceObj> m_RescourceObjDic = new Dictionary<int, ResourceObj>();
/// <summary>
/// ResourceObj 对象池
/// </summary>
protected ClassObjectPool<ResourceObj> m_ResourceObjPool = null;
/// <summary>
/// 根据异步的guid 存储ResourceObj 来判断是否时异步加载
/// </summary>
protected Dictionary<int, ResourceObj> m_AsyncResObjs = new Dictionary<int, ResourceObj>();
/// <summary>
/// 初始化
/// </summary>
/// <param name=&#34;recyclets&#34;></param>
public void Init(Transform recyclets,Transform scenets)
{
m_ResourceObjPool = ObjectManager.Instance.GetOrCreateClassPool<ResourceObj>( 500);
this.m_RecycleTs = recyclets;
this.m_RecycleTs.gameObject.SetActive(false);
this.m_SceneTs = scenets;
}
/// <summary>
/// 根据对象实例直接获取离线数据
/// </summary>
/// <param name=&#34;obj&#34;></param>
/// <returns></returns>
public OffLineData FindOffLineData(GameObject obj)
{
OffLineData offLineData = null;
ResourceObj resobj = null;
m_RescourceObjDic.TryGetValue(obj.GetInstanceID(),out resobj);
if (resobj!=null)
{
offLineData = resobj.m_offLineData;
}
return offLineData;
}
/// <summary>
/// 从对象池里面取对象
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;bclear&#34;></param>
/// <returns></returns>
protected ResourceObj GetResourceObjFromPool(uint crc)
{
List<ResourceObj> list = null;
if (this.m_ObjectPoolDic.TryGetValue(crc,out list)&&list!=null&&list.Count>0)
{
///resourceManager 的引用计数
ResourceManager.Instance.IncreaseResourceRef(crc);
ResourceObj resourceObj = list[0];
list.RemoveAt(0);
GameObject obj = resourceObj.m_CloneObj;
if (!System.Object.ReferenceEquals(obj,null))
{
if (!System.Object.ReferenceEquals(resourceObj.m_offLineData,null))
{
resourceObj.m_offLineData.ResetPrpo();
}
resourceObj.m_Already = false;
#if UNITY_EDITOR
if (obj.name.EndsWith(&#34;(Recycle)&#34;))
{
obj.name = obj.name.Replace(&#34;(Recycle)&#34;,&#34;&#34;);
}
#endif
}
return resourceObj;
}
return null;
}
/// <summary>
/// 取下异步加载
/// </summary>
public void CancelAsyncLoad(int guid)
{
ResourceObj resobj = null;
if (m_AsyncResObjs.TryGetValue(guid,out resobj)&&ResourceManager.Instance.CancelAsyncLoad(resobj))
{
m_AsyncResObjs.Remove(guid);
resobj.Reset();
m_ResourceObjPool.Recycle(resobj);
}
}
/// <summary>
/// 是否正在异步加载
/// </summary>
/// <returns></returns>
public bool IsAsyncLoading(int guid)
{
return m_AsyncResObjs.ContainsKey(guid);
}
/// <summary>
/// 该对象是否是对象池创建的
/// </summary>
/// <param name=&#34;obj&#34;></param>
/// <returns></returns>
public bool IsObjectManangerCreate(GameObject obj)
{
int guid = obj.GetInstanceID();
return m_RescourceObjDic.ContainsKey(guid);
}
/// <summary>
/// 同步加载
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;bclear&#34;></param>
/// <returns></returns>
public GameObject InstantiateObject(string path, bool isSceneObj=false,bool bclear = true)
{
uint crc = Crc32.GetCrc32(path);
ResourceObj resourceObj = GetResourceObjFromPool(crc);
if (resourceObj==null)
{
resourceObj = m_ResourceObjPool.Spwan(true);
resourceObj.m_Crc = crc;
resourceObj.m_bClear = bclear;
//resourcemanager提供加载方法
resourceObj= ResourceManager.Instance.LoadRecource(path, resourceObj);
if (resourceObj.m_ResItem.m_Obj != null)
{
resourceObj.m_CloneObj = GameObject.Instantiate(resourceObj.m_ResItem.m_Obj) as GameObject;
///赋值离线加载数据
resourceObj.m_offLineData = resourceObj.m_CloneObj.GetComponent<OffLineData>();
}
}
if (isSceneObj) resourceObj.m_CloneObj.transform.SetParent(this.m_SceneTs, false);
int tempId = resourceObj.m_CloneObj.GetInstanceID();
if (!m_RescourceObjDic.ContainsKey(tempId))
m_RescourceObjDic.Add(tempId,resourceObj);
return resourceObj.m_CloneObj;
}
/// <summary>
/// 异步资源加载
/// </summary>
/// <param name=&#34;path&#34;></param>
/// <param name=&#34;finishCallback&#34;>加载完成回调</param>
/// <param name=&#34;loadResPriority&#34;></param>
/// <param name=&#34;isSceneObj&#34;></param>
/// <param name=&#34;param1&#34;></param>
/// <param name=&#34;param2&#34;></param>
/// <param name=&#34;param3&#34;></param>
/// <param name=&#34;bclear&#34;>跳场景是否删除</param>
/// <returns></returns>
public long InstantiateObjectAsync(string path, OnAsyncObjFinishDele finishCallback, LoadResPriority loadResPriority, bool isSceneObj = false, object param1 = null, object param2 = null, object param3 = null, bool bclear=true)
{
if (string.IsNullOrEmpty(path)) return 0;
uint crc = Crc32.GetCrc32(path);
ResourceObj obj = GetResourceObjFromPool(crc);
if (obj!=null)
{
if (isSceneObj)
obj.m_CloneObj.transform.SetParent(this.m_SceneTs,false);
finishCallback?.Invoke(path, obj.m_CloneObj, param1, param2, param3);
return obj.m_Guid;
}
int guid = ResourceManager.Instance.CreateGuid();
obj = m_ResourceObjPool.Spwan(true);
obj.m_Crc = crc;
obj.m_bClear = bclear;
obj.m_setSceneParent = isSceneObj;
obj.m_FinishCallback = finishCallback;
obj.m_Guid = guid;
obj.Param1 = param1;
obj.Param2 =param2;
obj.Param3 = param3;
//调用resourmanager 异步加载
ResourceManager.Instance.AsnycLoadInstanceResource(path,obj, OnLoadInstanceObjFinish, loadResPriority,param1,param2,param3,crc);
return guid;
}
/// <summary>
/// 当实例化资源加载完毕时的回调
/// </summary>
/// <param name=&#34;path&#34;>路径</param>
/// <param name=&#34;obj&#34;>中间类</param>
/// <param name=&#34;param1&#34;></param>
/// <param name=&#34;param2&#34;></param>
/// <param name=&#34;param3&#34;></param>
protected void OnLoadInstanceObjFinish(string path, ResourceObj resobj, object param1 = null, object param2 = null, object param3 = null)
{
if (resobj == null) return;
if (resobj.m_ResItem.m_Obj==null)
{
#if UNITY_EDITOR
Debug.LogError(&#34;异步加载实例化资源错误:&#34;+path);
#endif
}
else
{
resobj.m_CloneObj = GameObject.Instantiate(resobj.m_ResItem.m_Obj) as GameObject;
///赋值离线加载数据
resobj.m_offLineData = resobj.m_CloneObj.GetComponent<OffLineData>();
}
if (resobj.m_CloneObj!=null&&resobj.m_setSceneParent)
{
resobj.m_CloneObj.transform.SetParent(this.m_SceneTs,false);
}
///加载完成从正在加载的异步中移除
if (m_AsyncResObjs.ContainsKey(resobj.m_Guid))
{
m_AsyncResObjs.Remove(resobj.m_Guid);
}
if (resobj.m_FinishCallback!=null)
{
int tempId = resobj.m_CloneObj.GetInstanceID();
if (!m_RescourceObjDic.ContainsKey(tempId))
{
m_RescourceObjDic.Add(tempId,resobj);
}
resobj.m_FinishCallback(path,resobj.m_CloneObj,param1,param2,param3);
}
}
/// <summary>
///回收资源
/// </summary>
/// <param name=&#34;obj&#34;></param>
/// <param name=&#34;maxCacheCount&#34;></param>
/// <param name=&#34;destorycache&#34;></param>
/// <param name=&#34;recycleParent&#34;></param>
public void ReleaseObject(GameObject obj,int maxCacheCount=-1,bool destorycache=false,bool recycleParent=true)
{
if (obj == null) return;
int guid = obj.GetInstanceID();
ResourceObj resobj = null;
if (!m_RescourceObjDic.TryGetValue(guid,out resobj))
{
Debug.LogError(&#34;对象不是ObjectManager 创建的&#34; +obj.name);
return;
}
if (resobj==null)
{
Debug.LogError(&#34;缓存的ResourceObj为空&#34;);
return;
}
if (resobj.m_Already)
{
Debug.LogError(&#34;该对象已经放回对象池了 检查自己是否清空引用!&#34;);
return;
}
#if UNITY_EDITOR
obj.name += &#34;(Recycle)&#34;;
#endif
List<ResourceObj> list = null;
///不缓存
if (maxCacheCount==0)
{
m_RescourceObjDic.Remove(guid);
ResourceManager.Instance.ReleaseResource(resobj,destorycache);
resobj.Reset();
m_ResourceObjPool.Recycle(resobj);
}
//回收到对象池
else
{
if (!m_ObjectPoolDic.TryGetValue(resobj.m_Crc,out list)||list==null)
{
list = new List<ResourceObj>();
m_ObjectPoolDic.Add(resobj.m_Crc,list);
}
if (resobj.m_CloneObj)
{
if (recycleParent)
resobj.m_CloneObj.transform.SetParent(this.m_RecycleTs);
else
resobj.m_CloneObj.SetActive(false);
}
if (maxCacheCount < 0 || list.Count < maxCacheCount)
{
list.Add(resobj);
resobj.m_Already = true;
//resourceManager 做一个引用计数
ResourceManager.Instance.DecreaseResourceRef(resobj);
}
//达到最大缓存个数
else
{
m_RescourceObjDic.Remove(guid);
ResourceManager.Instance.ReleaseResource(resobj, destorycache);
resobj.Reset();
m_ResourceObjPool.Recycle(resobj);
}
}
}
}
字数限制 不能发全部 需要的请移步码云 |
|