使用Visual Effect Graph创作惊艳的视觉效果

在Unite LA 2018期间,我们发布了在Unity中创作实时视觉效果的工具Visual Effect Graph,该工具使用在GPU运行的计算着色器和基于节点的工作流程。本文将比较Visual Effect Graph和现有的粒子系统,并展示如何开始使用这款强大工具。

113143lz5atn08p83dv586.png.thumb.jpg

Visual Effect Graph受到主流电影特效软件的启发,加入了许多相同的强大功能用于创作实时视觉效果,下面视频将对Visual Effect Graph进行简要介绍。

观看Visual Effect Graph介绍视频

入门
我们可以通过Unity 2018.3或更高版本编辑器中的资源包管理器安装Visual Effect Graph。

请点击Unity编辑器菜单Window > Package Manager,点开Advanced并选中“Show preview packages”,然后找到Visual Effect Graph,单击Install按钮即可。

113141px0dyx5y56mfz54q

目前,Visual Effect Graph运行于Unity 2018.3的高清晰渲染管线,对轻量级渲染管线的支持预计在之后的版本推出。为了使用Visual Effect Graph,请确保你的Unity项目使用High-Definition RP模板。

113141gq8mja0ez8m8wlk5.png.thumb.jpg

为了创建视觉效果,请在项目窗口点击右键,依次选择Create > Visual Effects > Visual Effects Graph。

创建资源后,将其拖到场景视图或层级窗口。

113142i0h8nsft0mvq0hvz

Visual Effect Graph窗口
Visual Effect Graph适用于VFX新手到资深艺术家和程序员等,Visual Effect Graph通过使用节点和属性模块,来提供一个快速学习,轻松掌握,强大的工作流程。

113142eddhp763aizogrxr

Context包含多个属性模块,用于表示应用于粒子的操作顺序。节点之间互相连接,会执行一系列输入属性模块的计算,从而定义粒子属性。节点系统会让使用Shader Graph着色器视图的用户感到很熟悉,但二个工具并不完全相同。

创建Context或单个节点,可以点击空格键,或单击右键,选择Create Node。创建属性模块,可在节点中点击空格键,或者单击右键,选择Create Block。

1、Context

113142jy9umxppoqj1b1iq.png.thumb.jpg

System是Initialize、Update和Output的Context组合。它由虚线轮廓表示。多个系统可以存在同一个Visual Effect Graph资源中。

Spawn定义生成粒子的数量和时间,例如Periodic Burst(间歇性喷发)、Constant(持续喷发)和Single Burst(单次喷发)等。

Initialize的前二个属性为Capacity(同时存在粒子数量)和Bounds(区域)。

Capacity确定每次系统中可以存在的粒子数量。

请注意:Capacity属性会根据粒子数量分配合适的内存,所以该数值应该对应可生成的粒子数量进行设置。通常,该值的计算公式为:Rate × Max Lifetime = Capacity

Bounds定义摄像机视图中粒子生成和模拟的区域。

Update会不断改变粒子属性,它是唯一可以使用作用力的部分。

Output会渲染粒子,它决定生成的粒子类型、纹理、颜色和方向。我们可以在此对粒子的大小,位置等属性进行最后调整。每个粒子系统可以有不同的输出结果,每个输出结果可以调整多数粒子属性。

2、Block
Block属性模块定义粒子的属性,这些属性可以由节点重写。Block包含在Context内,但有些属性模块无法在特定Context中使用。例如:Spawn Rate Block只能添加到Spawn Context中。

113143mdedzbt5tetz0550.png.thumb.jpg

我们可以通过取消勾选名称右侧的复选框禁用属性模块。有些输入内容可以通过点击输入名称左侧的小箭头展开,可以访问并修改详细属性,例如:Vector3的X,Y和Z。

在视图中选择Block和Context时,我们可以通过检视窗口修改它们。因此在创作视觉效果时,显示检视窗口可以方便创作过程。

113143jskvt7atvte7at1t.png.thumb.jpg

3、Node
Node节点具有很多功能,包括从输出指定数值和参数数据到执行各种不同的计算。Add,Multiply或Lerp等多数定义数值的节点可以通过修改来输出不同数值类型,例如:Float,Vector3或颜色数值。

