UGUI Panel的显示和隐藏优化

news2024/9/22 1:57:23

unity UI如何开启(显示)或者关闭(隐藏)Panel界面,相信大家都是知道的,但是如何做最好呢?

可能大家一般开启/关闭界面的方法就是直接SetActive吧。这样做通常是可以的,简答快速地解决需求,但是它又两个问题:
第一,Disable掉的物体上面的脚本也不运行了,而很多时候我们需要那个脚本运行。这样就不能用挂在自己身上脚本把自己SetActive(true)或者SetActive(false)。如果把自己的引用给另外一个脚本来对自己SetActive(true)或者SetActive(false),又会造成多余的耦合,并不符合OOP设计理念。
第二,Disable掉的物体,重新SetActive(true),会造成较大的性能消耗,如果此界面draw call较多,会有明显的延迟。

不用SetActive(true)/(false)之后,我们还有什么其他方法解决问题吗?

以下是大家可能想到的其他方法,它们也各有各的问题:

方法:Scale改为0,0,0,再改为1,1,1;
问题:改回后draw call加倍;大量垃圾回收;

方法:将界面移除Canvas这个父物体;
问题:改回后draw call加倍;大量垃圾回收;而且新增父物体增加额外引用耦合;

方法:放在Camera的某个culling层上;
问题:改回后draw call加倍;大量垃圾回收;只对screen space-camera有效;

方法:Canvas.enable = false;
问题:改回后延迟严重;而且不方便使用;

这些都不好,那你说,什么方法可行呢?

这个解决方法就是给Panel加一个CanvasGroup,上面提到的问题,在它身上都不会发生;

若要显示:

GetComponent<CanvasGroup>().alpha = 1;
GetComponent<CanvasGroup>().interactable = true;
GetComponent<CanvasGroup>().blocksRaycasts = true;

若要隐藏:

GetComponent<CanvasGroup>().alpha = 0;
GetComponent<CanvasGroup>().interactable = false;
GetComponent<CanvasGroup>().blocksRaycasts = false;

使用Profiler工具分析CanvasGroup组件

首先创建一个BasePanel脚本,通过CanvasGroup组件来实现UI面板的显示(OnEnter)和隐藏(OnExit)。这里的BasePanel相当于是UIPanel的基类了,这里我只是抽出了一部分,等以后有空了把简易的UI管理类也一起讲了。

[RequireComponent(typeof(CanvasGroup))]
public class BasePanel : MonoBehaviour
{
    private CanvasGroup m_CanvasGroup;
 
    private void Awake()
    {
        m_CanvasGroup = GetComponent<CanvasGroup>();
    }
 
    public void OnEnter()
    {
        m_CanvasGroup.alpha = 1;
        m_CanvasGroup.blocksRaycasts = true;
    }
 
    public void OnExit()
    {
        m_CanvasGroup.alpha = 0;
        m_CanvasGroup.blocksRaycasts = false;
    }
}


然后就创建一个测试脚本,用于比较CanvasGroup组件和使用SetAcive(true/false)的性能消耗。这边要引入命名空间UnityEngine.Profiling才可以使用性能检测,在需要性能测试的函数前后添加Profiler.BeginSample("展示的名字")和Profiler.EndSample()即可。这里为了明显展现性能消耗,开放了一个num变量来控制我们循环次数。

public class Main : MonoBehaviour
{
    public BasePanel panel;
    public int num;
    //public GameObject panelGo;
 
    private void Awake()
    {
        //panel = panelGo.GetComponent<BasePanel>();
    }
 
    private void Update()
    {
        Profiler.BeginSample("CanvasGroup");
        CanvasGroupFun();
        Profiler.EndSample();
 
        Profiler.BeginSample("SetActive");
        ActiveFun();
        Profiler.EndSample();
    }
 
    void CanvasGroupFun()
    {
        for (int i = 0; i < num; i++)
        {
            panel.OnEnter();
            panel.OnExit();
        }
    }
 
    void ActiveFun()
    {
        for (int i = 0; i < num; i++)
        {
            panel.gameObject.SetActive(true);
            panel.gameObject.SetActive(false);
        }
 
    }
}


将num设为100次结果如图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1335622.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多播ip地址配置和通信理解

