关于 ResKit 中 ResLoader 用法上的可能的简化。
Hocchi01 opened this issue · 1 comments
Hocchi01 commented
目前我看文档的 ResLoader 推荐用法是在每个需要加载资源的脚本中申请 ResLoader 并在销毁时回收:
public class TestResKit : MonoBehaviour
{
ResLoader mResLoader = ResLoader.Allocate();
void Destroy()
{
mResLoader.Recycle2Cache();
mResLoader = null;
}
}
秉持着减少样板代码的原则(尤其是在某个对象没有销毁事件,但却要为 ResLoader 额外编写 Destroy 方法)
我目前在项目中主要通过静态扩展(未修改 QF 项目代码)实现了用法上的简化:
public class TestResKit : MonoBehaviour, ICanLoadResource
{
void Func()
{
// 某个需要加载资源的地方
this.GetResLoader().LoadSync<GameObject>(...);
}
}
- 附加 ICanLoadResource 接口,通过该接口的静态扩展方法获取 ResLoader
- 无需在脚本中记录分配的 ResLoader,接口背后自动维护
- 无需再编写回收代码,gameObject 销毁后自动回收
实现思路:维护一个静态的关于<对象的HashCode,ResLoader>的字典,对象首次调用GetResLoader()
方法会为其分配 ResLoader 并记录在字典中,后续调用则从字典中取 ResLoader;销毁时自动回收则是和 QF 中自动注销实现思路一致,为 gameObject 追加专门响应销毁时事件的 Component 并添加回收回调。代码如下:
public interface ICanLoadResource
{
}
public static class CanLoadResourceExtension
{
private static readonly Dictionary<int, ResLoader> _resLoaderDict = new Dictionary<int, ResLoader>();
public static ResLoader GetResLoader(this ICanLoadResource obj)
{
int hashCode = obj.GetHashCode();
// 对象首次调用 GetResLoader
if (!_resLoaderDict.ContainsKey(hashCode))
{
_resLoaderDict.Add(hashCode, ResLoader.Allocate());
// 首次调用,若是组件则默认在销毁时注册行为:回收资源引用
if (obj is Component)
{
var lm = (obj as Component).gameObject.GetComponent<LifecycleModule>();
if (!lm)
{
lm = (obj as Component).gameObject.AddComponent<LifecycleModule>();
}
lm.OnDestroyed += () =>
{
if (_resLoaderDict.ContainsKey(hashCode))
{
_resLoaderDict[hashCode].Recycle2Cache();
_resLoaderDict.Remove(hashCode);
}
};
}
}
return _resLoaderDict[hashCode];
}
// 用于手动自行注销
public static void RecycleResLoader(this ICanLoadResource obj)
{
int hashCode = obj.GetHashCode();
if (_resLoaderDict.ContainsKey(hashCode))
{
_resLoaderDict[hashCode].Recycle2Cache();
_resLoaderDict.Remove(hashCode);
}
}
}
附:其中 LifecycleModule
public class LifecycleModule : MonoBehaviour
{
public Action OnDestroyed = () => { };
private void OnDestroy()
{
OnDestroyed();
}
}
可能存在的问题:不同对象的 HashCode 相同的情况,查阅了一些资料,不同对象应该是对应着不同的 HashCode。也可以考虑使用其他唯一性的键值。
Bian-Sh commented
收到