TA-Shader-文件 (转) Unity ShaderLab内存优化
发布于
2018-8-9
9934
27
TA资源类型
TA资源类型: 其它 
shader资源类型: 其它 
适用引擎: unity 其它 
资源介绍: -

您需要 登录 才可以下载或查看,没有账号?注册

x
我们在项目中使用shader,常见的,两种方式:
第一种是,给render附上一个材质,材质用某一个shader,这种情况,使用assetbundle热更新即可。
第二种是,runtime需要动态设置的shader,常使用Shader.Find()的方法来获取。这种方式,只有将shader放到Resources下,才能读取。但是Resources下的资源,是无法热更新的。
为了shader的热更,我们就不能用Shader.Find,而是要自己去实现一个类似的调用方式。如下:



  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using AdvancedInspector;
  4. using UnityEngine;
  5. using UnityEngine.UI;

  6. public class ShaderBinder : MonoBehaviour
  7. {
  8.     public ShaderVariantCollection shaderVariantCollection;

  9.     [Header("将所有要用的shader绑定到此")]
  10.     [Inspect]
  11.     [Descriptor("shader列表")]
  12.     [SerializeField]
  13.     private List<Shader> _shaders;

  14.     [HideInInspector]
  15.     public static ShaderBinder me;

  16.     [Inspect]
  17.     [SerializeField]
  18.     private List<Material> specialMats;

  19.     void Awake()
  20.     {
  21.         if (me != null)
  22.         {
  23.             Loger.LogError("重复创建ShaderBinder");
  24.         }

  25.         DontDestroyOnLoad(gameObject);
  26.         me = this;
  27.         if (shaderVariantCollection != null)
  28.         {
  29.             shaderVariantCollection.WarmUp();
  30.         }
  31.         else
  32.         {
  33.             Shader.WarmupAllShaders();
  34.         }
  35.     }

  36.     public Shader getShader(string shaderName)
  37.     {
  38.         for (int i = 0; i < _shaders.Count; i++)
  39.         {
  40.             if (_shaders[i].name == shaderName)
  41.             {
  42.                 return _shaders[i];
  43.             }
  44.         }

  45.         Loger.LogError(string.Format("can not find shader: {0}", shaderName));
  46.         return null;
  47.     }
  48. }
点击此处复制文本

我们可以这样使用
  1. Shader targetShader = ShaderBinder.me.getShader(targetShaderName);
点击此处复制文本

在使用之前,我们把需要get的shader,拖到对应的脚本上。让后将对应的prefab打包成assetbundle,在游戏开始前load出来。
1.jpg 动态调用的,需要热更新的shader

  • shaderlab的内存优化
shaderlab的内存优化,有文章已经讲得比较清楚了:Unity3D性能优化:ShaderLab内存占用
shaderlab的内存问题,第一个就是standard shader。有几种可能会引入standard shader:
  1,import 模型的时候,自动创建的材质。
2.jpg
import model自动引入的材质

即使我们去掉import materials的勾选,还是会引入这个材质。
想要彻底地去掉,需要将默认render的材质清空,或者设置一个自己定义的材质:

设置为自定义的一个材质

2,美术或者程序,在制作场景,制作资源的时候,错误地使用了默认的材质。例如,在场景中创建了一个默认的cube,这个cube,就会使用默认的材质,默认材质用的就是standard shader。
    对于游戏场景,我们可以在保存场景的时候,自动替换所有场景中默认的材质。


替换掉默认材质,替换掉standard shader
通过游戏场景的保存,能大部分解决问题了。
但是,程序可能用到的材质,可能散落在各处。每个项目理论上都能找出所有真正打包需要的所有prefab,然后用上面的方法统一替换包含standard的材质即可。
我们项目,之前文章说过基于ResourceId的管理方式,所以非常方便地找出所有会被打包的资源。
通过上面的方法,我们项目,已经排除了standard shader,在真机测试中,shaderlab的内存,降到了20多M。

  • 进一步优化shaderlab的内存
通过对standard的剔除,shaderlab降到了20M左右。
我们在看profile的分析的时候,发现这样一种情况,在profile中,我们看到同一个shader,会有多个copy,例如下图的Diffuse。


在我的项目中,这种情况,是因为我们的prefab,或者粒子特效,用的都是unity内置的shader,这些shader,在打包assetbundle的时候,是不会被打包的。
导致存在冗余,具体说明,可以看这篇文章的介绍Unity 5.x AssetBundle零冗余解决方案,这里面提到的内置资源的冗余,就是我提到的情况。

但是,我认为上面assetbundle零冗余方案的解决方案不是太好,所以,在研究和测试后,我们有了自己的方法,去处理依赖unity内置资源的问题。

1, 下载unity的build in shader,导入到项目中(如果项目开始就这么做了,能省很多事),后续当我们在材质上选择shader的时候,用的就不是build in的shader,而是导入到工程的shader,就和我们其他shader一样,可以更改,可以热更,打包也不会冗余了。



