游戏蛮牛学习群(纯技术交流,不闲聊):159852603
游戏蛮牛 手机端
开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2337

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 1166|回复: 18

[士郎] Unity ShaderLab内存优化

[复制链接]  [移动端链接]
排名
3
昨日变化

6892

主题

7416

帖子

2万

积分

Rank: 16

UID
1231
好友
185
蛮牛币
9948
威望
30
注册时间
2013-7-29
在线时间
3542 小时
最后登录
2018-10-23

社区QQ达人活力之星原创精华达人突出贡献奖财富之证游戏蛮牛QQ群会员蛮牛妹VIP

发表于 2018-8-7 11:56:49 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

x
  • 先简单说下shader的热更新

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

public class ShaderBinder : MonoBehaviour
{
    public ShaderVariantCollection shaderVariantCollection;

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

    [HideInInspector]
    public static ShaderBinder me;

    [Inspect]
    [SerializeField]
    private List<Material> specialMats;

    void Awake()
    {
        if (me != null)
        {
            Loger.LogError("重复创建ShaderBinder");
        }

        DontDestroyOnLoad(gameObject);
        me = this;
        if (shaderVariantCollection != null)
        {
            shaderVariantCollection.WarmUp();
        }
        else
        {
            Shader.WarmupAllShaders();
        }
    }

    public Shader getShader(string shaderName)
    {
        for (int i = 0; i < _shaders.Count; i++)
        {
            if (_shaders.name == shaderName)
            {
                return _shaders;
            }
        }

        Loger.LogError(string.Format("can not find shader: {0}", shaderName));
        return null;
    }
}

我们可以这样使用
[AppleScript] 纯文本查看 复制代码
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 模型的时候,自动创建的材质。


6.jpg



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

7.jpg

设置为自定义的一个材质

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

替换掉默认材质,替换掉standard shader



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


通过上面的方法,我们项目,已经排除了standard shader,在真机测试中,shaderlab的内存,降到了20多M。
  • 进一步优化shaderlab的内存

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

5.jpg



在我的项目中,这种情况,是因为我们的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变种,而很多变种,是我们不需要的
8.jpg

非常多的变种

解决方法是,根据需求,注释掉不需要的变种即可
9.jpg


