UGUI 显隐效率问题

    科技2025-01-29  35

    好早以前就在网上看到过对于UI的显示和隐藏最好使用CanvasGroup组件来控制会比较好,一直没有做过测试,这次来补下坑,顺便学了点性能分析Profiler工具。

    首先创建一个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次结果如图:


    与消除panel.gameObject进行对比 无多大区别

    public class GameTest : 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++) { panelGo.SetActive(true); panelGo.SetActive(false); } } }

    将num设为1000次结果如图

    SetActive和CanvasGroup调节alpha这两种方法在对单个Panel物体时每帧重复调用性能差距10倍左右


    在panel面板下再挂载一个text文本进行测试

    num为100次结果如图:

    SetActive方法中主要是Text.OnEnable()性能消耗大,它会对初始化文本网格的信息(每个文字所在的网格顶点,UV,顶点色等等属性),而这些信息都是储存在数组中(即堆内存中),文本越多,堆内存开销越大,相应GC就产生了

    而实际搭建UI场景中肯定不止一个Text那么简单,所以使用SetAcive(true/false)方法是耗时的并产生GC的

    Processed: 0.014, SQL: 8