113143o1l11gi0ywiilulu.png.thumb.jpg

流程工具
1、Auto Compile
默认情况下,每次修改节点或属性模块时,Visual Effect Graph都会重新编译。对于较小的视图,Auto Compile自动编译帮助我们在场景中快速看到改动效果。

但是对于比较复杂的系统,编译时间可能较长。禁用Auto Compile后,视图只会在保存或单击Compile按钮时进行编译,这样在大幅改动视图时,不必在每次调整后等待较长时间。

2、Blackboard
Blackboard面板可以存储视图中的参数,并公开给检视窗口以便进行修改。为了安排不同参数类型,Blackboard面板支持设置Categories类型和Tooltips提示信息。

113143k70v2ur50vgrpvzt.png.thumb.jpg

创建新参数,请点击Blackboard右上角的+图标。

113143g6l50pu5su7zd6dd.png.thumb.jpg

3、Target GameObject
Target GameObject面板允许你控制播放过程,或是查看场景中已打开视觉效果特定实例的本地空间辅助图示。

附加游戏对象,请点击场景中已打开的视觉效果实例,然后点击Attach,直接从场景实例打开视觉效果也会自动将该面板附加到游戏对象上。

113622irw5stkwlwj45wd2.png.thumb.jpg

4、Parameter Binders
虽然可以通过脚本来设置公开的参数,但Parameter Binders组件会自动配置视觉效果的参数,例如:游戏对象的位置,缩放和旋转。

113622cv2gvcenf28voxs8.png.thumb.jpg

添加Parameter Binder组件,请在层级窗口选中视觉效果,单击Add Component,搜索“Binder”并添加。将游戏对象拖到标着“None”的方框,然后点击 ⌄ 图标选择合适的参数。

113622bg5q5tk3z5dzxcnx.png.thumb.jpg

与现有粒子系统比较
Visual Effect Graph和粒子系统的主要区别在于它们运行的硬件。粒子系统在CPU模拟生成,而Visual Effect Graph将大量计算移动到运行在GPU的计算着色器。

113622q3lgsp81qlx5lvy8.png.thumb.jpg

从上面的对比图中,我们可以看出Visual Effect Graph的优点是能够模拟数百万个粒子,计算复杂的模拟过程,以及读取帧缓冲区。而粒子系统可以使用基础物理系统,并通过回读来与游戏交互。

特别需要注意的是设备兼容性,部分设备不支持Visual Effect Graph所需的计算着色器,例如:大多数的手机。

支持的数据类型
Visual Effect Graph支持使用Point Cache,Vector Field和Signed Distance Field等资源。通过这些资源的支持,可以表示体积、作用力、碰撞以及自定义数据类型。

Point Cache保存空间中点的属性,例如:Transform、法线、颜色和UV。
Vector Field在获取粒子的位置后,会在3D空间移动粒子。
Signed Distance Field可以使用体积来表示吸引和碰撞粒子。

下面的示例是在其它工具制作骷髅,然后导入Unity来创建魔法效果。

113623o9r439orhglrgtgy

VFX Toolbox工具集
Visual Effect Graph团队开发了一系列工具用于生成数据类型,这些工具统称为VFX Toolbox工具集。通过VFX Toolbox创建的数据可以与Unity的其它功能结合使用。

下载VFX Toolbox工具集:
https://github.com/Unity-Technologies/VFXToolbox

1、Image Sequencer
Image Sequencer图像序列工具可以处理图像序列,生成Flipbook纹理图集等纹理资源。

113623wqhmgaovivvtnnog.png.thumb.jpg

2、Point Cache Bake Tool
Point Cache Bake Tool点缓存烘焙工具又名为pCache Tool,它可以从纹理生成2D点缓存,从网格生成3D点缓存。

113623v2mdyi299dy9e327.png.thumb.jpg

使用技巧
1、便签,节点分组和名称
Visual Effect Graph带有一些实用功能,可以帮助注释和标记视图。

113623o2yk9op1kwzcmk9p

Context Names环境名称可以让你命名Context环境,只需双击Context环境标题部分的小型区域即可。

创建System Name系统名称,请双击虚线轮廓顶部下的小型区域。

Sticky Note便签功能可以创建可调整大小的文本框。创建标签,请在视图的空白区域单击右键,选择Create Sticky Note。

