Transform.SetParent
GameObject.Deactivate/Active
MipmapVisualization
Unity3D性能优化:ShaderLab内存占用
前言:
手机的内存占用一直是项目优化的重要部分。最近优化项目的内存占用时。发现了个占用比较恐怖的地方。
那就是ShaderLab
正文:
从上图(进入战斗场景时的内存快照)可以看出,ShaderLab占用居然达到42M(请忽略其他项数据,因为还没优化到=。=)。
为什么Shader的占用那么高呢?
由于当前项(ShaderLab)没有说明详细的shader占用信息。所以只能去另外找原因了,还好,在内存快照的Assets下的shader项中,有详细的使用信息。
然后我看到Standard的shader使用。那么我就开始迷惑了,因为项目里面根本没有地方使用过Standard这个shader,为什么会存在呢。
所以我感觉内存占用的大头就出在这了。
然后进行了一轮的排查,把部分使用到Standard的地方清除掉,测试并再拿一次内存快照。
清除了一部分后,ShaderLab降到27.6M(后来完全清除掉Standard,降到21M)。果然,主要原因就出在了Standard上。
那么问题又来了,为什么我没有使用到Standard,却会在内存中看到Standard的使用呢?
这里就要说下两个坑了,同样,也是排查这个问题的方法。
一.模型导入导致。
模型导入的时候,“Import Materials”是默认勾选的。所以当模型导入时,Unity会在同目录创建“Materials”目录,并创建相应的材质,而这个材质默认是使用Standard。
由于美术在制作过程中对Prefab中对模型另外赋予材质,所以实际上,默认创建的材质(Standard)是没有使用到的。可是当加载模型的时候,却又把默认创建的材质加载上了,并对着色器解析了。因此导致内存中有Standard。
那么解决方法也很简单,把“Import Materials”去掉,并把没有使用的默认材质删除。
注意:如果不把“Import Materials”去掉,导入到其他项目时,材质又会自动创建了。
由于实际项目中,Prefab改动次数比较大,相应的模型文件改动比较少,所以把项目中的模型和对应的Prefab分开打包成不同的AssetBundle。然后就出现一个很奇怪的情况。
没有勾选“Import Materials”的模型文件,在实例化Prefab时,ShaderLab会存在一份“Standard”的shader内存,而这个shader的引用是指向一
个“Default-Material”文件(可是这文件并不存在)。
但是,在模型和Prefab在相同的AssetBundle中,或者使用Resources加载时,却不会有“Standard”和“Default-Material”的出现。
暂时还还不确定是这是版本bug,还是Unity的特殊机制。(版本5.3.3)
临时解决方案:在需要模型与Prefab分开打包时,勾选“Import Materials”,直接使用和修改默认生成的材质。
二.默认模型(Cube、Sphere)创建导致的。
早期场景搭建时,为了方便定位和可视化,曾经使用Cube等系统默认的Mesh作为锚点,然后在启动游戏时禁用掉。
由于这些Cube不启用,性能消耗很轻微。所以就没有理会了。
可是,就因为是系统默认的Mesh,所以创建时,赋予的材质就是默认的材质“Default-Material”,而这个材质使用的着色器就恰恰是“Standard”。
所以“Standard”存在的并不冤了。
解决的方案也很简单,删掉这些mesh或者是替换材质。这样,这部分占用的“Standard”就不存在了。
总结:
由于Standard的变体太多了,所以当引用了Standard的时候,往往会存在多个Standard变体,占用大量的内存。如果,你发觉你的ShaderLab的内存过大,而又那么也不妨找找是不是上述的原因。
那ShaderLab占用内存过大是不是完全是Standard的原因呢?其实并不止的。像我优化完之后的27M(完全清除后是21M),肯定还有其他原因造成的。可是,优化的过程是砍大头,像上文那样,稍微优化一下,就能拿掉20多M,当然要立刻做,可是越往小的时候,优化效率就越来越低了,所以这时候就需要转移目标看一下“Objects”“Texture2D”这些大头了。所以,剩下ShaderLab的优化方向可能会在以后遇到的时候再补充。