Unity中Shader是否可以热更新的测试-程序员宅基地

技术标签: 游戏  移动开发  

在unity的资源中,shader是比较特殊的一类。主要有下面几个疑问

1. Shader算是代码,并且需要编译。那么是否可以热更新?

2. AB中加载进来的shader是否可以通过shader.Find(名称)来索引?

3.在使用shader_feature关键字后,build时忽略的变种是否要在运行时编译?

4.预编译shader cache的存储位置究竟在哪里?

 

直接补充最终结论:

1. shader可以热更新。

2. 使用multi_compile生成Shader Variant时,材质可以直接热更新。

3. 使用shader_feature生成Shader Variant时,可以使用ShaderVariantCollection来记录所有使用到的变种,实现材质更新。(目前仍有bug,必须将shader、SVC和所有材质放在一个AB中)

4. 不要用Shader.Find找自己包里的shader,使用AssetBundle.LoadAsset<Shader>()

5. shadercache随材质存储,材质可以热更新。

 

 

针对以上问题我做了一系列测试,记录如下:

 

测试一:

准备一个shader ,一个材质,一个cube做的prefab,各自打成一个AB。

在一个空场景中用脚本按如下顺序加载:

shaderAB->materialAB->prefabAB->prefab->GameObject。显示正常。

(事实上只要保证prefabAB->prefab->GameObject的顺序,materialAB和shaderAB在同一函数的任意位置都可以。Unity应该是延迟处理了资源的引用关系)

修改shader,打成新的ab,改名或者另存为备用。

发布以后,在文件夹中找到对应的shaderAB,使用新的shaderAB替换。

重新启动,效果已经更新。

结论一: shader可以热更新!

测试平台:android和pc standalone

代码稍作修改可以在运行时实现热更新。

 

测试二:

准备3个shader,引用同一个头文件。shader和cginc全部进入一个ab里。

运行时先加载shaderAB,然后用一个按钮切换shader

结果如下表:

 

热更新前

热更新后

Shader.Find

正常(原shader)

错误(shader丢失)[1]

AssetBundle.LoadAsset[2]

正常(原shader)

正常(新shader)

[1]    在Standalone或者移动平台上会有shader丢失;在Editor模式下会使用旧的shader,仔细分析后猜测是在Editor模式下,shader.Find的查找顺序如下:已加载的 AssetBundle->Shader源文件。而在发布平台上,由于没有散的shader源文件,所以直接丢失。

[2]    AssetBundle.LoadAsset的路径要使用Manifest中记载的路径,如下形式:

        Assets/Shaders/Src/shaderTest2.shader

结论二:可以在运行时手动替换上AB中的shader,但必须使用AssetBundle.LoadAsset

·可以使用cginc头文件!

·可以使用文件夹管理Shader!

·最好完全不使用Shader.Find,除非你100%确定这个shader不会热更新。

关于Shader.Find,个人猜测如下:

Unity内部使用一个字典或者HashSet来支持Shader.Find,这里暂且叫它ShaderMap。ShaderMap的键是ShaderLab语法中的名字;值是Shader文件的GUID。

ShaderMap生成于Build项目时,保存了来自三个地方的shader cache引用关系:

1.      Resources中的shader或Resources其中其他资源引用到的shader

2.      任意场景中引用到的shader

3.      StreamingAssets中Asset Bundle内的Shader

         运行时使用ShaderFind,只能找到这些Shader,如果对应GUID的shader不存在,查找就会失败,即使热更新后加入了新的Asset Bundle中含有同名Shader(即ShaderLab语法同名)。

4.      目前没有办法在发布以后动态更新ShaderMap。

  

 

测试三:

准备两个同样的shader,设定好#ifdef FEATURE,其一使用multi_compile,其二使用shader_feature

准备四个材质,分别对应

·multi_compile      FEATURE on

·multi_compile      FEATURE off

·shader_feature   FEATURE on

·shader_feature   FEATURE off

所有shader打成一个ab, 所有material打成一个ab

在运行时切换4个材质。结果如下:

·multi_compile   FEATURE off