便签中,字体大小从Small到Huge共有四个选项,右键单击便签并从列表中选择修改字体大小。调整便签大小,可以拖动便签边缘或边角进行调整。

Node Group节点分组为节点的分组设置标题,并将它们作为整体进行移动。创建节点分组,请选择一组节点后,右键单击一个选中节点,然后选择Group Selection。

如果要移动节点到节点分组,将该节点拖入已有分组即可。如果要将节点移出分组,按住Shift键然后将其拖出分组。如果要删除分组而不删除节点,单击选中分组标题,然后按下Delete键即可。

2、Spawner Chaining
Spawner Chaining生成器链允许一个生成器开启或停止其它生成器。只要将Spawn Context的输出部分连接到Start或Stop即可。

下图中节点生成了持续2秒的常量流,停止2秒后会重复之前的操作。

113623dw0ggh2hwywmgbmf.png.thumb.jpg

2、GPU事件
GPU事件允许在自定义条件下或粒子消失时触发另一个粒子系统。下图中,节点会在粒子消失时生成10~15个粒子。

启用GPU事件,请打开Preferences>Visual Effects,勾选”Experimental Operators/Blocks”。

113623tpvptfpvbgu0zotj.png.thumb.jpg

3、Timeline
Visual Effect Graph完全兼容Timeline功能,可以准确控制视觉效果的时间设置。你可以通过二种方法控制效果:事件和参数。

如果要控制时间,请在Timeline中创建Visual Effect Activation Track。如果要控制参数,请在Timeline中创建Animation Track。

下面的视频展示了如何设置这些轨道,从而使它们继承来自事件的数值。

观看展示视频

下载示例项目
为了帮助大家学习Visual Effect Graph,开发团队发布了持续更新的Unity示例项目。首次发布时,该项目包含三个示例:
1、Unity Logo示例展示基本行为
2、Morphing Face示例展示HDRP Lit的兼容性和点缓存
3、Butterflies示例展示高级行为

下载示例项目:
https://github.com/Unity-Technologies/VisualEffectGraph-Samples

结语
Visual Effect Graph及其文档正处于开发和编写状态。虽然处于预览阶段,但我们可以在GitHub的Scriptable Render Pipeline Wiki中访问文档。

文档访问地址:
https://github.com/Unity-Technol … Visual-Effect-Graph

我们将分享Visual Effect Graph的一些教程,尽请期待。更多Unity更多信息介绍尽在Unity官方中文论坛(UnityChina.cn)!

高清晰渲染管线:专注视觉质量

在《可编程脚本渲染管线SRP》中,我们介绍了可编程脚本渲染管线SRP(Scriptable Render Pipeline)。在Unity 2018.1中,我们已为用户提供了二个渲染管线:轻量级管线Light Weight Pipeline和高清晰渲染管线High Definition Pipeline。在本文中,我们将聚焦高清晰渲染管线或HD RP。

可编程脚本渲染管线SRP项目,Github地址:
https://github.com/Unity-Technologies/ScriptableRenderPipeline

012633bi9ffg9i79f27z79.jpg.thumb

HD RP介绍

  • HD RP旨在为开发人员提供实现高清晰视觉效果渲染的工具。它的设计遵循以下三个原则:
  • 基于物理的渲染
  • 统一且一致连贯的光照
  • 独立于渲染路径的特征

基于物理的渲染依赖三大要素:光照、材质和摄像机。光照和材质的效果依赖于物理的相互作用,它们之间应有明确的解耦,能在各种光照条件下获得一致的效果。摄像机决定光照会怎样在屏幕上显示出来。渲染的目标是让艺术家更轻松地实现近乎真实的效果。

统一光照意味着场景中所有对象和参与介质都会得到相同的光照。对象的不透明度、透明度或体积材质不应有任何区别。一个材质必须与任意光照产生正常交互,不管该光照的光源是什么,例如反射探头、区域光等。甚至当被贴花修改时,交互也要正常发生。这样才能得到更为一致的外观效果。

在实时渲染中,有很多渲染通道:延迟/正向、单程/多程、平铺/集群等。在游戏开发中,所选取的渲染路径经常会限制可使用的图形功能。对于HD RP,我们尝试在不同渲染路径下增加相同的一组图形功能。这样的结果是,在选择渲染路径时只需要考虑性能,而不必考虑游戏需要哪些功能。

