Runtime类图
Graphic
Grahic是UGUI的核心组件,负责显示图像,继承了UIBehaviour,ICanvasElement。它是一个抽象类,是MaskableGraphic(可遮罩图像)的基类,而后者是RawImage,Image和Text的基类。
继承自UIBehaviour的方法:
OnEnable方法
调用了CacheCanvas方法,从父节点中获取Canvas列表,取得第一个激活并且可用的Canvas赋值给m_Canvas,把m_Canvas注册到GraphicRegistry中(一个注册处,可以从m_Graphics获取指定Canvas所包含的Graphic,如果m_Graphics不包含,则把当前Graphic和Canvas注册添加到m_Graphics中),接着设置s_WhiteTexture(对应属性MainTexture,用来绘制图形的纹理),最后SetAllDirty(分别设置Layout布局、Vertices顶点和Material材质为Dirty)。
OnDisable方法
从GraphicRegistry和CanvasUpdateRegistry解除注册,并清空canvasRenderer,通知LayoutRebuilder重建Layout。
OnRectTransformDimensionsChange方法(当RectTransform尺寸发生变化时),如果在重建中,只设置SetVerticesDirty,否则调用SetVerticesDirty和SetLayoutDirty。
OnBeforeTransformParentChanged方法,从GraphicRegistry解除注册,并通知LayoutRebuilder重建Layout。
OnTransformParentChanged方法,设置m_Canvas为空,调用CacheCanvas方法。从父节点中获取Canvas列表,取得第一个激活并且可用的Canvas赋值给m_Canvas,把m_Canvas注册到GraphicRegistry中,最后SetAllDirty(分别设置Layout布局、Vertices顶点和Material材质为Dirty)。
OnDidApplyAnimationProperties方法,调用SetAllDirty(分别设置Layout布局、Vertices顶点和Material材质为Dirty)。
OnCanvasHierarchyChanged方法,当父Canvas的状态发生改变时调用(当父Canvas被启用,禁用或嵌套Canvas的OverrideSorting被改变时,该函数被调用),把m_Canvas设置到currentCanvas,设置m_Canvas为空,调用CacheCanvas方法。从父节点中获取Canvas列表,取得第一个激活并且可用的Canvas赋值给m_Canvas,如果currentCanvas与m_Canvas不同,从GraphicRegistry解除注册,如果Graphic是激活并且可用时,重新注册到GraphicRegistry。
SetAllDirty方法
- SetLayoutDirty(),通知LayoutRebuilder重建Layout,调用m_OnDirtyLayoutCallback()回调
- SetVerticesDirty(),设置m_VertsDirty为true,把自己注册到CanvasUpdateRegistry的图形重建序列中,并调用m_OnDirtyVertsCallback()回调
- SetMaterialDirty(),设置m_MaterialDirty为true,把自己注册到CanvasUpdateRegistry的图形重建序列中,并调用m_OnDirtyMaterialCallback()回调
继承自ICanvasElement的方法
Rebuild方法
在Canvas渲染前被调用,在这个方法里会调用UpdateGeometry和UpdateMaterial更新顶点和材质。
UpdateGeometry方法
调用DoMeshGeneration(DoLegacyMeshGeneration,使用旧版的网格生成)方法,如果rectTransform不为空,且宽高都大于0,调用OnPopulateMesh,实际上只是把顶点和三角形信息保存到了s_VertexHelper里。然后获取所有的IMeshModifier类型的组件,(IMeshModifier是一个接口,需要依据顶点信息的组件继承自它,例如Shadow就间接继承自它),调用IMeshModifier的ModifyMesh方法,修改Mesh信息。最后将s_VertexHelper里修改后的信息赋值给workerMesh,并将workerMesh设置给canvasRenderer。
UpdateMaterial方法
更新canvasRenderer的材质和纹理。在给canvasRenderer设置材质时,会遍历所有IMaterialModifier类型的组件,调用IMaterialModifier.GetModifiedMaterial方法,用于重建图像时,获取修改后的Material,来实现遮罩效果。
OnPopulateMesh方法
在CanvasUpdateRegistry布局重建和图形重建时,会调用重建序列中的Graphic的Rebuild方法,Rebuild方法会调用OnPopulateMesh方法,为CanvasRenderer的Mesh提供了顶点位置、顶点颜色、UV和三角形信息。OnPopulateMesh方法把顶点数据和三角形信息保存到VertexHelper中。这个方法,会在RawImage,Image和Text中被重写,用来绘制图片和文字。
CrossFadeColor方法
ColorTween是渐变效果的方法,通过m_ColorTweenRunner启动一个协程来运行,m_ColorTweenRunner是在Graphic构造函数里创建的,是TweenRunner<ColorTween>的实例。
Raycast方法
通过ICanvasRaycastFilter(Image继承了这个接口)的IsRaycastLocationValid方法,判断射线在该组件是否有效。这个方法在GraphicRaycaster的Raycast方法里也被使用到,用于筛选出被射线 照射到的Graphic。GraphicRaycaster继承自BaseRaycaster,输入模块通过Raycast来获取被影响的对象。
OnCullingChanged
当CanvasRenderer.cull is modified的时候调用
PixelAdjustPoint
调整给点的像素以达到完美像素,当canvas.pixelPerfect勾选上时调用
GetPixelAdjustedRect
获取完美像素下的举行区域
RegisterDirtyLayoutCallback
UnregisterDirtyLayoutCallback
注册和反注册布局改变的回调
RegisterDirtyVerticesCallback
UnregisterDirtyVerticesCallback
注册和反注册顶点改变的回调
RegisterDirtyMaterialCallback
UnregisterDirtyMaterialCallback
注册和反注册材质改变的回调
GraphicRegistry
用于注册一个Graphic属于的是哪一个画布
内部维护一个字典Dictionary<Canvas, IndexedSet<Graphic>> m_Graphics = new Dictionary<Canvas, IndexedSet<Graphic>>();
IndexedSet ,内部的列表都是唯一值
重要方法:
void RegisterGraphicForCanvas(Canvas c, Graphic graphic),将graphic和c关联起来
void UnregisterGraphicForCanvas(Canvas c, Graphic graphic),解除graphic和c的关联
IList<Graphic> GetGraphicsForCanvas(Canvas canvas),获取canvas关联着的所有的graphic列表
GraphicRaycaster
继承自BaseRaycaster,用于画布下的射线检测
public override void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)
1,调用GraphicRegistry.GetGraphicsForCanvas(canvas)获取canvas下的所有关联的Graphic
2,获取displayIndex,
if (canvas.renderMode == RenderMode.ScreenSpaceOverlay || currentEventCamera == null)
displayIndex = canvas.targetDisplay;
else
displayIndex = currentEventCamera.targetDisplay;
3,判断eventPosition是否为Vector3.zero,
如果不是,求出 int eventDisplayIndex = (int)eventPosition.z;如果eventDisplayIndex != displayIndex直接return
如果是,eventPosition = eventData.position;
4,将当前的eventPosition转换到当前的视口坐标系中求出其坐标位置
5,从这个位置发射一条射线,求出射线得到的结果,判断是否为有效击中,将有效击中的存到结果列表中
private static void Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, IList<Graphic> foundGraphics, List<Graphic> results)
过滤掉无效的结果,并按照depth排序
if (graphic.depth == -1 || !graphic.raycastTarget || graphic.canvasRenderer.cull)
continue;
if (!RectTransformUtility.RectangleContainsScreenPoint(graphic.rectTransform, pointerPosition, eventCamera))
continue;
if (eventCamera != null && eventCamera.WorldToScreenPoint(graphic.rectTransform.position).z > eventCamera.farClipPlane)
continue;
if (graphic.Raycast(pointerPosition, eventCamera))
{
s_SortedGraphics.Add(graphic);
}
s_SortedGraphics.Sort((g1, g2) => g2.depth.CompareTo(g1.depth));