当前位置: 首页 > news >正文

Unity技术分享连载(64)|Shader Variant Collection|Material.SetPassFast

Unity技术分享连载(64)|Shader Variant Collection|Material.SetPassFast

https://www.codetd.com/article/8857415

Unity技术分享连载(64)|Shader Variant Collection|Material.SetPassFast

https://www.jianshu.com/p/ed347dcff35e

原文链接:
https://blog.uwa4d.com/archives/TechSharing_64.html
我们将从日常技术交流中精选若干个开发相关的问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。
UWA QQ群:465082844
UWA 问答社区:answer.uwa4d.com


资源管理

Q1:Unity 5 的 Shader Variant Collection 功能是否推荐使用?我有以下3个疑点:
1)使用 Shader 变体之后,Shader 是否还能走资源更新?抑或 Shader 不推荐走资源更新?
2)Shader 变体和 Shader Always Include 的主要区别是什么?二者对内存和帧率影响如何?
3)在 Unity 5 较早的版本中,Shader 变体功能似乎有一些Bug,现在是否可靠?

经过测试,在较新的版本中(如Unity 5.5.3),将ShaderVariantCollection与Shader打包在相同的AssetBundle中后,其中会包含该Shader在ShaderVariantCollection中指定的Variant。因此:

1)使用 ShaderVariantCollection后依然可以进行资源更新(通过更新AssetBundle,来更新Shader的实现或者ShaderVariantCollection中包含的Variant)。

2)ShaderVariantCollection与Always Included Shaders的区别主要在于打包时所包含的Variant。Always Included Shaders中的Shader,其所有的Variant都会被包含,好处是,理论上不会出现Variant丢失的情况;坏处是,会导致更大的发布包以及额外的内存占用,而影响最大的是手动进行Warmup时的耗时以及ShaderLab的内存占用。因此一般来说,对于Variant特别多的Shader(如Standard Shader),并不推荐放入Always Included Shaders中。

3)目前即使是较新的版本,其可靠性我们也并不能确保,依然建议在使用前进行一些测试来验证。

此问答来自于UWA 问答社区:
https://answer.uwa4d.com/question/591418087640b5a822204e73
如您对该问题仍有疑问,可以转至社区进行进一步交流。


性能优化

Q2:请问为什么我项目渲染中Material.SetPassFast的开销这么高?这个该如何优化?

 

Material.SetPassFast是Unity引擎在渲染过程中Material的轮循切换开销,一般在Unity5.0~Unity5.3版本中出现。它的开销主要分为两种:

1) Shader.CreateGPUProgram峰值开销
这种情况主要出现在Shader第一次渲染时。在Unity5.0以后,引擎为了避免Shader加载时过高的CPU峰值出现,已经将Shader.Parse和Shader.CreateGPUProgram两种操作分开执行,前者在Shader加载时,后者在Shader第一次渲染时。下图则为一款项目运行时渲染时的Shader.CreateGPUProgram开销。

 

2) 渲染状态切换开销
这种情况是几乎每一帧都发生的,有渲染的地方就会有Material的切换。从问题图中可以看出,在运行的16000帧中,Material.SetPassFast一共被调用137万次。这里可以认为几乎全部是渲染时Material的切换操作。因此,该项较高的主要原因还是材质切换操作过多所致。所以,建议研发团队在报告中的详细材质页面查看是否有过多“冗余”的材质出现,如有则尽可能降低材质的使用冗余度。

 


动画

Q3:Animator会把所有状态的AnimationClip加载到内存,有什么好的办法可以动态加载?

1)Animator Controller结构不需要改变,但动画需要变化。比如随着人物等级或技能升级,同种的攻击动作随着变化等。该种需求可以通过AnimatorOverrideController来进行完成,即按需加载新的AnimationClip,然后替换AnimatorOverrideController中相应的AnimationClip即可。目前,Unity的AnimatorOverriderController不仅可以进行单个替换,同时也可以ApplyOverrides成组替换;