在HD RP的开发过程中,我们尽可能紧密地遵循这一原则。

HD RP的用途
HD RP针对高端PC和主机开发,可以提供惊艳的高清晰视觉效果。我们希望让小型团队也能使用AAA级图形功能。HD RP运行环境至少需要DX11级别的功能集,并大量使用计算着色器(Compute Shader)。但这样一来,HD RP就不会在功能较弱的平台上运行。HD RP支持的目标API是D3D11、D3D12、GNM(PlayStation 4)、Metal和Vulkan。我们也计划增加对VR支持,但还没在当前可用的预览版中实现。

HD RP具有一套全新的功能和行为,需要再学习和二次开发。我们提供了一个转换工具来将项目从Unity内置模式转为HD RP,但这只会帮助你快速重新设置材质和纹理。所有的光照、后期处理效果、场景设置、图形设置和自定义着色器都需要重做。

012735wxqxhtf13z2tujq3.png.thumb.jpg
Viking Village项目升级示例

最后,HD RP目前仍在预览阶段,这意味它还不适合用于正式创作流程。

光照改进
HD RP拥有一个全新的光照架构:它使用混合延迟/正向-平铺/集群渲染器。这意味着,在场景中有大量光照时,它比Unity内置渲染效果更好。这种新型光照架构更为注重性能。

012806ielflbzsejbw22om.png.thumb.jpg
在调试模式下可视化平铺光照列表

此外,HD RP还有大量额外的光照属性以及一个全新的光照编辑器。它可以淡化光照,仅影响漫反射光或镜面反射光,或是使用色温来设置光的颜色。聚光灯现在可以控制内部角度,而且可以拥有不同的形状,例如:椎体、立方体或金字塔体。HD RP还支持Colored cookies。

012806rzjjjyzl18jtcoc3.png.thumb.jpg

HD RP允许使用实时区域光,当前无阴影或烘焙。例如:柱形光。

012807a7594i9wb8wwb5b4.png.thumb.jpg

最后,光线遵循物理学平方反比衰减,使用的是物理光的单位。光照的控制完全是线性的,去除了Unity内置“Gamma mode”。太阳光强度使用的单位是勒克斯(lux),而点光源和聚光灯所用的单位是流明(Lumen)。

012808rtj88zy3rfrfdbft.jpg.thumb

在处理基于图像的光照方面,反射探头在HD RP中得到了更大提升。现在可以使用定向边界方框或球体形状,代理形状(近似场景几何的区域)和影响形状(像素受影响的区域)是分离的,而且加入了很多影响衰减选项(基于法线方向分平面等)。

材质渲染
HD RP有自带的标准着色器,名为受光着色器(Lit Shader)。Lit Shader有不少不错的功能,可以使用比Unity内置渲染中更为丰富的材质。双面选项也可以使用,会自动连接全局照明,加入了很多映射选项,例如单平面和三平面映射。诸如视差遮罩映射或曲面细分等高级功能也已经支持,只需一键便可使用!

012933perifueiqqddeczf.jpg.thumb

不过,加到材质渲染的功能中,最强大的则是其光照模型。

HD RP使用以下BRDF(双向反射分布函数):对镜面反射层使用各向同性多重散射GGX,对漫反射层使用Disney漫反射功能。HD RP与内置Unity在这方面的区别则在于多重散射部分。

金色金属球从平滑(左)到粗糙(右):

012959jlrm7mg8ln70dp0m.png.thumb.jpg
各向同性单散射GGX(类似Unity内置功能)

 

012959hdy42cjh3mctedtm.png.thumb.jpg
HDRP的各向同性多重散射GGX意味着更为粗糙的材质颜色不会更暗,而会更饱和。

默认参数为金属/光滑(Metallic/Smoothness),但也可以在同一着色器中切换为镜面色/光滑(SpecularColor/Smoothness)。

HD RP能增强或替换这个初始模型。它有大量选项可以使用:

用各向异性GGX替换各向同性GGX
增加次表面散射到Disney漫反射中
加入透射效果
加入彩虹效果
加入清漆层GGX

 

013056lafjv91niaa1sai1.png.thumb.jpg