正常

·multi_compile   FEATURE on

正常

·shader_feature  FEATURE off

正常

·shader_feature  FEATURE on

错误(和shader_feature  FEATURE off一样)

 

结论三:

·使用shader_feature的uber shader无法热更新!(结论已更新)

·若将shader存储于自定义AB时,仅按照所有shader_feature都没有定义的方式来编译。并且不会汇报这个编译过程中的任何错误!(如:在shader中定义了shader_feature A B;并且依赖于A、B二者任一必须定义的话,编译就会出错。)

·Unity并不会在发布平台上编译缺失的变种。(直接拿个现有的变种凑数?)

 

测试四

放弃热更新shader,检查在使用shader_feature的时候,材质能否热更新。即能否在热更新时生成缺失的变种。

准备一个uber shader。再来3个材质,各使用不同的变种,并分别打成m1,m2,m3三个包。发布时仅选择m1发布,然后在运行时热更新,使用m2,m3替换m1,显示效果达到预期。

这时候注意到m1,m2,m3体积分别为11,9,11KB,应该不只是存有shader引用和相关参数。因此再将m1,m2,m3打为一个ab,体积为11kb。

结论四:

·在shader进入mainAssets的前提下,材质可以热更新。

·shader cache随material ab存储,多个引用了同样shader(变种)的材质会重复存储cache。

 

更新测试五

使用ShaderVariantCollection,记录所有用到的variant。

将SVC和shader打入一个ShaderAB。

将材质打成MaterialAB

运行时加载ShaderAB,取SVC,WarmUp,再加载MaterialAB。结果丢失部分variant

 

更换分包方式,SVC、shader和Material打成一个包。一切正常。

结论五:

·使用ShaderVariantCollection可以做到带变种的材质更新。

·目前版本(5.6.0和5.5.2)依然有bug,必须将SVC、shader和所有对应材质放在一起才能做到可热更新。

 

 

备注:

·为了测试,我用HFS配置了局域网http服务器,只要在同一个无线网端下,pc和手机都能访问,配合不同平台的AB分文件夹管理,所有平台都能同步看到效果。

 ·ab.Unload()会把ab设为null!

 ·cginc头文件修改后,所有用到的shader必须手动import一次以强制重新编译!

测试二用到的工程(AB和热更新)

 

参考资料:

·hfs使用介绍:http://bbs.feng.com/read-htm-tid-2234118.html

·ab模型:http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html

·www禁用cache方法:http://answers.unity3d.com/questions/209078/disable-cache-for-www.html

 

转载于:https://www.cnblogs.com/cpxnet/p/6439706.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30847939/article/details/98280946

智能推荐

hdu 1229 还是A+B(水)-程序员宅基地

文章浏览阅读122次。还是A+BTime Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24568Accepted Submission(s): 11729Problem Description读入两个小于10000的正整数A和B,计算A+B。...

http客户端Feign——日志配置_feign 日志设置-程序员宅基地

文章浏览阅读419次。HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息。FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。NONE:不记录任何日志信息,这是默认值。配置Feign日志有两种方式;方式二:java代码实现。注解中声明则代表某服务。方式一:配置文件方式。_feign 日志设置

[转载]将容器管理的持久性 Bean 用于面向服务的体系结构-程序员宅基地

文章浏览阅读155次。将容器管理的持久性 Bean 用于面向服务的体系结构本文将介绍如何使用 IBM WebSphere Process Server 对容器管理的持久性 (CMP) Bean的连接和持久性逻辑加以控制,使其可以存储在非关系数据库..._javax.ejb.objectnotfoundexception: no such entity!

基础java练习题(递归)_java 递归例题-程序员宅基地

