大家好,我是阿赵。
在项目里面,有时候会遇到这样一个问题。在Unity编辑器里面编写了一个shader,在编辑器看,效果都是没有问题的。但如果把资源打包成AssetBundle后,会发现shader的表现不对了。遇到了这种问题的时候,一般人会各自的怀疑,怀疑是不是shader写得不对,导致在不同平台的表现不对。
实际上,有很多时候这并不是shader本身的问题,而是shader需要的数据丢失了,比如顶点颜色、法线、切线等。
一、模拟一个环境
我这里准备了2样东西:
1、一个shader,为了简单,我直接用ase连了一下线。这个shader有2个功能,一个是根据顶点颜色显示模型颜色,第二个是做了个边缘光效果。
2、从3DsMax里面导出了一个茶壶模型。茶壶模型带有顶点颜色,颜色是从底部到顶部从黑到白色渐变。
把模型从3DsMax导出成fbx,然后导入Unity,并且赋予材质之后,效果应该是这样的:
二、打包AssetBundle并加载
我这里模拟了拆分依赖的情况来打包AssetBundle,其中茶壶的预设、材质球和茶壶的fbx,都分别设置了AssetBundleName,并打包成3个AssetBundle。
然后加载了,通过依赖查找的方式,先加载了fbx和材质球的AssetBundle,然后再加载茶壶预设的AssetBundle。并把茶壶生成在场景里面。看到的效果是这样的:
很明显,和刚才在编辑器里面看到的效果不一样。
三、问题和解决
为了验证一下出现问题的原因,我们可以单独把模型的顶点色、法线、切线用shader输出一下来检查。
下面的图片里面,左边的茶壶是通过AssetBundle加载的,右边的是直接在编辑器拖进去的。
顶点颜色:
世界空间法线:
世界空间切线:
可以看出来,通过AssetBundle加载的茶壶,它的顶点颜色丢失了,变成了全部都是白色。法线数据还在,但切线数据也丢了。
为什么在打包AssetBundle的时候,模型网格的数据会丢失呢?
可以打开PlayerSetting看看,里面有2个选项:
Vertex Compression选项,看看说明可以知道,这是一个对顶点数据的压缩。压缩顶点数据可以减少内存和带宽的占用,但精度会变低。从说明可以知道,这个选项只会降低精度,并不会把数据直接丢弃。所以这个选项并不是引起问题的原因。
再看来Optimize Mesh Data选项。这个选项直接是去掉了不使用的网格组件数据。
这里要回头看看一个问题,由于我们把fbx单独打包了AssetBundle。而由于这个fbx在单独打包的时候,并不知道有什么材质球使用了它的哪些属性,所以它会认为,除了必要的顶点、索引和UV信息以外,其他的数据都是可以被丢弃掉的。
为了验证这个问题。我取消了fbx和材质球的单独打包,只打包预设作为AssetBundle。果然shader的显示就正常了。
但实际项目中,由于同一个fbx被多个模型预设使用,为了减少重复依赖打包,我们是不可避免的把网格模型单独打包AssetBundle作为依赖的。所以,这个问题不能简单的整体打包来解决。
下面来看看解决的办法。
方法一:
很明显的,由于Optimize Mesh Data选项导致数据被丢弃,我们只要不勾选这个选项,那么数据就不会被丢弃了。
方法二:
不要直接打包Fbx,而是通过ctrl+D,把Fbx里面的mesh复制出来,然后再把这个mesh作为资源来打包AssetBundle,预设上面也不要引用fbx,而是引用复制出来的mesh。
这样操作之后,打包AssetBundle再加载,顶点数据同样的不会丢失。
对比这两种解决方法,我更倾向于第二种。这是因为,fbx在导入unity的时候,其实还带着其他的数据,比如导入或者unity自动生成的材质球数据。这些数据我们一般都不希望使用的。所以复制出我们想要的网格数据使用,就避免了引用整个fbx,也避免了产生一些不必要的内存和加载的问题。