U3D资源加载框架迭代笔记
V0.0.1
一个初始的资源加载,卸载功能,list记录加载过的资源,这里只用Resources类作为演示,不用AB包加载。
using System.Collections.Generic; using UnityEngine; public class ResLoader { //资源加载记录 private List<UnityEngine.Object> mLoadedAssets = new List<UnityEngine.Object>(); //加载资源 public T LoadAsset<T>(string assetName,string path) where T : Object { var asset = mLoadedAssets.Find(loadedAsset => loadedAsset.name == assetName)as T; if (asset != null) { return asset; } asset = Resources.Load<T>(path + "/" + assetName); mLoadedAssets.Add(asset); return asset; } //卸载资源 public void UnLoadAllAssets() { foreach (Object loadedAsset in mLoadedAssets) { Resources.UnloadAsset(loadedAsset); } mLoadedAssets.Clear(); mLoadedAssets = null; } }
V0.0.2
1.将资源封装到Res类中
2.Res类添加引用计数功能,统计资源被引用的次数
3.设计引用计数模块
4.ResLoader代码重构,加入可全局访问的“资源加载记录池”
引用计数模块设计:
using System.Collections; using System.Collections.Generic; using UnityEngine; //引用计数 public interface IRefCounter { int RefCount { get; } void Retain(object refOwner = null); void Release(object refOwner = null); } public class RcBase : IRefCounter { public RcBase() { RefCount = 0; } public int RefCount { get; private set; } public void Release(object refOwner = null) { RefCount--; if (RefCount == 0) { OnZeroRef(); } } public void Retain(object refOwner = null) { RefCount++; } protected virtual void OnZeroRef() { } }
对资源进行封装:
using System.Collections; using System.Collections.Generic; using UnityEngine; //对 asset进行封装,并添加引用计数功能 public class Res :RcBase { public Object Asset { get; private set; } public string Name { get { return Asset.name; } } //初始化构造方法 public Res(Object asset) { Asset = asset; } protected override void OnZeroRef() { base.OnZeroRef(); //卸载资源 Resources.UnloadAsset(Asset); ResLoader.sharedLoadedRes.Remove(this); } }
ResLoader代码重构:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ResLoader { //所有ResLoader对象的加载记录池 public static List<Res> sharedLoadedRes = new List<Res>(); //该对象的加载资源记录 private List<Res> mResRecord = new List<Res>(); public T LoadAsset<T>(string assetName,string path) where T : Object { //如果该对象已经加载了资源 var res = mResRecord.Find(loadedAsset => loadedAsset.Name == assetName); if (res != null) { return res.Asset as T; } //如果全局缓存了资源 res = sharedLoadedRes.Find(loadedAsset => loadedAsset.Name == assetName); if (res != null) { res.Retain(); return res.Asset as T; } //如果没有缓存资源,从Resources文件夹里加载 var asset = Resources.Load<T>(path + "/" + assetName); res = new Res(asset); res.Retain(); //将加载后的资源记录到池中 mResRecord.Add(res); sharedLoadedRes.Add(res); return res.Asset as T; } //只卸载该ResLoader对象加载过的资源,其他ResLoader对象加载的资源不卸载 public void UnLoadAllAssets() { foreach (Res loadedAsset in mResRecord) { Resources.UnloadAsset(loadedAsset.Asset); } mResRecord.Clear(); mResRecord = null; } }