文章浏览阅读1.5k次。基础java练习题一、递归实现跳台阶从第一级跳到第n级,有多少种跳法一次可跳一级,也可跳两级。还能跳三级import java.math.BigDecimal;import java.util.Scanner;public class Main{ public static void main(String[]args){ Scanner reader=new Scanner(System.in); while(reader.hasNext()){ _java 递归例题

面向对象程序设计(荣誉)实验一 String_对存储在string数组内的所有以字符‘a’开始并以字符‘e’结尾的单词做加密处理。-程序员宅基地

文章浏览阅读1.5k次,点赞6次,收藏6次。目录1.串应用- 计算一个串的最长的真前后缀题目描述输入输出样例输入样例输出题解2.字符串替换(string)题目描述输入输出样例输入样例输出题解3.可重叠子串 (Ver. I)题目描述输入输出样例输入样例输出题解4.字符串操作(string)题目描述输入输出样例输入样例输出题解1.串应用- 计算一个串的最长的真前后缀题目描述给定一个串,如ABCDAB,则ABCDAB的真前缀有:{ A, AB,ABC, ABCD, ABCDA }ABCDAB的真后缀有:{ B, AB,DAB, CDAB, BCDAB_对存储在string数组内的所有以字符‘a’开始并以字符‘e’结尾的单词做加密处理。

算法设计与问题求解/西安交通大学本科课程MOOC/C_算法设计与问题求解西安交通大学-程序员宅基地

文章浏览阅读68次。西安交通大学/算法设计与问题求解/树与二叉树/MOOC_算法设计与问题求解西安交通大学

随便推点

[Vue warn]: Computed property “totalPrice“ was assigned to but it has no setter._computed property "totalprice" was assigned to but-程序员宅基地

文章浏览阅读1.6k次。问题:在Vue项目中出现如下错误提示:[Vue warn]: Computed property "totalPrice" was assigned to but it has no setter. (found in <Anonymous>)代码:<input v-model="totalPrice"/>原因:v-model命令,因Vue 的双向数据绑定原理 , 会自动操作 totalPrice, 对其进行set 操作而 totalPrice 作为计..._computed property "totalprice" was assigned to but it has no setter.

basic1003-我要通过!13行搞定:也许是全网最奇葩解法_basic 1003 case 1-程序员宅基地

文章浏览阅读60次。十分暴力而简洁的解决方式:读取P和T的位置并自动生成唯一正确答案,将题给测点与之对比,不一样就给我爬!_basic 1003 case 1

服务器浏览war文件,详解将Web项目War包部署到Tomcat服务器基本步骤-程序员宅基地

文章浏览阅读422次。原标题:详解将Web项目War包部署到Tomcat服务器基本步骤详解将Web项目War包部署到Tomcat服务器基本步骤1 War包War包一般是在进行Web开发时,通常是一个网站Project下的所有源码的集合,里面包含前台HTML/CSS/JS的代码,也包含Java的代码。当开发人员在自己的开发机器上调试所有代码并通过后,为了交给测试人员测试和未来进行产品发布,都需要将开发人员的源码打包成Wa..._/opt/bosssoft/war/medical-web.war/web-inf/web.xml of module medical-web.war.

python组成三位无重复数字_python组合无重复三位数的实例-程序员宅基地

文章浏览阅读3k次,点赞3次,收藏13次。# -*- coding: utf-8 -*-# 简述:这里有四个数字,分别是:1、2、3、4#提问:能组成多少个互不相同且无重复数字的三位数?各是多少?def f(n):list=[]count=0for i in range(1,n+1):for j in range(1, n+1):for k in range(1, n+1):if i!=j and j!=k and i!=k:list.a..._python求从0到9任意组合成三位数数字不能重复并输出

ElementUl中的el-table怎样吧0和1改变为男和女_elementui table 性别-程序员宅基地

文章浏览阅读1k次,点赞3次,收藏2次。<el-table-column prop="studentSex" label="性别" :formatter="sex"></el-table-column>然后就在vue的methods中写方法就OK了methods: { sex(row,index){ if(row.studentSex == 1){ return '男'; }else{ return '女'; }..._elementui table 性别

java文件操作之移动文件到指定的目录_java中怎么将pro.txt移动到design_mode_code根目录下-程序员宅基地

文章浏览阅读1.1k次。java文件操作之移动文件到指定的目录_java中怎么将pro.txt移动到design_mode_code根目录下

推荐文章

热门文章

相关标签