经常有朋友问&#xff0c;为什么相同局域网的ip需要相同网段&#xff0c;为什么组播的网段可以不同&#xff1f; 比如&#xff1a; 在您的局域网&#xff08;192.168.1.0/24 网段&#xff09;中设置多播组时&#xff0c;您可以选择一个在本地网络范围内尚未使用的多播组地址。…

【Java中序列化的原理是什么(解析)】

&#x1f341;序列化的原理是什么&#xff1f; &#x1f341;典型-----解析&#x1f341;拓展知识仓&#x1f341;Serializable 和 Externalizable 接门有何不同? &#x1f341;如果序列化后的文件或者原始类被篡改&#xff0c;还能被反序列化吗?&#x1f341;serialVersionU…

电路设计(7)——窗口比较器的multism仿真

1.功能设计 构建一个窗口比较器的电路&#xff0c;在输入电压大于3.5v&#xff0c;小于0.8v时&#xff0c;蜂鸣器报警&#xff0c;输入电压在0.8v到3.5v之间时&#xff0c;不报警。 整体电路如下&#xff1a; 2.设计思路 在输入端&#xff0c;采取电阻分压的方式&#xff0c;输…

2024年最新Python爬虫入门『最强教程』新鲜出炉!

近年来&#xff0c;大数据成为业界与学术界最火热的话题之一&#xff0c;数据已经成为每个公司极为重要的资产。互联网大量的公开数据为个人和公司提供了以往想象不到的可以获取的数据量。而掌握网络爬虫技术可以帮助你获取这些有用的公开数据集。 爬虫能干什么呢&#xff1f;一…

11-GraalVM元原生时代的Java虚拟机

文章目录 GraalVM诞生的背景Java在微服务/云原生时代的困境事实矛盾 问题根源Java离不开虚拟机 解决方案革命派保守派 GraalVM入门GraalVM特征GraalVM下载和安装GraalVM下载win10安装及配置linux安装及配置 GraalVM初体验(Linux)多语言开发(了解即可、官网有Demo)GraalCompiler…

无人叉车驻车定位RFID传感器CNS-RFID-01|1S的CAN总线通信连接方法

无人叉车驻车定位RFID传感器CNS-RFID-01|1S支持CAN总线通信方式&#xff0c;广泛应用于智能仓库&#xff0c;AGV |RGV小车&#xff0c;无人叉车&#xff0c;搬运机器人定位&#xff0c;驻车等领域&#xff0c;本篇幅主要介绍器CNS-RFID-01|1S RFID传感器的CAN总线通信连接方法。…

“双十一、二” 业务高峰如何扛住?韵达快递选择 TDengine

小 T 导读&#xff1a; 为了有效处理每日亿级的数据量&#xff0c;早在 2021 年&#xff0c;韵达就选择用 TDengine 替代了 MySQL&#xff0c;并在三台服务器上成功部署和上线了 TDengine 2.0 集群。如今&#xff0c;随着 TDengine 3.0 版本的逐渐成熟&#xff0c;韵达决定将现…

NAT协议的实现方式

在网络通信中&#xff0c;NAT协议&#xff08;Network Address Translation&#xff0c;网络地址转换&#xff09;扮演着关键角色&#xff0c;允许内部网络与外部网络之间进行有效的通信。 实现内外网之间网络地址转换的过程中&#xff0c;NAT采用了不同的实现方式&#xff0c;…

案例分析:三一重工集团数字化转型

三一重工集团&#xff0c;作为制造业中的数字化转型佼佼者&#xff0c;荣获“全球灯塔工厂”的殊荣&#xff0c;率先采用了物联网、云计算、大数据等尖端技术手段。数字化转型让三一重工步入了全面信息化的管理时代&#xff0c;通过ERP、CRM、HRM等系统的协同运作&#xff0c;实…

高度可定制的JS电子表格组件DHTMLX Spreadsheet v5.1——拥有全新内置主题

DHTMLX Spreadsheet是用纯JavaScript编写的开源电子表格小部件&#xff0c;可让您快速在网页上添加类似于Excel的可编辑数据表。高度可定制的JavaScript电子表格组件&#xff0c;具有优雅的Material样式&#xff0c;可安全、方便地编辑和格式化数据。 近日DHTMLX Spreadsheet …

