如题,出现这个问题是我们公司项目在优化阶段将部分打包的资源,如:Prefab 中的一些对象的材质,都使用了最简单的 shader,这些 shader 可能只是一个 unlit
这个 unlit 简单到什么程度呢?可能只是使用到 uv 坐标对 texture 采样,所以顶点数据仅仅使用到:
- SV_Position (这个是每个 VertexShader 必定需要的数据,所以这个是剔除不了的)
- Texcoord 或是 Texcoord0
所以 Normal, Tagent, Color0~7, Texcoord1~8 都没有使用到
这时,如果你对仅仅使用到这 unlit shader 的mesh来 build asset bundle (AB 包) 资源,这些 Mesh 中原本可能包含的顶点数据: Normal, Tagent, Color0~7, Texcoord1~8,但是 shader 都没用上这些数据,最后这些顶点数据都会被删除掉,因为 Unity 静态分析引用的资源发现该 Mesh 用到的 Material(材质)的 Shader 都没有使用到对应的其他顶点数据: Normal, Tagent, Color0~7, Texcoord1~8,那么这个 Mesh 的这些数据统统都会在 Build Asset Bundle时被删除。
然后如果你的项目在运行后,会切换了某些 shader,并且这些 shader 使用到: Normal, Tagent, Color0~7, Texcoord1~8 其一的顶点数据来做计算渲染,那么结果就会和你预想的不一样
运行中,切换的 shader 可能用到的功能:
- 使用法线来计算光照
- 使用 Tagent 来还原 TBN 矩阵
- 使用 Color 来着色,或是作为一些效果的 Bake 数据
- 使用 Texcoord 也是来所一些其他的数据
那么这些效果都会异常,因为该 Mesh 打包在 AssetBundle 前,就会经过前面说的静态分析,分析该 Mesh 被引用到的所有 Material(材质)、所有 Shader,是否用到对应的顶点数据,用到的都会保留,没用到的都会统统删除
如何关闭 Unity 的自动删除顶点数据的优化功能?
问:那么在哪些可以设置: Unity 不要剔除这些没使用到的 Mesh 顶点数据的功能呢?
答:在:ProjectSettings->Player->Other Settings->Optimization->Optimize Mesh Data
改选项默认是开启的,如下图:
坑就坑在默认是开启的,这在 Unity 论坛中,某个帖子,已经被吐槽到不行了:
Warning to all my friends: BEWARE Optimise Mesh Data!!
注意会增加资源打包的时间
另外需要注意,开启:Optimise Mesh Data 虽然可以优化我们的包体大小,但是这会大大增加我们的打包资源的时间,这随着 Mesh 的数量与 Shader 的数量成:MeshNumber * ShaderNumber 的倍数增长,原因可以从上面说明分析出来,因为是静态分析
我是如何发现 Mesh 数据丢失的?
渲染效果异常了,我就排查 shader 问题
- 先在 Shader Graph 中使用查看一遍有无逻辑问题
- 再逐一对渲染时某个效果的数据都分别用颜色输出,可便于快速的分析数据的范围是否有问题
因为渲染中的 Rim 效果出了问题,那么我只要将 Rim 效果的数据都使用颜色来输出即可
就一个:Intensity(强度)、NormalVector(法线向量)ViewVector(视线向量),所以将这几个数据输出颜色就很快检测出来
在输出法线作为颜色输出后,就可以发现打包资源后的法线数据都是错乱的,而打包资源前,都是正确的
所以在此可以分析是法线数据丢失了
为了再次确定打包出来的 AB 包资源内的 Mesh 没有了法线数据,可以这么来做:
- 使用 AssetStudio : Perfare/AssetStudio
用它来解 AB 包内的资源,并将资源导出 fbx 或是 obj 格式的模型文件 - 再使用 FbxFormatConverter - Fbx 格式的转换器(目前只有:Binary、Ascii 的互转),来将解包后重新导出的 obj/fbx 转为 ascii 文本内容来查看法线数据是否还在(这部也可以使用 3D MAX 等支持打开 FBX/OBJ 文件的 3D 编辑软件来查看法线、等相关顶点数据信息)
解决
方式1 - 不选中 Optimize Mesh Data
配合之前做资源优化相关的同学一起查看,最后,尝试将:ProjectSettings->Player->Other Settings->Optimization->Optimize Mesh Data的选项去掉(去掉勾:不选中),然后再打包,发现渲染效果都正常了
方式2 - 保留 Optimize Mesh Data的勾选
Optimize Mesh Data 的功能虽然可以手写,但是也麻烦,还是使用 Unity 自带的
就利用它是使用静态分析的方式,将一些必要的效果放在一些 Prefab(可以随便新建一些 Prefab) 的 Renderer 材质改为需要使用到效果最大化(包含所有顶点数据都使用到)材质中使用到顶点各个数据的 Shader ,这样就算勾选了 Optimize Mesh Data来导出的时候,也可以保留这部分 Mesh 的顶点数据了
(如果Unity有类似:PostProccessAssetImport的接口,如:PreOptimizeMeshData之类的,就可以写个脚本处理了,但是 Unity 没有提供类似的接口)
Tips
如果只是想查看法线数据有否,可以用 AssetStudio 导出的 *.obj 直接搜索:vn 即可(vertex normal),如果没有说明就没有法线数据
References
- PlayerSettings.stripUnusedMeshComponents - 这是官方的文档,说的不够详细,但是从描述中可以分析得出来,就是静态分析的方式
- Warning to all my friends: BEWARE Optimise Mesh Data!! - 被吐槽到不行的某个帖子
- 针对移动平台打assetbundle 时,optimize mesh data 选项开启会造成mesh 顶点色不可用的问题 - 这是后来才搜索到的相关 UWA 的帖子也有说明
- OPTIMIZE MESH DATA PLAYER SETTING CAN DRASTICALLY INCREASE BUILD TIMES - 这里有人试过,Optimize Mesh Data 开启后 Build 资源 20 分钟耗时,关了之后,小于 1 分钟,但是具体也是看项目的使用情况来开、关
- Unity 中关于 BuildSetting 中 “Optimize Mesh Data” 选项的“坑” - 这么早就有人踩坑了
- Asset Bundle and Mesh Missing Tangents - 他的情况是切线丢失了