众所周知,我们在unity里编写Shader使用的HLSL/CG都是高级语言,这是为了可以书写一套Shader兼容多个平台,在unity打包的时候,它会编译成对应平台可以运行的指令,而变体则是,根据宏生成的,而打包运行时,GPU会根据你设置的宏切换这些打包出来的代码,而不是我们书写那种只生成的一个Shader,这也是为了提高运行速度。
如果你要查看实际运行的代码,可以使用RenderDoc等工具截帧查看实际运行的代码。
可以在Shader上面查看当前生成的变体数量。
优化Shader最主要的是优化Shader的算法,整理代码结构,减少冗余。使用最精简,运行效率最高的代码来实现我们的功能。
我们可以在微软的网站查看,根据指令槽进行排序,查看性能消耗顺序。里面展示了在片元里面的占用:
函数优化的再多也节省不了多少,都不如少渲染几次节省的多,所以,我们要从减少渲染量上面入手。
我们在Unity的内置CGInclude文件中可以发现不少函数都有inline关键字,有inline修饰的函数为内联函数,可以解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,但inline 的使用是有所限制的,inline 只适合函数体内代码简单的函数且会被频繁调用时使用,不能包含复杂的结构控制语句例如 while、switch,并且内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)。
美术资源主要是包含:纹理,网格以及Shader的变体,其中最主要的是纹理。
纹理大小会影响资源加载时间,gpu渲染时间,内存的使用,包体大小以及画面质量。
有些同学一直认为要极致压缩在unity里面的大小,这种方式是不对的,那只是导入到unity中的图片存储格式,不代表在打包后的占用,unity在打包时,会将格式转换成其它格式进行存储。
上图展示了图片打包后的占用,前面则表面了当前的图片使用了何种压缩。
所以,不要在乎图片导入时的大小和尺寸,要在图片上进行设置,比如设置其最大1024。
首先,科普一下bpp,比如4 bpp,意思为每个像素占用4bit 应为 4bit per pixel。
unity官方纹理压缩文档
3. 开启minmap可以有效降低带宽,但是会增加内存 33%
4. 各向异性过滤,建议不开启或者只单独处理
它是默认开启的,一般设置Per Texture,然后需要在图片上开启。
开启以后会增加采样,会降低纹理mipmap过渡时的锯齿。
5. 如果ui图片的尺寸不符合标准,会采用无损压缩,会造成浪费。
纹理和Mesh的检查工具,可以一键查看相关占用
可以一键检查出对应的大文件。
Mesh统计了使用次数的总占用,可以清晰的查看当前Mesh在场景的总占用。红色为未合并网格。
贴图相关检测
可以检测贴图的尺寸是否规范
可以检测贴图尺寸是否过大
会将非4的倍数的图片导出到相应文件夹,然后美术同学可以修改完成图片后,对资源进行替换。
shader相关检查
可以查看所有shader变体数量
可以打印出项目中shader的所有变体数量。
变体减少的办法就是减少宏的使用,如果没办法,就少用multi_compile,使用shader_feature
变体的相关使用 点击此处看官网
资源引用查找
可以查看资源之间的互相引用,Uses可查看使用的资源,Used By可以查看被引用,Unused Assets查看没有被使用的资源
可以选中物体进行查看相关引用,或者向上查找
Prebe资源分析
查找一个Prefab的资源引用分析,以及占用。
蒙皮动画也在游戏运行时占用比较大的性能,一般都会有一些方式解决,这里我推荐之前项目中使用的,使用GPU Skining + LOD,近处的模型使用默认蒙皮动画,保证效果,远处的角色模型,则使用低模+顶点动画烘焙动画贴图,根据颜色像素转换反向和距离,重新生成顶点位置绘制,这种方式还支持合批甚至GPU Instancing提高性能。
资源加载有时也会出现卡顿的情况 查看官方文档,这个一般需要程序同学协助完成。
默认情况下,Shader会在首次渲染几何体是进行加载,这也是我们减少变体的原因之一。如果使用了相同的变体和Shader,渲染新的几何体时,将不会在重新加载Shader。
有时会运行卡顿,我们可以使用预加载的形式进行Shader加载。
优化unity UI,这是先备份一下,需要时再看。