HashMap扩展问题:HashMap如何实现线程安全?

HashMap如何实现线程安全&#xff1f; 方法一&#xff1a;java.util.Collections.synchronizedMap(Map<K,V> m) 底层实际上是将hashMap又封装了一层&#xff0c;变成SynchronizedMap<K,V>&#xff0c;并在每一个对HashMap的操作方法上添加了synchronized修饰。代…

基于 Webpack 插件体系的 Mock 服务

背景 在软件研发流程中&#xff0c;对于前后端分离的架构体系而言&#xff0c;为了能够更快速、高效的实现功能的开发&#xff0c;研发团队通常来说会在产品原型阶段对前后端联调的数据接口进行结构设计及约定&#xff0c;进而可以分别同步进行对应功能的实现&#xff0c;提升研…

WooCommerce Cost of Goods电商商城商品成本插件 轻松跟踪利润

WooCommerce Cost of Goods电商商城商品成本插件 轻松跟踪利润 WooCommerce Cost of Goods电商商城商品成本插件通过将货物成本纳入订单和报告中&#xff0c;轻松跟踪利润。 WooCommerce Cost of Goods电商商城商品成本插件功能 WooCommerce Cost of Goods电商商城商品成本插…

设计模式--工厂方法模式

实验3&#xff1a;工厂方法模式 本次实验属于模仿型实验&#xff0c;通过本次实验学生将掌握以下内容&#xff1a; 1、理解工厂方法模式的动机&#xff0c;掌握该模式的结构&#xff1b; 2、能够利用工厂方法模式解决实际问题。 [实验任务]&#xff1a;加密算法 目前常用…

IntelliJ IDEA插件

插件安装目录&#xff1a;C:\Users\<username>\AppData\Roaming\JetBrains\IntelliJIdea2021.2\plugins aiXcoder Code Completer&#xff1a;代码补全 Bookmark-X&#xff1a;书签分类 使用方法&#xff1a;鼠标移动到某一行&#xff0c;按ALT SHIFT D

静态HTTP:构建高效、可扩展的Web应用程序的基础

静态HTTP是Web应用程序的重要组成部分&#xff0c;它为构建高效、可扩展的Web应用程序提供了坚实的基础。下面将详细介绍静态HTTP的优势和在Web应用程序中的作用。 一、静态HTTP的优势 高效性能&#xff1a;静态HTTP内容在服务器上预先生成&#xff0c;然后通过HTTP协议传输到…

STM32MP157D-DK1开发板Qt镜像构建

上篇介绍了STM32MP57-DK1开发板官方系统的烧录。那个系统包含Linux系统的基础功能&#xff0c;如果要进行Qt开发&#xff0c;还需要重新构建带有Qt功能的镜像 本篇就来介绍如何构建带有Qt功能的系统镜像&#xff0c;并在开发板中烧录构建的镜像。 1 Distribution包的构建 ST…

Unity 如何获取当前日期的中文星期几

要获取当前日期是星期几可以使用DateTime下的DayOfWeek方法。 首先我们在脚本中添加System引用&#xff1a; using System; 然后我们再调用DateTime下的DayOfWeek方法&#xff1a; DayOfWeek dayOfWeek DateTime.Now.DayOfWeek; //获取当前是星期几 由于返回的是英文&…

simulink代码生成(三)——自定义变量名称

在simulink代码生成的学习过程中&#xff0c;遇到了一个卡壳的问题&#xff1a;如何在生成的代码中定义一个可控变量&#xff1f; 给大家看一下原m代码与生成的C代码对比结果&#xff1a; 原来的m函数代码&#xff1a;结构清晰&#xff0c;变量名与物理意义对应 生成的代码&a…

详解Java反射机制reflect(一学就会,通俗易懂)

1.定义 #2. 获取Class对象的三种方式 sout(c1)结果为class com.itheima.d2_reflect.TestClass 获取到了Class对象就相当于获取到了该类 2.获取类的构造器 3.获取全部构造器对象 2.根据参数类型获取构造器对象 类型后必须加.class 3.构造器对象调用构造器方法 4.暴力访问 4.获…