2)Animator Controller结构需要改变,类似于Animation老版本动画的AddClip功能。这种需求需要替换AnimatorController,研发团队可以在动态加载AnimationClip的同时,动态加载相应的Animator Controller,然后进行替换即可。

以上方法研发团队可根据自身实际情况而定。


动画

Q4:为什么Transform.设置Parent会触发Animator的初始化吗?Parent是等于null的。

 

把 Parent 设为null,相当于把这个 GameObject 变为根节点。如果在设置之前这个 GameObject 本身是激活状态,但其的父节点是未激活状态,那么设置之后,相当于把这个GameObject 激活。而激活GameObject 时就会触发 Animator.Initialize 等操作了。


资源管理

Q5:美术做粒子的时候,粒子与粒子之间共用资源的情况很多,例如某几个粒子共用一个Material,某几个粒子共用一个贴图等,应该如何组织AssetBundle?要是对应到最细的那个程度,凡是共用过的资源都单独打一个AssetBundle,好像又会很琐碎,假如不那么做,粒子与粒子之间的AssetBundle又会有冗余。这方面有什么好的建议?

AssetBundle打包没有标准的方式,单就粒子系统而言,因为其个体本身比较小,并且在项目中经常大量出现,所以并不建议将粒子系统逐个打包,而是建议根据其出现频率进行打包,比如将同一段时间、同一出现场景等的粒子系统打包在一起。同时,由于粒子系统的Shader基本上都是Unity内置Shader,因此,尽可能将Shader进行依赖打包。我们在UWA Day 2017上对于这种情况进行了详细说明,其Shader在中低端移动设备上的加载开销较高,需要研发团队特别关注。

今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站(answer.uwa4d.com)上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:465082844(仅限技术交流)

 



作者:侑虎科技
链接:https://www.jianshu.com/p/ed347dcff35e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

 

 

 

 

 

相关文章:

  • 最新的asmdef定义的模块中,VisualStudio中无法引用UnityEngine.iOS.XCode命名空间
  • UNIYT关于V S2017,VS2019断点调试卡住的问题
  • Mac上用VS Code调试 Unity程序
  • Jenkins的Credentials(证书)管理
  • jenkins 添加 证书凭证Credentials
  • Mac Jenkins集成打包踩过的坑
  • 【Unity】AssetBundle化したプレハブの中でRenderTextureを持っていたらエラーが出た
  • GDC 2017上的Keynote:
  • UE4获取UProperty的值,以及一些情况下的UClass获取
  • Unity Mac Vscode 调试
  • c# 装箱拆箱
  • 【Unity】TimeLineCinemachine系列教程——动态赋值,我要打十个!
  • Unity Timeline 二次简单封装TimelineProxy(代理)
  • 用Timeline实现动画特写(下)
  • Unity Timeline PlayableDirector GetGenericBinding
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 【翻译】babel对TC39装饰器草案的实现
  • Apache Pulsar 2.1 重磅发布
  • JavaScript创建对象的四种方式
  • JavaScript学习总结——原型
  • leetcode讲解--894. All Possible Full Binary Trees
  • MQ框架的比较
  • React-生命周期杂记
  • Synchronized 关键字使用、底层原理、JDK1.6 之后的底层优化以及 和ReenTrantLock 的对比...
  • UEditor初始化失败(实例已存在,但视图未渲染出来,单页化)
  • unity如何实现一个固定宽度的orthagraphic相机
  • vue-loader 源码解析系列之 selector
  • vue学习系列(二)vue-cli
  • 深入浅出Node.js
  • 由插件封装引出的一丢丢思考
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • Nginx实现动静分离
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • # Panda3d 碰撞检测系统介绍
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #FPGA(基础知识)
  • $nextTick的使用场景介绍
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (分布式缓存)Redis持久化
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (四)Linux Shell编程——输入输出重定向
  • *2 echo、printf、mkdir命令的应用
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .net 按比例显示图片的缩略图
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .net程序集学习心得
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • /var/lib/dpkg/lock 锁定问题
  • @DataRedisTest测试redis从未如此丝滑
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @SuppressWarnings(unchecked)代码的作用