Unity UGUI Canvas.WillRenderCanvases 具体引起了网格重建的UI元素

UGUI 中的 SendWillRenderCanvases 是很多情况下需要衡量UI 性能的重要函数,此函数要尽量少的耗时,UWA 推荐值在5ms。
在平时开发,或者优化UI性能的时候,如果我们知道具体哪个UI元素引起的此函数调用,那么就反查逻辑代码,来减少或者去除耗时函数的触发。
那我们可以在编辑器模式下,添加查找代码来定位。
以下代码转自转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
==================华丽分割线==================

using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.UI;
 
public class NewBehaviourScript : MonoBehaviour {
 
    IList m_LayoutRebuildQueue;
    IList m_GraphicRebuildQueue;
 
    private void Awake()
    {
        System.Type type = typeof(CanvasUpdateRegistry);
        FieldInfo field = type.GetField("m_LayoutRebuildQueue", BindingFlags.NonPublic | BindingFlags.Instance);
        m_LayoutRebuildQueue = (IList)field.GetValue(CanvasUpdateRegistry.instance);
        field = type.GetField("m_GraphicRebuildQueue", BindingFlags.NonPublic | BindingFlags.Instance);
        m_GraphicRebuildQueue = (IList)field.GetValue(CanvasUpdateRegistry.instance);
    }
 
    private void Update()
    {
        for (int j = 0; j < m_LayoutRebuildQueue.Count; j++)
        {
            var rebuild = m_LayoutRebuildQueue[j];
            if (ObjectValidForUpdate(rebuild))
            {
                Debug.LogFormat("{0}引起{1}网格重建", rebuild.transform.name, rebuild.transform.GetComponent().canvas.name);
            }
        }
 
        for (int j = 0; j < m_GraphicRebuildQueue.Count; j++)
        {
            var element = m_GraphicRebuildQueue[j];
            if (ObjectValidForUpdate(element))
            {
                Debug.LogFormat("{0}引起{1}网格重建", element.transform.name, element.transform.GetComponent().canvas.name);
            }
        }
    }
    private bool ObjectValidForUpdate(ICanvasElement element)
    {
        var valid = element != null;
 
        var isUnityObject = element is Object;
        if (isUnityObject)
            valid = (element as Object) != null; //Here we make use of the overloaded UnityEngine.Object == null, that checks if the native object is alive.
 
        return valid;
    }
}

==================华丽分割线==================
以上代码添加到不会被销毁的物体上,就可以在控制台查看哪些元素引起了重建。
但是此代码只是输出了元素的名字,我们还是在手动去查找元素。因为我修改了log的日志输出,这样,可以点击log,直接在Hierarchy面板中选中引起重建的元素,更快速的定位问题。

// 只修改log的日志输出格式即可
Debug.Log(string.Format("{0}引起{1}网格重建", rebuild.transform.name, rebuild.transform.GetComponent().canvas.name),rebuild.transform);

Debug.Log(string.Format("{0}引起{1}网格重建", element.transform.name, element.transform.GetComponent().canvas.name), element.transform);

你可能感兴趣的:(Unity UGUI Canvas.WillRenderCanvases 具体引起了网格重建的UI元素)