需求环境
在上一级的【解决方案】文章中,我们设计出了动态加载资源的业务流程,而这一节,我们就通过一些简单的代码,来实现出业务流程中的效果。
吸取之前文章的经验,如果按照正式项目的规格开发,本篇文章就会非常冗余,所以我们优化一下,仅仅针对技术点进行讲解与释放,具体与工程相关的,我们就不再文章中讲解,但你可以在Github的工程中找到它们。、
现在,我们先回顾一下之前所设计出的业务流程。
那么,在这个业务流程中,我可以定义出在游戏运行时,资源有三种状态:
1、未加载
2、已经加载
3、已可以释放
三种状态了某个资源此时的最佳使用环境,也就是说,接下来需要使用的资源,我就放到池中,而接下来很长一段时间内不需要使用的资源,我就彻底释放掉。以确保程序的内存总是在可控范围之内。
设计
为了达到这样的目的,我们就需要划分三个模块去做。
1、最基础的资源加载,与池。
2、资源加载的自动记录过程。
3、资源加载的动态释放与加载过程。
池
首先,池,因为我们是模拟,所以这个就比较容易实现,在现实工程中,则可能需要考虑不同资源类型的具体逻辑。
///
/// 池
///
Dictionary<int, Stack> PoolDict = new Dictionary();
///
/// 正在工作的资源对象
///
Dictionary<Object, int> WorkingPool = new Dictionary();
首先是2个定义,一个是回收池,一个是工作区,工作区用来反向查资源的ID,同时,也检测是否有资源是通过其他方法加载的,理论上,游戏内不应该存在其他的途径来加载资源。
接下来,就是2份逻辑代码,一个是创建资源,它用到了之前我们实现的资源管理器,另一个是回收资源。
///
/// 得到资源,如果池子里有,直接拿,否则创建
///
///资源类型,方便上级使用
///资源id
///
public T getObj(int _id)
where T : Object
{
Object temp = null;
//池子里有就取一个
if (PoolDict.ContainsKey(_id) &&
PoolDict[_id].Count > 0)
temp = PoolDict[_id].Pop();
//如果池子里没有,就创建一个新的
temp = DJAssetsManager.GetInstance().Load(_id);
if (temp as T == null)
{
Debug.LogError("代码写错了或资源配错了,传入的资源id与希望得到的类型不匹配");
Debug.Break();
return null;
}
//加入工作池
WorkingPool.Add(temp,_id);
return (T)temp;
}
///
/// 回收资源
///
public void recObj(Object _obj)
{
if (WorkingPool.ContainsKey(_obj))
{
//正常回收
int id = WorkingPool[_obj];
WorkingPool.Remove(_obj);
if (PoolDict.ContainsKey(id) == false)
PoolDict.Add(id, new Stack());
PoolDict[id].Push(_obj);
}
else
{
//不属于池管理的资源直接删除掉。不过得打出警告,按理说不应该存在
Debug.LogWarning("检测到非法创建的资源:" + _obj.name);
Destroy(_obj);