基于Unity YooAsset自动化资源管理框架,附源代码

源代码地址在最后,非常感谢你的观看

1.繁琐的内存管理,在C++时代对内存管理需要new 和 Delete相对应,Delete之后还需要把指针置空,不然会导致内存泄漏或者野指针的问题。

2.市面上普遍的资源管理采用Index计数方式管理,当计数为0的时候就会在内存不足或者特定的地方释放内存比如场景切换。

问题:Index计数方式过于繁琐,需要资源加载和释放完全对应,不然就会有内存泄漏风险。

思考:采用引用计数方式来处理内存释放,当引用数据为Null的时候,释放这个内存。

实践:

环境:Unity 2022.3.62

YooAsset版本:2.3.16

1.点击加载资源,我们可以看到YooAsset的AssrtBundle里面已经有多条加载到内存的数据:

2.我们点击卸载资源,会发现YooAsset的资源已经全部被清空了。

3.原理和核心代码,通过传入GameObject的引用,来保持资源的存活,当这个资源的GameObject的引用不存在的时候,就判定这个资源可以释放了。

cs 复制代码
 public async void LoadAssetAsync<T>(string path,GameObject refObj,Action<T> call)where T : UnityEngine.Object
    {
        AssetHandle assetHandle = _assetHelper.Package.LoadAssetAsync<T>(path);
        await assetHandle.Task;
        if (assetHandle.AssetObject == null)
        {
            Debug.LogError($"资源加载错误LoadAssetAsync:{path}");
            return;
        }

        if (!_autoRefData.TryGetValue(path, out ResAutoRefData resAutoRefData))
        {
            resAutoRefData = new ResAutoRefData(assetHandle);
            _autoRefData.Add(path, resAutoRefData);
        }
        resAutoRefData.RefObj.Add(refObj);
        T asset = assetHandle.AssetObject as T;
        call?.Invoke(asset);
    }

4.释放资源的代码(可以看到只检测了GameObject被释放的资源):

cs 复制代码
 //释放引用计数为0的资源
    public async UniTask UnloadAsset()
    {
        //因为GameObject销毁是在本帧的最后阶段才会消耗,所以要等待帧结束
        await UniTask.WaitForEndOfFrame();
        _removeHandle.Clear();
        foreach (string path in _autoRefData.Keys)
        {
            ResAutoRefData resAutoRef = _autoRefData[path];
            List<GameObject> refObjs = resAutoRef.RefObj;
            int refIndex = 0;
            foreach (GameObject refObj in refObjs)
            {
                if (refObj != null)
                {
                    refIndex++;
                    break;
                }
            }
            if (refIndex == 0)
            {
                resAutoRef.Handle.Release();
                _removeHandle.Add(path);
            }
        }

        //移除资源的加载
        if (_removeHandle.Count != 0)
        {
            foreach (string path in _removeHandle)
            {
                _autoRefData.Remove(path);
            }
        }
        UnloadUnusedAssetsOperation unloadUnused = _assetHelper.Package.UnloadUnusedAssetsAsync();
        await unloadUnused.Task;
    }

源代码地址:YooAssetAutoMemory: 基于Unity YooAsset自动化资源管理框架。

相关推荐
知已难寻9 小时前
Docker 入门:容器技术与 Docker 基础
java·运维·服务器·docker·云原生·容器
Alluxio16 小时前
Alluxio + OCI:为 AI 工作负载实现亚毫秒访问延迟与可扩展吞吐
运维·数据库·人工智能·分布式·缓存·ai·语言模型
goehou20 小时前
让 AI 替我操作这台电脑,先把手能伸多远定下来
windows·自动化·权限管理·ai agent
Sayai21 小时前
Neo4j 图数据质量检查实战:环路检测、孤立节点与连通分量,两条 Cypher 引出的数据体检清单(含变长路径性能陷阱)
运维·neo4j·图数据库·数据质量·cypher
Elastic 中国社区官方博客21 小时前
更少的位数,相同的召回率:DiskBBQ 更保守的自动校准扫描
大数据·运维·开发语言·人工智能·elasticsearch·搜索引擎
方便面不加香菜21 小时前
Docker Volume -- 管理卷Volume详解
运维·docker·容器
Frankie_stand1 天前
测试自动化实战指南:从脚本化、自动判据到 CI 集成的完整落地路径
android·ci/cd·自动化
沫璃染墨1 天前
从零入门计算机网络系列(十八):TCP连接管理详解——从三次握手与四次挥手到TIME_WAIT机制
运维·服务器·网络·c++·网络协议·tcp/ip·tcp
Felven1 天前
华为鲲鹏920s芯片serdestool工具使用说明
linux·运维·服务器·华为·鲲鹏920·serdestool
江湖有缘1 天前
Docker实战 | 使用Docker部署lemonitor镜像站点列表程序
运维·docker·容器