通过调整光照模型能让我们实现多种复杂的外观。

013056fgoss1bezqsf1sv1.jpg.thumb
通过透射和次表面散射实现的蘑菇画面

HD RP也能对透明材质使用一组全新选项。例如:通过先背面再前面渲染来帮助排序,用深度后期通道来对景深效果实现透明或其它功能。

013057kmai23im2ar8i72c.png.thumb.jpg
使用双面透明渲染先背面再前面,渲染实现的彩虹效果示例

基于受光着色器(Lit Shader),HD RP提供了一个分层受光着色器(Layered Lit shader),能够混合多个受光着色器。

012933perifueiqqddeczf.jpg.thumb

HD RP还加入了对贴花的支持。贴花在不透明和透明材质都可以使用,可以正确影响全局光照光照贴图或光照探头的采样。

013239jal1i0u5711o10o6.png.thumb.jpg
使用贴花在地板上绘制的粉笔画示例

调试
HD RP中加入的最重要功能是调试工具。调试功能对理解数据创作和性能问题极其重要。

HD RP带有一个全新的自定义调试窗口,能控制调试视图模式和渲染管线设置。这个调试窗口既可以在Unity编辑器中使用,也可以在任意播放器中使用。它现在可以在PlayStation 4等任意目标设备上拥有所有调试功能。

013313lku9eub1f9cf8gw3.png.thumb.jpg
在Unity编辑器中的调试窗口示例,展示了通用属性

调试窗口允许显示透明材质和不透明材质的任意材质属性,无论它们使用的是延迟渲染路径还是正向渲染路径。

它允许光照调试视图:仅适用漫反射光或仅适用镜面反射光模式。它还能为整个场景修改属性,例如:法线、反射率、光滑度。它也能显示例如动态向量和深度缓冲区的中间渲染目标。它可以根据属性突出对象,例如:突出显示使用光照贴图或曲面细分的对象,还带有NaN检查器等。

012633crs4cwzuqhaq857e.png.thumb.jpg
播放器中的调试窗口示例,带有漫反射光模式,并改写了反射率

它还有一个有意思的模式-颜色选择器模式,用于在应用后期处理功能前读取当前屏幕上的数值或HDR值。调试窗口可以被轻松扩展以支持游戏所需要的任意调试工具,例如:AI或动画调试工具。

新的行为
HD RP具有与 Unity内置的渲染管线完全不同的新行为。

延迟和渲染路径支持的功能是一样的。次表面散射、屏幕空间环境遮罩和贴花的处理功能在二种渲染路径中是一样的。没有必要为使用特定功能选择特定渲染路径。

HD RP使用摄像机相关渲染。这意味着即使远离世界的原点,也可以有不错的渲染精度。这对所有使用HD RP的着色器都有影响。摄像机可以控制所使用的光照架构,可以在同一场景混合使用延迟渲染路径和正向渲染路径,也可以控制为这次渲染使用哪些功能。它还可以禁用烟雾、阴影和后期处理等效果。

013421kh7c7h7i5xpt9htl.png.thumb.jpg

为了调整场景设置,还加入了一个基于体积设置的全新系统,它类似当前后期处理效果中的设置。现在可以对每个体积设定场景设置,例如:天空、阳光级联阴影、屏幕空间阴影接触等。还可以通过插入参数在体积间获得平滑的过渡效果。

013455hy23d2k4234412dk.png.thumb.jpg

对于天空和烟雾还增加了新选项,例如:基于高度的烟雾效果或是用天空颜色着色的雾。烟雾会影响透明材质和不透明材质。

最后,HD RP使用一个专用渲染目标分配系统。它能避免在调整屏幕大小时反复重新分配目标。从而避免了在处理动态分辨率时,产生额外的渲染目标分配。

局限
我们仍在开发HD RP,所以它的一些功能还在制作中。HD RP将在 Unity 2018.1作为预览版发布,目前还不适合用来进行正式的创作。

其中一个重要局限是,HD RP还不支持使用Unity粒子系统制作的Lit Particle,只支持Unlit Particle。此外,内置地形系统还存在一些瑕疵。对于所有SRP,之前在Overlay图层渲染的任何对象,例如:镜头光斑特效,都不支持。Grabpass功能也已经不存在了。