2, 替换默认的材质。美术制作资源的时候,有时候会用默认的材质,除了Default-Material,还有Default-Particle(特效经常用),Sprites-Default。
我们不可能要求美术注意到不用默认材质,对他们要求太高了,也不科学。
所以,我们需要用脚本做统一更改。
我们就用之前的脚本,对需要打包的资源,做统一替换材质即可





第一个红框内,是替换默认材质,第二个红框内,是替换为导入的shader。
通过这个优化之后,我们在用profile看的时候,应该解决了90%的重复,还有很少数的重复,我没有仔细研究是哪里来的。我们花20%的精力,解决掉80%的问题,shaderlab已经从20多M,下降到5M,我觉得已经ok了。
这个方法带来的好处,除了shaderlab内存降低,也使我们不再依赖不可编辑的内置shader,让所有的shader都可改,可更新。


  • 再进一步优化shaderlab
上面的方法,很好地运行了一段时间,但是在几个月后我再一次profile的时候发现,shaderlab,又涨到28M了,这次即没有standard,也没有内置shader冗余的问题。
在仔细地分析测试后,定位在我们使用的后处理shader上,我们使用的后处理是:Unity-Technologies/PostProcessing,根据筛选,我们只用到其中的bloom 和 Color Grading,只有这两个,不应该,额外增加了20M多的内存吧。
最后分析,是因为后处理的multi_compile,导致过多的shader变种,而很多变种,是我们不需要的






注释掉以后(记得注释对应的shader内对应的#if 这类代码块),shaderlab从28M回到了6M多点,这就是一个合理的数据了。
============================
最后,总结下shaderlab的内存优化:
  • 清理standard的使用,不要让其进入打包内容
  • 处理内置shader和默认材质的问题,替换为创建的材质和导入的shader,减少冗余。
  • 清理复杂shader的multi_compile或者shader feature,删除或注释不需要的,减少shader变种
希望这篇简单的说明,能给大家带来帮助。








参与人数 2 元素币 +21 活跃度 +38

本帖被以下画板推荐:

还没有设置签名!您可以在此展示你的链接,或者个人主页!

使用道具 举报 登录

回复 <
yeshengwu  发表于 2018-8-9 07:25:45  
2#
感谢大佬讲解~~
回复 收起回复
使用道具
天蝎  发表于 2018-8-9 08:51:43  
3#
学习了····感谢大神的分享···
回复 收起回复
使用道具
MAX小伙  发表于 2018-8-9 09:18:09  
4#
好贴,谢谢分享!
回复 收起回复
使用道具
qq_独角戏_UZQ  发表于 2018-8-23 11:43:10  
5#
眼花
回复 收起回复
使用道具
時間回流  发表于 2018-9-2 20:50:21  
6#

感谢大佬讲解~~
回复 收起回复
使用道具
chXX  发表于 2018-9-3 09:59:17  
7#
不放在Resousrce下 ,Shader.Find()也能找到啊!
回复 收起回复
使用道具
ZhaoZG  发表于 2018-10-15 10:13:23  
8#
66666666666666666666666666666
回复 收起回复
使用道具
asdasdcsdsadfa  发表于 2018-10-15 10:47:07  
9#
资源哪里好,肯定元素找!
回复 收起回复
使用道具
minge111  发表于 2018-11-6 09:36:44  
10#
大佬 看不懂 要从哪里学起
回复 收起回复
使用道具
yaoyuan777  发表于 2018-11-6 09:54:23  
11#
支持一下
回复 收起回复
使用道具
qq_wangbingxv_i  发表于 2018-11-11 11:07:21  
12#
多谢分享。
回复 收起回复
使用道具
peet07  发表于 2018-11-11 21:25:51  
13#

资源甚好,发帖艰辛,且阅且珍惜
回复 收起回复
使用道具
qq_男爵_N7Z  发表于 2018-11-17 09:44:59  
14#
厉害了
回复 收起回复
使用道具
旧巷少年  发表于 2019-3-15 19:12:43  
15#
甚好甚好
回复 收起回复
使用道具
MasterZjy  发表于 2019-3-25 14:47:52  
16#
感谢大佬,已学习
回复 收起回复
使用道具
泽浪  发表于 2019-3-26 11:15:28  
17#
好贴先收藏,先学会再说
回复 收起回复
使用道具
peet07  发表于 2019-3-28 13:36:02  
18#
好贴,谢谢分享!
回复 收起回复
使用道具
なら  发表于 2019-4-21 16:25:47  
19#
楼主是个人才
回复 收起回复
使用道具
なら  发表于 2019-4-21 16:25:49  
20#
楼主是个人才
回复 收起回复
使用道具
12下一页

快来发表你宝贵的意见吧!

成林 实名

通过了实名认证的内容创造者

unity3D

  • 价格:260元素币

  • 主题
    181
    精华
    28
    超神
    5
    扩散
    750
    微金
    3000
    智慧
    220
    余额
    0
    在线时间
    5805 小时

    【绝】结界玄晶 微库VIP 扩散者 紫色药水 学徒法袍 元素铜币 元素银币 元素金币 元素秘币 长剑 绿色药水 长枪 火元素

    快速回复 返回顶部 返回列表