项目中遇到一个需求:由于模型和UI像素的原因,项目中用尺子测量东西的时候肉眼读数与实际误差过大,为了减少误差需要在unity中把尺子的刻度画出来。一开始我是有点懵的,心想这unity怎么能画出一个类似于刻度的矩形呀,后来经过组长的指导,了解到UGUI中有一个MaskableGraphic类可以画线,就研究了一下该类原理,得以实现需求。

MaskableGraphic类画线原理

实际上Unity中的每一个UI元素都是由三角面片拼接而成的,首先新建一个UI元素的空物体,新建一个脚本继承MaskableGraphic类,重写OnPopulateMesh方法,默认执行基类方法看一下效果:

unity 圆形矩阵 unity 画矩形_UGUI


将脚本挂载到空物体上:

unity 圆形矩阵 unity 画矩形_unity_02


unity 圆形矩阵 unity 画矩形_unity 圆形矩阵_03


我们可以清楚的看到一张Image图片其实就是由两个三角面片组合而成的,基于这个原理我们就可以画出一个矩形来了。

重写OnPopulateMesh方法

unity 圆形矩阵 unity 画矩形_unity 圆形矩阵_04


unity 圆形矩阵 unity 画矩形_MaskableGraphic_05


unity 圆形矩阵 unity 画矩形_unity 圆形矩阵_06

实现的效果

MaskableGraphic绘制的时候是根据UI物体的锚点位置开始绘制的,默认不改锚点是这个效果:

unity 圆形矩阵 unity 画矩形_unity_07


unity 圆形矩阵 unity 画矩形_mesh_08


将锚点Pivot改为0之后的效果:

unity 圆形矩阵 unity 画矩形_mesh_09


unity 圆形矩阵 unity 画矩形_unity_10


根据实际需求找规律重写绘制方法实现了我想要的效果:

控制绘制矩形的数量

unity 圆形矩阵 unity 画矩形_mesh_11

额外的知识

OnPopulateMesh方法

重写Graphic的OnPopulateMesh方法,在CanvasUpdateRegistry布局重建和图形重建时,会调用重建序列中的Graphic的Rebuild方法,Rebuild方法会调用OnPopulateMesh方法,为CanvasRenderer的Mesh提供了顶点、顶点颜色、UV和三角形信息。OnPopulateMesh方法把顶点数据和三角形信息保存到VertexHelper中。

需要注意的事

虽然使用MaskableGraphic类能减小像素带来的误差,但是如果绘制的时候设置的像素太小的话,遇到低分辨率的电脑就看不出来,解决方法:

将要绘制的UI空物体放到不受屏幕像素影响的canvas下绘制,适当增加面片的像素,canvas的组件canvas scaler的UI Scale Mode属性修改为Constant Pixel Size即无论屏幕大小如何,UI始终保持相同像素大小。

unity 圆形矩阵 unity 画矩形_unity 圆形矩阵_12