未来的开发计划
我们目前专注于增强稳定性和平台支持。但仍会推出一些炫丽的功能,例如:体积光照。

013604inzk6znrrb21nakj.png.thumb.jpg

区域光将基于Unity Labs团队的研究进行改进。为了得到更为一致的光照和后期处理效果,基于物理的摄像机是下一步要开发的内容。我们还有多个正在制作的角色渲染工具原型。

013628yl8wqsmqlj98ek63.jpg.thumb
《Windup》项目中的小女孩角色渲染

结语
HD RP为Unity带来了全新的渲染管线,能够将当下游戏的视效水准提到尽可能的高。但它也有缺点,那就是其学习曲线,因为HD RP和当前内置的渲染管线有显著的区别。

013653ki5qau2qb2u5n57f.jpg.thumb
使用HD RP和复杂材质制作的风格化游戏环境示例

所有这些功能都有一定的复杂性。统一光照和一致光照本身就很难实现,所以拥有强大的调试工具非常重要。对于摄像机相关渲染的使用则需要更多考量。你也可以为HD RP编写自定义着色器,但这需要更多的额外知识。

你也可以在GitHub上跟踪HD RP的开发进展。如果你有任何问题,欢迎访问SRP在 Github上的频道或者在Unity 官方中文论坛(Unitychina.cn)反馈给我们。

Unity UI性能优化技巧

本文将介绍一些提升Unity UI性能的技巧。更多优化技巧,可以观看下方的视频,内容是Unity工程师Ian Dundore在Unite Europe 2017的演讲《使用Unity性能提升技巧》。
https://v.qq.com/x/page/k0704uoak3j.html

划分画布
问题:UI Canvas上有一个或多个元素变化时,会污染整个画布。
画布(Canvas)是Unity UI的基本组件。它会生成网格来呈现放置在画布上的UI元素,当UI元素变化时,它会重新生成网格并向GPU发起绘图调用,从而显示出UI。

生成这些网格会消耗大量性能。需要将UI元素收集到批处理中,从而尽可能减少绘图调用。因为批处理的生成过程性能消耗较大,通常只在必要时候才重新生成。问题在于,当画布上有一个或多个元素变化时,必须重新分析整块画布,才能得到绘制元素的最优方法。

许多用户将整个游戏的UI都放到一块画布,上面摆放了成百上千个元素。因此当修改其中一个元素时,会产生持续数毫秒的CPU使用量飙升情况。

解决方案:划分画布
每块画布上的元素都与其它画布的元素相隔离,所以我们可以使用工具来切分画布,从而解决Unity UI的批处理问题。

你也可以通过嵌套画布来解决,这样能允许设计师创建大型分层UI,而且不必担心不同内容出现在多个画布上。子画布的内容与父画布和同级画布相互隔离。它们会保持自带几何体,执行自己的批处理。

当使用子画布分离画布时,尝试根据画布更新时间来分组。例如:分离动态元素和静态元素。

Graphic Raycaster的最佳用法
问题:Graphic Raycaster有哪些最佳用法?
Graphic Raycaster组件能够将输入内容转换为UI事件,它会把触屏输入转为事件,然后发送给相关UI元素。每个接收输入内容的画布都需要Graphic Raycaster组件,包括子画布。

尽管该组件名为Graphic Raycaster,但它却不是个光线投射器,默认情况下它只会测试UI图形。该组件会获取特定画布上输入信息相关的UI元素集,然后执行交点测试,它会针对Graphic Raycaster的画布上每个交互式UI元素的RectTransform,检查输入事件发生的位置。

解决方案:关闭静态或非交互式元素的Raycast Target。
例如:有个带文字的按钮,关闭该元素的Raycast Target会直接减少Graphic Raycaster每帧进行的交点测试次数。

111035lb6qqj6aus5qzluz.jpg.thumb

问题:有时候Graphic Raycaster会充当光线投射器使用。
如果将画布上的渲染模式设为世界空间摄像机(Worldspace Camera)或屏幕空间摄像机(Screen Space Camera),此时可以设置阻挡遮罩(Blocking Mask)。

阻挡遮罩决定光线投射器是通过2D物理还是3D物理投射光线,从而了解特定物理对象是否阻挡用户与UI交互。

