目录

包体大小优化笔记

AssetBundle大小管理策略(航海项目包体管理)

一些记录

  • bsdiff差分算法
  • 出正式包怎么剥离无用的dll,比如log插件dll,Debug库,绘制插件dll(仅dev使用)参考 - 这里可以在打包正式包时将dll删除后打包

AssetBundle大小管理策略

主要问题:纹理,Shader,FBX动画

图集、图片文件过大

../../imgs/2022-01-20-11-41-31.png

../../imgs/2022-01-20-11-48-28.png 使用第三方无损压缩,减小文件大小,这里文件大小是原来的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平台

../../imgs/2022-01-20-11-51-05.png

使用ETC 4Bit压缩后

../../imgs/2022-01-20-11-52-38.png

使用 Crunched ETC 压缩(需要真机测试性能及是否支持该压缩格式),这个格式消耗cpu,进入GPU处理阶段会解压成etc压缩,GPU本身不支持 Crunched ETC压缩
../../imgs/2022-01-20-11-53-24.png

推荐 Android 和IOS都用ASTC;
参考:ASTC纹理压缩格式详解

FBX文件过大

../../imgs/2022-01-21-11-14-07.png
主要是animation和纹理占用比较大,每个带动画的角色都是这样的情况

压缩大小比10倍,待测,不知道animation压缩怎么样

  • 设置FBX Animation Compress格式

使用R220002@ui_comeout.fbx动画文件测试

现在的FBX配置
../../imgs/2022-01-20-15-39-33.png ../../imgs/2022-01-20-15-38-38.png
文件大小是4322kb,打包AB文件大小是1553kb

修改FBX配置(没有勾选 Resample Curves) ../../imgs/2022-01-20-15-41-33.png
../../imgs/2022-01-20-15-41-49.png
文件大小是4322kb,打包AB文件大小是499kb (这里fbx文件本身大小没变,untiy不修改源文件)
../../imgs/2022-01-20-15-44-33.png
修改后的内存大小是原来的1/4,Ab文件是原来的1/3 (动画表现一致)

使用脚本剔除无用scale数据及修改数据精度(没有勾选 Resample Curves) 这种方式每次animation导入修改后都不会保持,因为untiy默认重新导入animation并计算数据,需要在animation后处理中处理,每次变化都要执行一遍
../../imgs/2022-01-20-16-10-03.png
../../imgs/2022-01-20-16-34-32.png
文件大小是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时遇到的问题:
../../imgs/2022-01-24-20-27-28.png
../../imgs/2022-01-24-20-33-18.png
一个fbx上出现两个animation 动画,__preview_Take 001应该是美术没有删除干净 打包AB文件没有发现__preview_Take 001资源打包进去

AB加载和卸载策略

现有加载策略:

  1. 根据manifest配置文件进行加载资源并且找到依赖进行加载
  2. 只有同步加载没有异步加载
  3. 加载的Bundle和LoadAsset资源都做了缓存,但是没有引用计数

现有资源卸载策略:

  1. lua Bundle加载资源后直接卸载bundle;
  2. 场景加载后将bundle卸载,在切换场景时: - 执行LuaGC处理 - 清理所有Asset的引用(将缓存的Dict清空)(资源泄露:bundle没有卸载,清空了asset引用,再次加载资源时会再次LoadAsset,会存在多份相同asset;加载效率利用率低,没有区分常驻内存资源和非常驻内存资源,bundle管理粗放)
  3. 非场景资源加载后没有卸载流程,全部依靠场景卸载时清理
  4. 除了上述bundle卸载之外,游戏运行中没有卸载bundle,内存占用过高容易崩溃
  5. 业务层只管加载,不处理卸载
  6. Resources.UnloadUnusedAssets()没有调用(场景加载时会自动调用,记不清了)

调整方案:

  1. 同步和异步加载
  2. 使用引用计数方案对Bundle和Asset管理
  3. 增加图集管理(图集制作细分方案待定)
  4. 使用加载和卸载成对管理,或者做内置管理和实例对象绑定

URP Package 内置shader打包问题

  • Universal Render Pipeline/Lit has too many Shader variants(150994944) ../../imgs/2022-01-24-14-05-37.png
    URP 自带Lit Shader变体太多问题

  • Assertion failed on expression:`m_UserPathRemap.count(pathStr) == 0` ../../imgs/2022-01-24-14-23-38.png

可能因为在Project Setting–>Graphing设置All include 然后打包又打进去所以报错了

包体优化结果

../../imgs/2022-01-27-10-17-42.png 左侧蓝色是优化后的,右侧红色是优化前的

DisableWriteTypeTree问题

关闭Bundle文件的type information数据写入,这是为了使用Unity版本不同做的兼容(标记数据,unity版本相同无用)

1
2
//BuildAssetBundleOptions.DisableWriteTypeTree
BuildPipeline.BuildAssetBundles(dir,ls.ToArray(),BuildAssetBundleOptions.DeterministicAssetBundle | BuildAssetBundleOptions.ChunkBasedCompression|BuildAssetBundleOptions.DisableWriteTypeTree, BuildTarget.Android);

../../imgs/2022-01-26-17-18-18.png 红色是开启默认type information写入,asset classes就是写入的数据,左侧蓝色是关闭type information写入的大小 bundle文件大小差5k多(每个bundle文件内容不一样,大小也不一样),还是很可观的

参考:https://blog.csdn.net/kangluo1/article/details/119089200

Shader变体处理

  • Graphics APIs 只保留OpenGLEL3就可以了,否则打包Shader时每个平台生成一套代码导致AB包过大 ../../imgs/2022-01-27-18-24-08.png

  • Graphics -> Tier Settings默认三种配置,每个shader会生成对应三套代码,这里将Tier三种配置设置成相同的,则Shader只会生成一套代码,减小包体

../../imgs/2022-01-27-18-26-27.png

  • 单独打包Shader文件(没有材质球) 关于#pragma multi_compile#pragma shader_feature 测试
1
2
3
4
            #pragma multi_compile  COM_M COM_N
            #pragma multi_compile  COM_X COM_Y COM_Z
            #pragma shader_feature _ A B
            #pragma shader_feature E F

打包的AB包中的Shader keywords数量
../../imgs/2022-01-27-18-39-42.png multi_compile两行的keywords组合相乘是最后的shader代码的数量,注意数量
这里#pragma shader_feature 如果第一项是_则认为没有keywords,如果不是_,则默认打包进第一个选项(这里是E

  • 单独打包材质球(将材质球和shader打包一起)
1
2
3
4
            #pragma multi_compile  COM_M COM_N
            #pragma multi_compile  COM_X COM_Y COM_Z
            #pragma shader_feature _ A B
            #pragma shader_feature E F

打包的AB包中的Shader keywords数量

材质球keywords默认: ../../imgs/2022-01-27-18-48-01.png
../../imgs/2022-01-27-18-39-42.png

材质球指定keywords后
../../imgs/2022-01-27-18-47-30.png
../../imgs/2022-01-27-18-46-29.png
指定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文件中 ../../imgs/2022-01-27-18-51-53.png

参考: 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不是内置的)。
../../imgs/2022-03-07-11-15-01.png
../../imgs/2022-03-07-11-21-04.png
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内部的ShaderPackages中,不能使用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