Graphic
是一个抽象类,是MaskableGraphic
的基类,而MaskableGraphic
是Image,RawImage,Text的基类。负责显示界面。继承自UIBehavior
类以及ICanvasElement
接口。
重写UIBehavior的方法
OnEnable
首先调用CacheCanvas
方法,获取第一个处于激活状态的Canvas,然后赋值给m_Canvas
,然后将m_Canvas注册进GraphicRegistry
(之后再看注册进去的作用),然后设置s_WhiteTexture
(也就是mainTexture),最后调用SetAllDirty()
: Layout,Material,Vertices(标记Dirty后会触发重新绘制)
OnDisable
从GraphicRegistry
,CanvasUpdateRegistry
取消注册,清空canvasRender,然后重建Layout。
OnDestroy
删除 Mesh
OnRectTransformDimensionsChange
当RectTransform参数发生变化后会调用这个方法。
如果正在重建就标记顶点
为Dirty,否则标记顶点和Layout为Dirty。
OnBeforeTransformParentChanged
取消从GraphicRegistry
注册,标记重建Layout.
OnTransformParentChanged
重新给m_Canvas
赋值,从GraphicRegistry
注册Canvas,然后SetAllDirty()
。
OnDidApplyAnimationProperties
当 animation 属性发生变化后出发,会SetAllDirty()
。
OnCanvasHierarchyChanged
Called when the state of the parent Canvas is changed. 如果当前Canvas不是第一个处于激活状态的Canvas,那么就取消注册之前的Canvas,然后重新注册新的Canvas。
实现ICanvasElement 接口的方法
Rebuild(CanvasUpdate update)
用来重建当前stage,会在渲染前调用,
如果 canvasRenderer==null || canvasRenderer.cull(忽略渲染)就return掉。
符合条件就根据是否标记了VertsDirty
或MaterialDirty
而进行更新三角面和Material。
其他的一些方法
UpdateGeometry()
根据useLegacyMeshGeneration
不同而执行DoLegacyMeshGeneration()
或者DoMeshGeneration()
方法。
DoLegacyMeshGeneration。 首先会调用
OnPopulateMesh()
添加四个顶点,以及两个三角面到VertexHelper(这就是创建一个基础的四边形,而四个顶点和两个三角面是必不可少的)这个方法会在Image等组件中重写,然后绘制出不同的东西。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15protected virtual void OnPopulateMesh(VertexHelper vh)
{
var r = GetPixelAdjustedRect();
var v = new Vector4(r.x, r.y, r.x + r.width, r.y + r.height);
Color32 color32 = color;
vh.Clear();
vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(0f, 0f));
vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(0f, 1f));
vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(1f, 1f));
vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(1f, 0f));
vh.AddTriangle(0, 1, 2);
vh.AddTriangle(2, 3, 0);
}然后进行填充网格(FillMesh),这里要求顶点数不超过65000个。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public void FillMesh(Mesh mesh)
{
InitializeListIfRequired();
mesh.Clear();
if (m_Positions.Count >= 65000)
throw new ArgumentException("Mesh can not have more than 65000 vertices");
mesh.SetVertices(m_Positions);
mesh.SetColors(m_Colors);
mesh.SetUVs(0, m_Uv0S);
mesh.SetUVs(1, m_Uv1S);
mesh.SetUVs(2, m_Uv2S);
mesh.SetUVs(3, m_Uv3S);
mesh.SetNormals(m_Normals);
mesh.SetTangents(m_Tangents);
mesh.SetTriangles(m_Indices, 0);
mesh.RecalculateBounds();
}之后会拿到所有继承
IMeshModifier
的组件然后全部通过IMeshModifier.ModifyMesh()
进行修改Mesh信息。最后将Mesh提交给CanvasRenderer。DoMeshGeneration() 其实和DoLegacyMeshGeneration差不多。
UpdateMaterial()
更新材质球
和贴图
到CanvasRender。设置材质球时会获取所有的IMaterialModifier
组件,然后遍历这些组件通过IMaterialModifier.GetModifiedMaterial(currentMat)
的方式获取修改过的Material,然后返回。
1 | protected virtual void UpdateMaterial() |
CrossFadeColor()
在TweenRunner中开启协程,像NGUI的Tween动画。
Raycast()
- 首先说一下点击屏幕后如何判断是否点击到某和物体的原理:当点击屏幕,会发出一条由屏幕的点击位置射向屏幕后方的一条射线,检测这条射线是否射中某个GameObject,然后去响应对应事件即可。
在Raycast
方法中通过ICanvasRaycastFilter.IsRaycastLocationValid
进行判断传入的射线是否有效。该方法在GraphicRaycaster中被调用。