解决方案:通过2D或3D物理投射光线会消耗不少性能,所以要谨慎使用该功能。
尽量减少Graphic Raycaster的数量,不要将Graphic Raycaster添加到非交互式UI画布上,因为这样做无法检查交互事件。

避免使用Camera.main
问题:世界空间画布需要了解交互事件来自哪个摄像机。
当设置画布进行渲染时,不管该画布是在世界空间还是摄像机的屏幕空间,都可以指定用于为UI中Graphic Raycaster生成交互事件的摄像机。渲染模式为“Screen Space – Camera”的画布需要使用该设置,该设置名为“Render Camera”。

111035x5odnios6scin66x.jpg.thumb

然而在渲染模式为“World Space”的画布上,该设置是可选的,名为“Event Camera”。

111035qjqqcxcjglclll40.jpg.thumb

如果将世界空间画布的Event Camera字段留空,这不意味着该画布不会接收事件。它会使用游戏的主摄像机。为了确定哪个摄像机是主摄像机,该画布会访问Camera.main属性。

111035b152ax15dxmwj6xx.jpg.thumb

根据Unity所使用的代码路径,每帧中每有一个Graphic Raycaster和世界空间画布,该画布会访问7到10次Camera.main。每次访问Camera.main都会调用Object.FindObjectWithTag。这个做法在运行时并不合适。

解决方案:避免使用Camera.main
缓存摄像机的引用,然后创建系统来跟踪主摄像机。如果使用世界空间画布,要指定Event Camera,不要将该属性留空。如果需要修改Event Camera,编写代码来更新Event Camera属性。

避免使用布局分组
问题:每个影响布局的UI元素都会至少执行一次GetComponents调用。
当修改布局系统的一个或多个子元素时,会使布局变脏。修改后的子元素会使拥有该元素的布局系统(Layout System)无效化。

简单介绍一下布局系统:布局系统是一组连续的布局分组(Layout Group),它们在布局元素(Layout Element)之上。布局元素不只是名为Layout Element的组件,它们还包括UI图像、文字和Scroll Rect组件,而且Scroll Rect同时也是布局分组。

回到问题本身,每个使布局变脏的UI元素都会至少执行一次GetComponents调用,该调用会在布局元素父对象上寻找有效的布局分组。找到有效布局分组后,它会继续遍历Transform层级,直到停止寻找分组或是到达层级的根部分,无论先满足哪个条件都会停止寻找过程。因此。每个布局分组会给每个子布局元素的改变过程添加一次GetComponents调用,使嵌套布局分组的性能变差。

解决方案:避免使用布局分组。
使用锚点进行比例布局。在拥有动态元素数量的活跃UI上,考虑编写代码来计算布局,仅在需要时运行该代码,而不是每次发生改变的时候。

巧妙地聚集UI对象
问题:用错误的方法聚集UI对象。
通常情况下,用户通过重置父对象来聚集UI对象,然后再禁用对象,但这样会造成不必要的污染。

解决方案:首先禁用对象,然后将其父对象重置为对象池。
这样操作仅会改变一次原有的层级,但在重置父对象时,要避免二次改变原有的父对象,也不要改变新的层级。如果要从对象池移除对象,首先重置它的父对象,然后更新数据,再启用该对象。

如何隐藏画布
问题:如何隐藏画布?
有时需要隐藏UI元素和画布,要怎样高效完成该任务呢?

解决方案:禁用Canvas组件。
禁用Canvas组件会阻止画布向GPU发起绘图调用,所以该画布不再可见。然而,此时该画布不会丢弃它的顶点缓冲区,它会保留所有网格和顶点,当重新启用时不会触发重构过程,它只会重新绘制画布内容。

此外,禁用Canvas组件不会触发Canvas层级上性能消耗较大的OnDisable/OnEnable回调。禁用子组件时要小心,注意它是否运行性能消耗较大的每帧代码。

UI元素上Animator的最佳用法
问题:如何在UI上使用Animator?
Animator每帧都会改变元素,即使动画中的数值没有变化。Animator没有空指令检查。

解决方案:
只在频繁变化的动态元素上加入Animator。对于很少变化的元素,或是仅响应事件时才变化的元素,请自行编写代码或补间系统,你可以在Asset Store资源商店找到许多补间系统插件。