浅谈资源加载 -AssetBundleSystem

2023-05-16

AssetBundleSystem

Ps:稍微抽点时间写一下这个,这个小项目完成度80%左右,在年初2月份的时候就完成的差不多了,因为各种原因处于半搁浅的阶段,现在官方出了Addressable Assets System ,遂和大伙谈谈这个资源加载。

真的是懒到极致了。

起个头:

项目中代码只是占了体积的一小部分,资源是项目中体积的大头,同时也时刻影响着加载和内存。所以合理的使用和管理资源成为了一个项目中比较重要的部分,在此重要分为两个部分 Editor 和代码部分。

代码部分:

众所周知,Unity5之后除了Assetbundle,这个看似方便的东西,实际上如果不对它进行一个合理的管控,对于包体和内存都是一个不好的发展。它会通过相同的assetbundlename将所有引用的(未打成ab)资源的都打到一个ab包中,冗余就变得不可避免;但是如果做到0冗余,则又会增加IO的开销(小文件太多)。所以就得由代码或者工具进行一些合适的管控。(以assetbundle为例子)

加载部分:

初步设想需求就是这样:

需要梳理清楚这个资源是否有对其他资源的依赖,否则可能导致加载出来的对象关键数据丢失或者整个加载失败。良好的事件通知机制:当加载失败或者加载成功的能及时正确的通知到调用方。良好的异常/失败处理机制:当一个对象加载过程中其中某个步骤失败了,那么之前可能会有先一步加载的资源(比如依赖资源)可能会无法正确的释放,导致泄漏。良好的日志信息:方便开发者准确的把握流程和加载过程中的情况,方便维护相关内容。同时根据功能分多个system。

说到运行时的加载的资源会有2种:Resources的资源,通过Resources.Load<T>(xxxx)的方式进行同步加载。AssetBundle的资源,通过AssetBundle.LoadFromFile /LoadFromMemory等同步和Async系列的异步接口进行加载。Resouces下的资源Unity自动维护引用关系,直接Load足以。而对于细分依赖关系的Assetbundle资源,则需要自行维护资源加载。

1.通过AssetDatabase.GetAssetBundleDependencies 或EditorUtility.CollectDependencies来进行资源依赖的收集。 2.加载过程,在异步情况下如果有正在进行的同目标Task,则把委托事件同等的传递给Task方,先行加载依赖(如果内存中已经存在相关的资源则不需要加载),并记录资源引用。 3.当依赖加载完成时进行目标资源的加载,并记录引用,当真正的主体资源被成功加载的时候则对其依赖进行引用计数的维护(这样即便在加载流程中发生异常也能保证依赖引用计数的正确性,如果提前在依赖加载阶段进行计数,则可能会导致在异常发生的时候的泄漏问题出现)。 4.事件通知,完成或者失败通知到调用方,如果是Prefab因为在unity需要真正使用需要Instaniate所以在Instaniate层使用WeakReference或者挂接AliveTrakcer(随便取名的监听生命周期的脚本函数)来维护实例引用。如果是其他比如Font,Text,Texture资源,则在调用方进行SelfReference等非实例化对象的记录。

举例:摘出一段代码:

判断任务类型(任务尽量单一,不要涉及太多,不容易维护,所以这里基本就是一个task对一个资源),然后进行加载,先加载依赖,当依赖完成则进行目标资源的加载

if (task.IsLoad())
{
    LoadDependency(ref context, ref task, ref result);

    LoadSubTask(ref context, ref task, ref result);

    int finishcnt;
    int totalcnt;
    if (task.IsSubAllDone(ref context, out finishcnt, out totalcnt) )//
    {

        GameAssetBundle gameAssetBundle;
        if (context.Cache.GetAssetBundle(task.AssetBundleName, out gameAssetBundle))
        {
            if (task.Result.ProgresCallback != null)
            {
ProgressArgs progressArgs = new ProgressArgs((float)finishcnt / (totalcnt + 1), 0, task.AssetPath, false);
task.Result.ProgresCallback(ref progressArgs);
            }

            Load(ref context, ref task, ref gameAssetBundle, ref result, true);
            context.Cache.UpdateAssetBundle(task.AssetBundleName, ref gameAssetBundle);
        }
        else
        {
            Debug.LogErrorFormat("not found gameassetbundle :{0}", task.AssetBundleName);
            AddException(ref context, task.AssetPath);
        }

    }
    else
    {
        if (task.Result.ProgresCallback != null)
        {
            ProgressArgs progressArgs = new ProgressArgs((float)finishcnt / (totalcnt + 1), 0, task.AssetPath, false);
            task.Result.ProgresCallback(ref progressArgs);
        }
    }
}

