Graphic是用來顯示圖像的一個抽象類,是MaskableGraphic的父類,而MaskableGraphic是Image、RawImage、Text的父類。
Graphic繼承於UIBehaviour和ICanvasElement。
UIBehaviour是所有UI的父類,聲明了Unity生命周期的函數,除IsDestroyed函數外都是虛函數。
ICanvasElement提供了Canvas對其管理的元素的更新事件的接口。
繼承於UIBehaviour的函數:
OnRectTransformDimensionsChange(RectTransform改變時):把Vertices和layout設為dirty。
OnBeforeTransformParentChanged(父節點改變前):把Canvas和Graphic的連接關系從GraphicRegistry中移除,並且讓LayoutRebuilder重建布局。
OnTransformParentChanged(父節點改變時):調用CacheCanvas函數,獲取父節點的Canvas組件,在GraphicRegistry中注冊Canvas和Graphic的連接關系,然后調用SetAllDirty函數。
OnEnable:調用CacheCanvas函數,獲取父節點的Canvas組件,在GraphicRegistry中注冊Canvas和Graphic的連接關系,把s_WhiteTexture(MainTexture)設置為默認的白色紋理,然后調用SetAllDirty函數。
OnDisable:在GraphicRegistry和CanvasUpdateRegistry分別移除注冊,canvasRenderer清理了,然后讓LayoutRebuilder重建布局,
OnCanvasHierarchyChanged(父節點的Canvas改變時):重新在GraphicRegistry中注冊新改變的Canvas。
OnDidApplyAnimationProperties(應用動畫屬性時):調用SetAllDirty函數。
講講SetAllDirty
public virtual void SetAllDirty() { SetLayoutDirty(); SetVerticesDirty(); SetMaterialDirty(); } /// <summary>
/// Mark the layout as dirty and needing rebuilt. /// </summary>
/// <remarks>
/// Send a OnDirtyLayoutCallback notification if any elements are registered. See RegisterDirtyLayoutCallback /// </remarks>
public virtual void SetLayoutDirty() { if (!IsActive()) return; LayoutRebuilder.MarkLayoutForRebuild(rectTransform); if (m_OnDirtyLayoutCallback != null) m_OnDirtyLayoutCallback(); } /// <summary>
/// Mark the vertices as dirty and needing rebuilt. /// </summary>
/// <remarks>
/// Send a OnDirtyVertsCallback notification if any elements are registered. See RegisterDirtyVerticesCallback /// </remarks>
public virtual void SetVerticesDirty() { if (!IsActive()) return; m_VertsDirty = true; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); if (m_OnDirtyVertsCallback != null) m_OnDirtyVertsCallback(); } /// <summary>
/// Mark the material as dirty and needing rebuilt. /// </summary>
/// <remarks>
/// Send a OnDirtyMaterialCallback notification if any elements are registered. See RegisterDirtyMaterialCallback /// </remarks>
public virtual void SetMaterialDirty() { if (!IsActive()) return; m_MaterialDirty = true; CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild(this); if (m_OnDirtyMaterialCallback != null) m_OnDirtyMaterialCallback(); }
SetLayoutDirty中LayoutRebuilder重建布局,SetVerticesDirty和SetMaterialDirty里注冊CanvasUpdateRegistry,將組件加到m_GraphicRebuildQueue中,等待Canvas重建時重建Graphic。並且三個函數都會通知執行對應的回調事件。可以通過RegisterDirtyLayoutCallback來增加回調。
繼承於ICanvasElement的函數:
Rebuild(在預渲染循環時重建幾何圖形和它的材質):沒有被剔除的話,更新頂點(幾何結構)和材質,即調用UpdateGeometry和UpdateMaterial。
UpdateGeometry
protected virtual void UpdateGeometry() { if (useLegacyMeshGeneration) DoLegacyMeshGeneration(); else DoMeshGeneration(); }
DoLegacyMeshGeneration和DoMeshGeneration都是生成網格的函數,邏輯相似。DoLegacyMeshGeneration直接改動workerMesh,DoMeshGeneration使用VertexHelper來完成部分邏輯。
這里以DoMeshGeneration為例
private void DoMeshGeneration() { if (rectTransform != null && rectTransform.rect.width >= 0 && rectTransform.rect.height >= 0) OnPopulateMesh(s_VertexHelper); else s_VertexHelper.Clear(); // clear the vertex helper so invalid graphics dont draw.
var components = ListPool<Component>.Get(); GetComponents(typeof(IMeshModifier), components); for (var i = 0; i < components.Count; i++) ((IMeshModifier)components[i]).ModifyMesh(s_VertexHelper); ListPool<Component>.Release(components); s_VertexHelper.FillMesh(workerMesh); canvasRenderer.SetMesh(workerMesh); }
OnPopulateMesh:建立4個頂點,構築兩個三角形(形成一個矩形),保存到VertexHelper里。
ModifyMesh:IMeshModifier類型的組件調用ModifyMesh,修改網格信息。
FillMesh:s_VertexHelper里修改后的信息賦值給workerMesh。
SetMesh:將網格信息提交給canvasRenderer。
UpdateMaterial
protected virtual void UpdateMaterial() { if (!IsActive()) return; canvasRenderer.materialCount = 1; canvasRenderer.SetMaterial(materialForRendering, 0); canvasRenderer.SetTexture(mainTexture); }
設置材質和紋理。
以上就是Graphic實現顯示圖像的核心代碼,此外還有個比較重要的函數CrossFadeColor,它會使用TweenRunner和ColorTween以協程的方式來改變顏色。