赞
踩
资源:Resource,主要分为Prefab,Image,AudioClip等,一般在开发时为单个文件
包/ab包:AssetBundle,打包后的单个文件,内含若干资源
包名:AssetBundleName,为资源设置的归属包的名称
打包:按一定规则或配置为资源设置包名(一般写个工具读配置遍历设置),build时资源会被打到对应的包中
解包:游戏运行时,根据资源路径加载资源,需要先找出所属包,先加载包,然后才能加载资源
两者为逆操作,故需要根据打包规则反推所属包,使用配置文件或者遍历所有AB包都不可取
未设置包名的资源不会被打进包中,除非它被某包中资源引用到,如果被多个包中资源引导到,就会打到多个包中(冗余)
设置了包名的资源如果被其他包资源引用,两个包会建立引用关系
大部分项目使用的都是按文件夹打包,打包规则分为2类:
以上规则还会配置文件后缀过滤,比如只设置ui的prefab包名,引用的静态图片等未设置包名的资源会自动打进同一个包里,引用到的公共图集等设置了包名的资源,会生成一个包引用关系
一个典型的ui打包规则配置文件大致如下:
文件夹路径 | 子层级 | 打包规则 | 后缀列表 | 备注 |
---|---|---|---|---|
ui/common | 0 | 散包 | common下每个资源单独打包(多了点引用,方便更新) | |
ui/form | 1 | 整包 | prefab | form下每个文件夹(如xxx_form)打成一个包,只给prefab资源设置包名 |
ui/dynamic | 1 | 散包 | jpg|png | dynamic下每个文件夹里(如xxx_form)的图片单独打包(一般都很大,按需加载,不打整包) |
子层级:文件夹下层级,因为打包规则中文件夹不递归扫描,降低复杂度
根据项目的需要,在打包数量和冗余大小之间取舍的策略差异较大,不赘述
解包即反解包名,根据资源路径得到所属包名称
在上一步的打包中,包名一般设置为文件(夹)路径,按照打包的逆操作,资源路径一定包含包名路径
通过系统api获取到所有包名,生成前缀树,按资源路径进行查询,叶子节点即为所属包名
资源加载流程:输入资源路径和回调,反解包名,加载包,加载资源,执行回调
加载包的done指自身和依赖的ab包均加载完成,这些ab包的加载没有先后关系,可以同步发起
如果依赖的ab包未加载或被错误地提前回收,最常出现的就是经典的紫红色贴图丢失bug
同步实现较为简单,但是绝不符合项目需求,异步就会比较复杂,建议搭建时先实现同步版后转异步版
为了开发时的Resources模式和测试时的AB模式兼容,一套接口,两套实现是必须的,Resources模式加载逻辑简单(没有包,同步加载),不赘述
每个ab包都对应一个管理单元AbUnit,结构大致如下:
属性 | 类型 | 说明 |
---|---|---|
name | string | 包名 |
state | Enum | 状态:加载中,已加载 |
depends | Dictionary<string, AbUnit> | 依赖的ab包管理单元 |
reference count | int | 被依赖计数,为0时回收 |
resources | Dictionary<string, object> | ab包内已加载的资源,key为纯净资源名 |
callbacks | Dictionary<string, List> | 回调表,key为纯净资源名 |
一个ab包的生命周期大概是:
为了防止内存爆掉,需要在适当的时候回收无用ab包,小游戏会在切场景等操作时调用系统api一键清理,不过大一点的游戏都不能这么莽,常见方案就是引用计数,引用类型分:
每个包内包含若干资源,按需加载,资源没有引用计数,ab包释放时统一释放即可
较为特殊的资源是图集,不能像其他资源那样的方式加载,一次性全部加载后存到字典中即可
引用计数是这套方案中最重要的部分
自动引用计数
如果一个脚本自从被添加后,从未被激活过,那么start和destroy都不会执行,反之都会执行,
因此Ref脚本计数有一个临界bug如下:
资源加载完成时go是disabled,导致Ref脚本start不执行,计数未增加,ab包被回收,等go被enabled出现资源丢失
解决方案:
增加ParentResRef脚本,当go发现自己被disabled,会往上找到enabled的首个祖先节点,挂上该脚本,增加引用计数,destroy同理
手动引用计数
由程序员增减引用计数,主要用于对象池、预加载等上层应用自身对资源进行管理的情形
自动计数中,每个go对于一个类型的资源只能挂一个脚本,引用一个包,所以封装按钮这种多图片切换的情形时也要手动计数
最大并行数
同一帧发起大量资源加载时,会造成短时io堵塞,进而产生卡顿,所以需要限制加载最大并行数
超过最大并行数的请求排队等候即可
最优数值可能因机器而已,可以实际调试获得
垃圾箱
在ab包引用计数为0后,不立即回收,而是进入垃圾箱,然后等待一段时间后,仍然为0,再实际回收
避免了少量情况下的循环回收加载,如列表滚动到下方后上方图标被回收
加载优先级
可以为加载请求添加优先级参数,用于低优先级预加载某些资源,在低配手机效果会比较好
因为玩家操作的不确定性和项目组对秒开界面没有变态的要求,所以没有实装
同步加载支持
理论上是可以同步异步都支持的
但是有一个bug:
对同一个ab的异步加载发起后,再发起同步加载,会自动略过,这就很可能导致同步代码之后的业务逻辑出错,感觉Unity不太会修复
而且强行同步加载意义不大,故舍弃
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。