UI优化策略-UI性能优化技巧

http://forum.china.unity3d.com/thread-32932-1-1.htmlhtml

 

划分画布缓存

问题: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每帧进行的交点测试次数。性能

 

问题:有时候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”。spa

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

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

根据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元素上Animator的最佳用法

问题:如何在UI上使用Animator?
Animator每帧都会改变元素,即便动画中的数值没有变化。Animator没有空指令检查。
解决方案
只在频繁变化的动态元素上加入Animator。对于不多变化的元素,或是仅响应事件时才变化的元素,请自行编写代码或补间系统,你能够在Asset Store资源商店找到许多补间系统插件。

 

抗锯齿

问题:UI抗锯齿不起效
Canvas的Render Mode设置为Screen Space - Overlay的时候,UI的渲染不会通过MASS buffer,而是直接写入到Final buffer。
解决方案
使用Screen Space - Camera模式。

相关文章
相关标签/搜索