包体大小优化笔记
AssetBundle大小管理策略(航海项目包体管理)
一些记录
- bsdiff差分算法
- 出正式包怎么剥离无用的dll,比如log插件dll,Debug库,绘制插件dll(仅dev使用)参考 - 这里可以在打包正式包时将dll删除后打包
AssetBundle大小管理策略
主要问题:纹理,Shader,FBX动画
图集、图片文件过大
使用第三方无损压缩,减小文件大小,这里文件大小是原来的1/3。
使用图片无损压缩打包测试,图片属性:RGBA 2048*2048,使用RGBA Crunched ETC2
内存压缩
压缩尺寸 | 压缩前 | 压缩后 | |
---|---|---|---|
图片文件 | 1564kb | 481kb | |
AB文件 | 2048 | 268kb | 260kb |
AB文件 | 1024 | 96kb | 89kb |
可以发现压缩后的图片打包AB文件比压缩前小大概7kb左右 |
- 图片在内存中没有压缩
纹理的压缩格式影响AB包的大小 (Android平台测试)
使用ETC2压缩生成AB包比使用 Crunched ETC生成AB包大3倍(这里只是说明压缩格式影响AB包文件大小,不说明压缩格式和包体的具体关系)。
Android平台
使用ETC 4Bit压缩后
使用 Crunched ETC 压缩(需要真机测试性能及是否支持该压缩格式),这个格式消耗cpu,进入GPU处理阶段会解压成etc压缩,GPU本身不支持 Crunched ETC压缩
推荐 Android 和IOS都用ASTC;
参考:ASTC纹理压缩格式详解
FBX文件过大
主要是animation和纹理占用比较大,每个带动画的角色都是这样的情况
压缩大小比10倍,待测,不知道animation压缩怎么样
- 设置FBX Animation Compress格式
使用R220002@ui_comeout.fbx
动画文件测试
现在的FBX配置
文件大小是4322kb,打包AB文件大小是1553kb
修改FBX配置(没有勾选 Resample Curves)
文件大小是4322kb,打包AB文件大小是499kb (这里fbx文件本身大小没变,untiy不修改源文件)
修改后的内存大小是原来的1/4,Ab文件是原来的1/3 (动画表现一致)
使用脚本剔除无用scale数据及修改数据精度(没有勾选 Resample Curves)
这种方式每次animation导入修改后都不会保持,因为untiy默认重新导入animation并计算数据,需要在animation后处理中处理,每次变化都要执行一遍
文件大小是4322kb,打包AB文件大小是310kb
修改后内存更低了和原始比是原来的不到1/4,AB文件是原来的1/5 (这里fbx文件本身大小没变,untiy不修改源文件) (动画表现一致)
如果所有的角色动画都进行调整,包体可以明显减小
fbx导入到Unity之后是不会变化的,就是说Unity里面的所有编辑都不会保存在FBX文件里,可能在meta文件中,这里没有测试。
注意压缩后需要真机测试看看动画是否一致,这里是win editor测试的,没有真机测试
参考:
https://blog.uwa4d.com/archives/Optimization_Animation.html
https://zhuanlan.zhihu.com/p/353402448
https://www.bzetu.com/344/.html
https://blog.uwa4d.com/archives/UWA_Pipeline22.html
处理Animation时遇到的问题:
一个fbx上出现两个animation 动画,__preview_Take 001
应该是美术没有删除干净 打包AB文件没有发现__preview_Take 001
资源打包进去
AB加载和卸载策略
现有加载策略:
- 根据manifest配置文件进行加载资源并且找到依赖进行加载
- 只有同步加载没有异步加载
- 加载的Bundle和LoadAsset资源都做了缓存,但是没有引用计数
现有资源卸载策略:
- lua Bundle加载资源后直接卸载bundle;
- 场景加载后将bundle卸载,在切换场景时: - 执行LuaGC处理 - 清理所有Asset的引用(将缓存的Dict清空)(资源泄露:bundle没有卸载,清空了asset引用,再次加载资源时会再次LoadAsset,会存在多份相同asset;加载效率利用率低,没有区分常驻内存资源和非常驻内存资源,bundle管理粗放)
- 非场景资源加载后没有卸载流程,全部依靠场景卸载时清理
- 除了上述bundle卸载之外,游戏运行中没有卸载bundle,内存占用过高容易崩溃
- 业务层只管加载,不处理卸载
Resources.UnloadUnusedAssets()
没有调用(场景加载时会自动调用,记不清了)
调整方案:
- 同步和异步加载
- 使用引用计数方案对Bundle和Asset管理
- 增加图集管理(图集制作细分方案待定)
- 使用加载和卸载成对管理,或者做内置管理和实例对象绑定
URP Package 内置shader打包问题
-
Universal Render Pipeline/Lit has too many Shader variants(150994944)
URP 自带Lit Shader变体太多问题 -
Assertion failed on expression:`m_UserPathRemap.count(pathStr) == 0`
可能因为在Project Setting–>Graphing设置All include 然后打包又打进去所以报错了
包体优化结果
左侧蓝色是优化后的,右侧红色是优化前的
DisableWriteTypeTree问题
关闭Bundle文件的type information
数据写入,这是为了使用Unity版本不同做的兼容(标记数据,unity版本相同无用)
|
|
红色是开启默认type information
写入,asset classes就是写入的数据,左侧蓝色是关闭type information
写入的大小
bundle文件大小差5k多(每个bundle文件内容不一样,大小也不一样),还是很可观的
Shader变体处理
-
Graphics APIs 只保留
OpenGLEL3
就可以了,否则打包Shader时每个平台生成一套代码导致AB包过大 -
Graphics -> Tier Settings默认三种配置,每个shader会生成对应三套代码,这里将Tier三种配置设置成相同的,则Shader只会生成一套代码,减小包体
- 单独打包Shader文件(没有材质球) 关于
#pragma multi_compile
和#pragma shader_feature
测试
|
|
打包的AB包中的Shader keywords数量
multi_compile
两行的keywords组合相乘是最后的shader代码的数量,注意数量
这里#pragma shader_feature
如果第一项是_
则认为没有keywords,如果不是_
,则默认打包进第一个选项(这里是E
)
- 单独打包材质球(将材质球和shader打包一起)
|
|
打包的AB包中的Shader keywords数量
材质球keywords默认:
材质球指定keywords后
指定keywords后等于选择shader_feature
的变体,multi_compile
进行全部组合
总结:材质球指定shader_feature
keywords后和shader打包到AB文件中,shader的keywords是受材质球的keywords配置影响的;加入了GraphicsSetting-> always included shader后,会将它所有的keywords变体打包到游戏中
可以用Shader Variant Collection
单独控制keywords,把collection和shader打包到一个AB文件中
参考: https://zhuanlan.zhihu.com/p/68888831
https://blog.csdn.net/eevee_1/article/details/118632371
https://zhuanlan.zhihu.com/p/392004640 https://blog.csdn.net/danteshenqu/article/details/78170745 https://zhuanlan.zhihu.com/p/83780152
关于
GraphicsSetting-> always included shader
说明:
如果打AB时不想shader被打包进AB包,则用always included shader
添加shader,单只能是unity buildin 内置shader(Packages内的shader不是内置的)。
cube11和cube1使用的shader是Unlit/Color
,Cube22和Cube2使用的shader是custom/Cube2
;每个ab文件内只有一个cube物体的prefab,引用一个材质球和对应的shader
AB文件cube11和cube22是在always included shader
添加前打包的,AB文件Cube1和Cube2是在always included shader
添加后打包的
根据上面打包测试分析出结果:
- Cube22和Cube2使用自定义shader
custom/Cube2
,不管always included shader
内是否添加该shader,打AB包都会把该shader打包进去- Cube11和Cube1使用内置shader
Unlit/Color
,always included shader
内添加该shader,打包AB包不会把该内置shader打包进去;否则会打包进AB包内- URP内Shader算是自定义shader,不管
always included shader
内是否添加,都会将使用的URP Shader打包到对应AB包中
关于URP Shader打包问题
由于
URP
内部的Shader
在Packages
中,不能使用Inspector
面板设置AssetBundleName
及脚本代码设置AssetBundleName
。在Graphics
面板中添加URP shader
,但是打包还是会被打进去 解决方案: 1. 使用AssetBundleBuild
方式打包可以控制Packages内的资源 2. 使用Addressables
官方插件打包可以设置Packages内的资源材质球和shader打包到一起,会根据材质球引用的keywords变体打包,而加入了
GraphicsSetting-> always included shader
后,会将它所有的keywords变体打包到游戏中关于shader变体说明:https://blog.csdn.net/kuangben2000/article/details/105400835