gameobject因为会涉及到实例化,所以需要维护实例化的引用, 像普通的asset资源或者场景资源,则通过依赖引用和自引用的方式进行引用维护,最后根据不同的策略进行管理。

内存管理:

当一些资源已经使用完毕或者完全看不见的时候,会需要即时的对资源进行一个卸载操作,或者要加载一些资源则可以直接使用缓存中的资源。常规一般就是通过已经加载对象的引用计数和卸载策略(比如卸载周期,对未来即将到来的加载调用做一个等待周期结束再实际卸载的操作)来判断资源是否需要卸载,卸载策略主要看你关注的重心是什么,如果你的重心是内存,则即时快速的卸载或者对内存阀值的控制是好的方案;如果你关心的重心是帧率,则异步的加载和较长时间的资源内存驻留是个合适的方案。一些老资源则可以直接使用缓存中的资源。对于assetbundle,通过AssetBundle.UnLoad(true/false)进行卸载,true需要把加载出来的Assets也进行一个统一的卸载,因为true会完整的卸全部资源,false则单纯的卸载Assetbundle资源,通过之前维护的引用计数进行合理的管理。这里默认采用unload true,因为对全部的引用都做了管理,清理的更干净,可以用这种,不放心,可以unload false。

策略制定方面:

基本就是采用上面说的:简单/内存/fps

举例:摘出一段代码:

public enum UnLoadStrategy
{
    Default,
    Memory,
    FramesPerSecond,
}


public void Run(ref AssetBundleContext context, AssetEvent eEvent)
{
    bool force = eEvent == AssetEvent.Destroy;

    bool inLoading = context.Tasks == null ? false : context.Tasks.Count > 0;
    if (!inLoading || force)
    {
        var result = Record(ref context, ref force, context.Cache.GetAllAssetBundle());

        if (result != null && result.Count > 0)
        {
                    UnLoad(result, ref context);
        }
    }
}

极懒模式之编辑器部分:

基本制作了几个简单的部分:

Asset:修改assetbundlename(拖拽 / ×(设置空名字)),罗列信息,罗列冗余打包的资源,正/反向查资源引用。

Profiler:简单罗列task和ab的情况

Build:显示了参数选项和含义,记得打依赖资源(dep)!

Sprite:极简(各种sort,set偷懒了,233),主要就是用于观察图集和引用。

很晚了,有空再补充。晚安!!下一章预计(有空可以交流一波,下一个模块基本形式已经完成,持续优化中):

