// 布局重建序列和图像重建序列 // 当需要更新布局或图像时,可以调用RegisterCanvasElementForLayoutRebuild和 // RegisterCanvasElementForGraphicRebuild两个方法将对象添加到对应的重建序列中 // PerformUpdate方法会调用Rebuild方法对这两个序列中中的对象进行更新操作 privatereadonly IndexedSet<ICanvasElement> m_LayoutRebuildQueue = new IndexedSet<ICanvasElement>(); privatereadonly IndexedSet<ICanvasElement> m_GraphicRebuildQueue = new IndexedSet<ICanvasElement>();
// 检查指定的Canvas元素是否是Unity的Object,是否可以进行有效更新 // Object是Unity所有对象的基类,object是C#中所有对象的基类 privateboolObjectValidForUpdate(ICanvasElement element) { var valid = element != null;
var isUnityObject = element is Object; if (isUnityObject) valid = (element as Object) != null;
return valid; }
// 清理两个队列中的无效元素 // MonoBehaviour对空值相等性重载了==操作符,用于检查他们是否被销毁 // 这段代码中处理的是一个ICanvasElement接口类型的列表,而不是具体的MonoBehaviour类型 // 因此直接使用==操作符不能直接转发到MonoBehaviour,而只是检查接口本身是否为null // IsDestroyed()方法用于检查元素的后端是否被销毁 privatevoidCleanInvalidItems() { var layoutRebuildQueueCount = m_LayoutRebuildQueue.Count; for (int i = layoutRebuildQueueCount - 1; i >= 0; --i) { var item = m_LayoutRebuildQueue[i]; // 元素是否为空 if (item == null) { m_LayoutRebuildQueue.RemoveAt(i); continue; }
// 元素是否被销毁 if (item.IsDestroyed()) { m_LayoutRebuildQueue.RemoveAt(i); item.LayoutComplete(); } }
var graphicRebuildQueueCount = m_GraphicRebuildQueue.Count; for (int i = graphicRebuildQueueCount - 1; i >= 0; --i) { var item = m_GraphicRebuildQueue[i]; if (item == null) { m_GraphicRebuildQueue.RemoveAt(i); continue; }
if (item.IsDestroyed()) { m_GraphicRebuildQueue.RemoveAt(i); item.GraphicUpdateComplete(); } } }
// 计算指定Transform对象的父级层级数目 privatestaticintParentCount(Transform child) { if (child == null) return0;
var parent = child.parent; int count = 0; while (parent != null) { count++; parent = parent.parent; } return count; }
// 将一个Canvas元素注册到图像重建队列中,一个带返回值一个不带返回值方法 publicstaticvoidRegisterCanvasElementForGraphicRebuild(ICanvasElement element) { instance.InternalRegisterCanvasElementForGraphicRebuild(element); } publicstaticboolTryRegisterCanvasElementForGraphicRebuild(ICanvasElement element) { return instance.InternalRegisterCanvasElementForGraphicRebuild(element); } privateboolInternalRegisterCanvasElementForGraphicRebuild(ICanvasElement element) { // 是否正在进行图像重建更新操作,是的话将不会将元素添加到图像重建队列中 if (m_PerformingGraphicUpdate) { Debug.LogError(string.Format("Trying to add {0} for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.", element)); returnfalse; } // 向图像重建队列中添加元素,确保不会重复添加 return m_GraphicRebuildQueue.AddUnique(element); }
// 从布局和重建的队列中移除指定的Canvas元素 publicstaticvoidUnRegisterCanvasElementForRebuild(ICanvasElement element) { instance.InternalUnRegisterCanvasElementForLayoutRebuild(element); instance.InternalUnRegisterCanvasElementForGraphicRebuild(element); } privatevoidInternalUnRegisterCanvasElementForLayoutRebuild(ICanvasElement element) { // 如果正在进行布局重建更新操作,将不会移除指定元素 if (m_PerformingLayoutUpdate) { Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); return; } // 调用元素的布局重建完成函数 element.LayoutComplete(); // 从布局重建队列中移除元素 instance.m_LayoutRebuildQueue.Remove(element); } privatevoidInternalUnRegisterCanvasElementForGraphicRebuild(ICanvasElement element) { // 如果正在进行图像重建更新操作,将不会移除指定元素 if (m_PerformingGraphicUpdate) { Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); return; } // 调用元素的图像重建完成函数 element.GraphicUpdateComplete(); // 从图像重建队列中移除元素 instance.m_GraphicRebuildQueue.Remove(element); }
// 从布局和重建的队列中禁用指定的Canvas元素 publicstaticvoidDisableCanvasElementForRebuild(ICanvasElement element) { instance.InternalDisableCanvasElementForLayoutRebuild(element); instance.InternalDisableCanvasElementForGraphicRebuild(element); } privatevoidInternalDisableCanvasElementForLayoutRebuild(ICanvasElement element) { // 如果正在进行布局重建更新操作,将不会禁用指定元素 if (m_PerformingLayoutUpdate) { Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); return; } // 调用元素的布局重建完成函数 element.LayoutComplete(); // 禁用指定元素 instance.m_LayoutRebuildQueue.DisableItem(element); } privatevoidInternalDisableCanvasElementForGraphicRebuild(ICanvasElement element) { // 如果正在进行图像重建更新操作,将不会禁用指定元素 if (m_PerformingGraphicUpdate) { Debug.LogError(string.Format("Trying to remove {0} from rebuild list while we are already inside a rebuild loop. This is not supported.", element)); return; } // 调用元素的图像重建完成函数 element.GraphicUpdateComplete(); // 禁用指定元素 instance.m_GraphicRebuildQueue.DisableItem(element); }
for (int i = 0; i <= (int)CanvasUpdate.PostLayout; i++) { // 标记每一个元素的性能分析 UnityEngine.Profiling.Profiler.BeginSample(m_CanvasUpdateProfilerStrings[i]);
// now layout is complete do culling... UnityEngine.Profiling.Profiler.BeginSample(m_CullingUpdateProfilerString); // 执行实际的裁剪操作 ClipperRegistry.instance.Cull(); UnityEngine.Profiling.Profiler.EndSample();
// 标记正在进行图像更新操作 m_PerformingGraphicUpdate = true;
for (var i = (int)CanvasUpdate.PreRender; i < (int)CanvasUpdate.MaxUpdateValue; i++) { UnityEngine.Profiling.Profiler.BeginSample(m_CanvasUpdateProfilerStrings[i]); for (var k = 0; k < m_GraphicRebuildQueue.Count; k++) { try { var element = m_GraphicRebuildQueue[k]; // 判断元素是否是有效元素 // 对布局重建序列中的每一个元素进行CanvasUpdate的每个阶段更新 if (ObjectValidForUpdate(element)) element.Rebuild((CanvasUpdate)i); } catch (Exception e) { Debug.LogException(e, m_GraphicRebuildQueue[k].transform); } } UnityEngine.Profiling.Profiler.EndSample(); }
for (int i = 0; i < m_GraphicRebuildQueue.Count; ++i) // 调用图像重建完成函数 m_GraphicRebuildQueue[i].GraphicUpdateComplete(); // 清空图像重建序列 并修改图像重建标志为false m_GraphicRebuildQueue.Clear(); m_PerformingGraphicUpdate = false; UISystemProfilerApi.EndSample(UISystemProfilerApi.SampleType.Render); }