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

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

http://forum.china.unity3d.com/thread-32932-1-1.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每帧进行的交点测试次数。

 

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

然而在渲染模式为“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模式。

转载于:https://www.cnblogs.com/TravelingLight/p/9724156.html

相关文章:

  • pygame中多个class类之间的关系
  • Luogu 1341 无序字母对 - 欧拉路径
  • Hadoop HDFS 文件系统的存储哲学
  • 牛客国庆集训派对Day1-New Game!(几何+最短路)
  • 寻找最长回文字符串
  • JavaScript 中 this的指向
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • Java 里如何实现线程间通信
  • Django框架-AJAX
  • P1044 栈 洛谷(数论)(卡特兰数)
  • 矩阵运算
  • MySQL之架构与历史(一)
  • 函数指针
  • Django admin源码剖析
  • 第53节:Java当中的IO流(上)
  • 345-反转字符串中的元音字母
  • Angular Elements 及其运作原理
  • Codepen 每日精选(2018-3-25)
  • HomeBrew常规使用教程
  • Java新版本的开发已正式进入轨道,版本号18.3
  • JS+CSS实现数字滚动
  • JS实现简单的MVC模式开发小游戏
  • miaov-React 最佳入门
  • Spring Boot快速入门(一):Hello Spring Boot
  • SwizzleMethod 黑魔法
  • Vue 2.3、2.4 知识点小结
  • vue--为什么data属性必须是一个函数
  • 记一次和乔布斯合作最难忘的经历
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 微信小程序实战练习(仿五洲到家微信版)
  • 项目实战-Api的解决方案
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​学习一下,什么是预包装食品?​
  • (1)STL算法之遍历容器
  • (11)MATLAB PCA+SVM 人脸识别
  • (42)STM32——LCD显示屏实验笔记
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (阿里云万网)-域名注册购买实名流程
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (二)windows配置JDK环境
  • (分布式缓存)Redis分片集群
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • *p++,*(p++),*++p,(*p)++区别?
  • ../depcomp: line 571: exec: g++: not found
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET 药厂业务系统 CPU爆高分析
  • .net(C#)中String.Format如何使用
  • .NET中 MVC 工厂模式浅析
  • .net中我喜欢的两种验证码