资源地址:AssetBundleSystem(有空则维护一波,不过等官方那个出来后,可能就不用这个了。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈资源加载 -AssetBundleSystem 的相关文章

  • POCO C++库学习和分析 -- 日志 (一)

    POCO C 43 43 库学习和分析 日志 一 日志对于程序来说是非常重要的 xff0c 特别是对一些大型程序而言 一旦程序被发布 xff0c 在现场日志几乎是程序员唯一可以获取程序信息的手段 Poco作为一个框架类库 xff0c 提供了
  • 字节存储排序:大端和小端

    当前的存储器 xff0c 多以byte为访问的最小单元 xff0c 当一个逻辑上的地址必须分割为物理上的若干单元时就存在了先放谁后放谁的问题 于是端 endian 的问题应运而生了 对于不同的存储方法 就有大端 big endian 和小端
  • CRC算法原理及C语言实现

    CRC算法原理及C语言实现 摘 要 本文从理论上推导出CRC算法实现原理 xff0c 给出三种分别适应不同计算机或微控制器硬件环境的C语言程序 读者更能根据本算法原理 xff0c 用不同的语言编写出独特风格更加实用的CRC计算程序 关键词
  • 动态分配的内存释放之后指针要置空

    define CRT SECURE NO WARNINGS include lt stdio h gt include lt stdlib h gt void main2 int num scanf 34 d 34 amp num prin
  • yolomark的相关操作

    1 文件组成 主要组成部分如图上 改yolo mark脚本中指令 主要是改左边的图片路径 2 使用步骤 进入cmd 输入yolo mark exe的文件路径 开始标注 image num 是对应图像的数 xff0c object id是对应
  • c++:3.7迭代器(1)

    迭代器 迭代器的基本概念 xff1a 1 迭代器是一种遍历容器元素的数据类型 C 43 43 迭代器Interator就是一个指向某种STL对象的泛型指针 通过该指针可以简单方便地遍历所有元素 2 迭代器 xff08 iterator xf
  • 51单片机定时器的查询和进入中断处理

    51单片机定时器可用两种方式处理 xff1a 查询和进入中断处理 1 查询方式 void Init T0 void 定时器初始化 TMOD 61 0x01 计时器模式 TH0 61 65535 65000 256 初装值为65536 650
  • DIY 无人机

    这是一个为满足个人兴趣的实践性项目 这个项目起源于我买的一架航模级的遥控电动直升机 xff0c 想要飞好它还是相当困难的 xff0c 需要敏捷的反应 轻柔的控制 xff0c 不幸的是我的反射弧很长 xff0c 所以练习起来格外困难 在对我的
  • 自定义的CircleProgressBar,支持自定义宽度,颜色等等。

    基于Anbase框架优化了了一个自定义的CircleProgressBar xff0c onDraw方法如下 64 Override protected void onDraw Canvas canvas super onDraw canv
  • 3D打印技术

    3D打印技术 什么是3D打印技术3D打印机的发展和运用领域3D打印过程 什么是3D打印技术 3D打印 xff08 3D printing xff09 是快速成型的一种技术 xff0c 自1986年美国科学家查克 赫尔开发第一台商业3D印刷机
  • 改变世界的17个方程式

    数学是一种美妙而优雅的东西 xff0c 它隐藏在我们生活的方方面面 xff0c 却又难以察觉 xff0c 而这需要一双慧眼才能看到 2013年 xff0c 科普作家伊恩 斯图尔特 Ian Stewart 就专门出了一本书 xff0c 名叫
  • ROS控制多台机器人实现多机协同

    ROS控制多台机器人的思路与实现 1 实现思路1 1 两台机器人跟随1 2 多台机器人编队 2 TF工具的使用2 1 什么是TF2 2 TF的构成2 3 向TF工具广播发送自己位置2 4 向TF工具收听获取坐标关系 3 通过turtlesi
  • 适合小白入门Arduino UNO的介绍

    编者按 xff1a 本文转载于酷耍平台 xff08 kooshua com xff09 Arduino是什么 xff1f Arduino是一款便捷灵活 方便上手的开源电子原型平台 包含硬件 xff08 各种型号的Arduino板 xff09
  • 记海康摄像头获取保存截图的一个方法(c#)

    记海康摄像头获取保存截图的一个方法 xff08 c xff09 先获取海康摄像头接口信息 引入模块 span class token keyword using span span class token namespace System
  • Linux设备树语法详解

    概念 Linux内核从3 x开始引入设备树的概念 xff0c 用于实现驱动代码与设备信息相分离 在设备树出现以前 xff0c 所有关于设备的具体信息都要写在驱动里 xff0c 一旦外围设备变化 xff0c 驱动代码就要重写 引入了设备树之后
  • Arduino智能越野小车AIR ROVER

    摘自 xff1a https goldelec com product detail 507 精心打造智能小车AIR ROVER xff0c 结实 稳固 大小适中 xff0c 越野爬坡能强 xff0c 采用麦克纳姆轮 xff0c 通过手机A
  • SSR的原理及好处

    什么是SSR SSR是Server Side Render简称 xff0c 叫服务端渲染 在客户端请求服务器的时候 xff0c 服务器到数据库中获取到相关的数据 xff0c 并且在服务器内部将Vue组件渲染成HTML xff0c 并且将数据
  • 区位码、国标码与机内码

    区位码 国标码与机内码 为了适应计算机处理汉字信息的需要 xff0c 在 1980 年 xff0c 我国国家标准总局发布 信息交换用汉字编码字符集 基本集 1981 年 5 月 1 日 开始实施的这套国家标准 这套国家标准的标准号是 GB2
  • 获取NSString子字符串

    NSString类中提供了这样三个方法用于获取子字符串 xff1a substringFromIndex substringWithRange substringToIndex xff1a 它们该怎么使用呢 xff1f 见下面代码即可知道

随机推荐

  • NSData和UIImage之间的转换

    源自 xff1a http stackoverflow com questions 2240765 nsdata to uiimage Try this code This worked for me create path to save
  • 获取UIImage的图像MD5

    问 xff1a I 39 m trying to compare two UIImages from the file system to see if they are the same Obviously I can 39 t use
  • 最全面的shsh备份及恢复教程,已更新Win版小雨伞4.33.00

    转自 xff1a http bbs weiphone com read htm tid 2017752 html 很多小白不知道如何备份shsh xff0c 论坛有很多关于备份shsh的帖子 xff0c 但大多都不全面 xff0c 本贴把s
  • C++查看大端序小端序的一些思考

    首先明确一个概念 xff0c 无论是大段序还是小端序 类型指针指向的地址都是该类型所占内存的低地址 明确了这个 xff0c 就好判断大端序和小端序了 这是大端序小端序的介绍链接 下边的是验证系统是大端序还是小端序的程序 span class
  • 设计模式书籍推荐

    1 名称 xff1a Head First Design Patterns 语言 xff1a java 评论 xff1a Jolt大奖得主 xff0c 介绍了常见的十几种模式 我认为最好的模式入门书籍 xff0c 内容生动 xff0c 风格
  • C#如何调用linux so库

    testlib c中的内容 xff1a include lt stdio h gt int sum int a int b return a 43 b int minus int a int b return a b main cs中的内容
  • 电机KV值

    电机 KV 值 xff1a 电机的转速 xff08 空载 xff09 61 KV 值 X 电压 xff1b 例如 KV1000 的电机在 10V 电压下它的转速 xff08 空载 xff09 就是 10000 转 分钟 电机的 KV 值越高
  • 用DD命令制作硬盘镜像

    用DD命令制作硬盘镜像 本文参考http serverfault com questions 4906 using dd for disk cloning写出 xff0c 转载时请说明出处 以下的说明都是针对备份整个硬盘 xff0c 而不是
  • 什么是PID 算法

    PID是工业控制上的一种控制算法 xff0c 其中P表示比例 xff0c I表示积分 xff0c D表示微分 以温度控制的PID程序为例 xff1a P xff08 比例 xff09 表示在温度设定值上下多少度的范围内做比例动作 xff0c
  • html代码向左居右对齐

    刚才居然忘了 现在写出来 lt div align 61 right gt 居右对齐 lt div gt left左 xff0c center中 xff0c right右
  • 出现java.lang.IllegalArgumentException: No configs match configSpec

    模拟器不支持OpenGL ES 2 0 是因为android模拟器不支持OpenGL ES 2 0 xff0c 解决办法 xff1a 创建模拟器时 xff1a GPU emulation选yes xff0c 需要android 4 0以上的
  • [005] [ARM-Cortex-M3/4] 大小端存储

  • Android使用java调用C的方法

    Android使用java调用C的方法 xff1a 要将C语言写的算法需要集成到安卓端 xff0c 因此学习如何从安卓java调用C JNI 1 JNI 提示 Android NDK Android Developers google cn
  • STM32之USART-串口通信(含串口实验详细解析)

    STM32之串口通信 USART xff08 含串口实验详细解析 xff09 开发环境 xff1a Window 10开发工具 xff1a Keil uVision5 MDK硬件 xff1a STM32F103 资料参考 xff1a 正点原
  • 昆仑镜Air530 GPS串口输出

    原理图 Air724UG硬件手册说明 Air724UG模块硬件手册 实际开机后并不是默认打开 pmd手册 LDO VMMC level范围0 15 其中0表示关闭其余值满足下面公式 step 61 9 level 当step大于127时为1
  • 常用bat代码

    清除空文件夹 清理空文件夹 删除空文件夹 64 echo off for f 34 tokens 61 34 i in 39 dir s b ad sort r 39 do rd 34 i 34
  • 如何快速的翻译并阅读外文文献

    本文适用一些想要快速了解文献内容的童鞋 在进行查找文献时 不可避免要查找外文文献 其中以英文居多 当然也有可能涉及到其他语言 像楼主这样学了十几年英语 然而听说读写弱鸡的人 面对英语时 会头痛 要是查到其他语言的文献时 估计要死的心都有了
  • [c/c++ ]字节序与大小端转换

    注明 xff1a 以下内容均为学习内容整理 xff0c 记录 xff0c 便于自己学习 xff0c 并非完全意义上的自产 xff0c 如有感到不适 xff0c 请联系我 一 多字节值及字节序 1 brief 现在有一个数字 65430 xf
  • 5V升压8.4V芯片电路图,5V充电7.4V电池

    两节锂电池串联 xff0c 串联电压相加 xff0c 一般锂电池标称电压3 7V xff0c 3 7V 43 3 7V 61 7 4V xff0c 7 4V锂电池 xff0c 充电充满电压饱和是8 4V 7 4V锂电池放电电压一般是6V 8
  • 浅谈资源加载 -AssetBundleSystem

    AssetBundleSystem Ps 稍微抽点时间写一下这个 xff0c 这个小项目完成度80 左右 xff0c 在年初2月份的时候就完成的差不多了 xff0c 因为各种原因处于半搁浅的阶段 xff0c 现在官方出了Addressabl