注释掉不需要的
注释掉以后(记得注释对应的shader内对应的#if 这类代码块),shaderlab从28M回到了6M多点,这就是一个合理的数据了。

最后,总结下shaderlab的内存优化:
  • 清理standard的使用,不要让其进入打包内容
  • 处理内置shader和默认材质的问题,替换为创建的材质和导入的shader,减少冗余。
  • 清理复杂shader的multi_compile或者shader feature,删除或注释不需要的,减少shader变种

希望这篇简单的说明,能给大家带来帮助。

知乎@Gordon







2.jpg
3.jpg

跟我念“站长妹纸萌萌哒!”我说站长,你说YO!爱你们么么哒~
回复

使用道具 举报

5熟悉之中
686/1000
排名
6574
昨日变化

4

主题

298

帖子

686

积分

Rank: 5Rank: 5

UID
191995
好友
1
蛮牛币
1503
威望
0
注册时间
2016-12-13
在线时间
180 小时
最后登录
2018-10-23
发表于 2018-8-7 14:44:55 | 显示全部楼层

回复

使用道具 举报

3偶尔光临
170/300
排名
27776
昨日变化

1

主题

68

帖子

170

积分

Rank: 3Rank: 3Rank: 3

UID
5719
好友
0
蛮牛币
198
威望
0
注册时间
2013-10-15
在线时间
89 小时
最后登录
2018-10-15
发表于 2018-8-7 16:04:36 | 显示全部楼层
看完这篇文章,我脖子不痛了

回复 支持 反对

使用道具 举报

3偶尔光临
244/300
排名
10475
昨日变化

0

主题

96

帖子

244

积分

Rank: 3Rank: 3Rank: 3

UID
267358
好友
0
蛮牛币
328
威望
0
注册时间
2018-2-1
在线时间
54 小时
最后登录
2018-9-30
发表于 2018-8-7 16:09:52 | 显示全部楼层
[发帖际遇]: 一个袋子砸在了 Wangyu_qq 头上,Wangyu_qq 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

4四处流浪
429/500
排名
8044
昨日变化

0

主题

223

帖子

429

积分

Rank: 4

UID
281167
好友
1
蛮牛币
858
威望
0
注册时间
2018-5-14
在线时间
64 小时
最后登录
2018-9-27
发表于 2018-8-7 20:48:28 | 显示全部楼层
学习了,感谢感谢

回复

使用道具 举报

7日久生情
2137/5000
排名
2815
昨日变化

1

主题

1375

帖子

2137

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
119154
好友
0
蛮牛币
2282
威望
0
注册时间
2015-8-21
在线时间
271 小时
最后登录
2018-10-22
发表于 2018-8-8 09:36:21 | 显示全部楼层
谢谢楼主大大。

回复

使用道具 举报

5熟悉之中
966/1000
排名
3336
昨日变化

1

主题

159

帖子

966

积分

Rank: 5Rank: 5

UID
139214
好友
0
蛮牛币
1430
威望
0
注册时间
2016-3-12
在线时间
388 小时
最后登录
2018-10-23
发表于 2018-8-8 09:54:14 | 显示全部楼层

回复

使用道具 举报

5熟悉之中
699/1000
排名
6171
昨日变化

2

主题

332

帖子

699

积分

Rank: 5Rank: 5

UID
112390
好友
2
蛮牛币
860
威望
0
注册时间
2015-7-7
在线时间
155 小时
最后登录
2018-10-23
发表于 2018-8-8 10:16:04 | 显示全部楼层
不错,谢谢分享                  
[发帖际遇]: swordlegend 发帖时在路边捡到 1 蛮牛币,偷偷放进了口袋. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

排名
46139
昨日变化

0

主题

4

帖子

9

积分

Rank: 1

UID
287956
好友
0
蛮牛币
18
威望
0
注册时间
2018-6-30
在线时间
1 小时
最后登录
2018-8-8
发表于 2018-8-8 13:26:18 | 显示全部楼层
不错.感谢分享
[发帖际遇]: 一个袋子砸在了 zhangjiangen 头上,zhangjiangen 赚了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

5熟悉之中
579/1000
排名
5802
昨日变化

6

主题

98

帖子

579

积分

Rank: 5Rank: 5

UID
5349
好友
1
蛮牛币
2157
威望
0
注册时间
2013-10-10
在线时间
265 小时
最后登录
2018-10-19
发表于 2018-8-8 21:09:34 | 显示全部楼层
非常好的文章。Mark一下
[发帖际遇]: d_kb 捡了钱没交公 蛮牛币 降了 2 . 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1249/1500
排名
2197
昨日变化

0

主题

293

帖子

1249

积分

Rank: 6Rank: 6Rank: 6

UID
135463
好友
0
蛮牛币
94
威望
0
注册时间
2016-1-23
在线时间
354 小时
最后登录
2018-10-23
发表于 2018-8-9 09:52:07 | 显示全部楼层
yhgjghf tg;,rd gf,;dmg;lfdmpvfdlmpglkmdfpgfdgdz

回复 支持 反对

使用道具 举报

2初来乍到
102/150
排名
13877
昨日变化

0

主题

12

帖子

102

积分

Rank: 2Rank: 2

UID
254938
好友
0
蛮牛币
134
威望
0
注册时间
2017-11-17
在线时间
36 小时
最后登录
2018-8-28
发表于 2018-8-9 10:35:13 | 显示全部楼层

回复

使用道具 举报

2初来乍到
148/150
排名
10148
昨日变化

0

主题

7

帖子

148

积分

Rank: 2Rank: 2

UID
196702
好友
0
蛮牛币
244
威望
0
注册时间
2016-12-28
在线时间
43 小时
最后登录
2018-8-18
发表于 2018-8-9 10:57:13 | 显示全部楼层

回复

使用道具 举报

5熟悉之中
843/1000
排名
5532
昨日变化

0

主题

436

帖子

843

积分

Rank: 5Rank: 5

UID
146677
好友
9
蛮牛币
2733
威望
0
注册时间
2016-4-25
在线时间
167 小时
最后登录
2018-10-23
QQ
发表于 2018-8-9 19:30:48 | 显示全部楼层
谢谢分享,支持一下

回复 支持 反对

使用道具 举报

5熟悉之中
634/1000
排名
4021
昨日变化

3

主题

63

帖子

634

积分

Rank: 5Rank: 5

UID
41534
好友
6
蛮牛币
3273
威望
0
注册时间
2014-8-24
在线时间
216 小时
最后登录
2018-9-26
发表于 2018-8-10 10:22:15 | 显示全部楼层
学习啦。收益匪浅

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

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