好早以前就在网上看到过对于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的