当前位置:网站首页>Unity使用MaskableGraphic画一条带箭头的线
Unity使用MaskableGraphic画一条带箭头的线
2022-07-06 19:19:00 【周周的Unity小屋】

一、绘制箭头线段的原理
利用UGUI的MaskableGraphic类我们可以重写OnPopulateMesh函数来绘制多个矩形面片,让多个矩形面片组成一根带箭头的线段。如下图:
在一个大矩形UI框内重画一个右箭头的原理是:
由R1、R2、R3和R4四个顶点画出右箭头的头部下半部分小矩形:
由R1、R5、R6和R7四个顶点画出右箭头的头部上半部分小矩形:
由R4、R8、R9和R7四个顶点画出箭杆小矩形:
这样,我们只需要用9个顶点信息绘制出3个小矩形来构成一个箭头样式的线段了。同理,将右箭头的顶点信息中的x轴坐标取反,就可以画出左箭头了;将左右箭头部分画出来,再画中间箭杆矩形就可以组成一个左右双箭头样式的线段。详细请看下面核心代码和实现效果。
二、核心脚本及实现效果
1、核心脚本
DrawArrow.cs脚本:
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 定义箭头方向的枚举
/// </summary>
public enum DirectionType
{
Right,
Left,
Both
}
public class DrawArrow : MaskableGraphic
{
[SerializeField]
private DirectionType arrowDirection = DirectionType.Right;//默认为右箭头
public DirectionType ArrowDirection
{
set
{
arrowDirection = value;
SetVerticesDirty();//设置箭头类型之后需要重新绘制顶点
}
}
public Color arrowColor = Color.black;//默认箭头颜色为黑色
public float arrowPixel = 1.0f;//默认箭头像素为1
private float width;
private float height;
protected override void OnPopulateMesh(VertexHelper vh)
{
base.OnPopulateMesh(vh);
vh.Clear();
width = rectTransform.rect.width;//获取该矩形UI的宽
height = rectTransform.rect.height;//获取该矩形UI的高
//定义右箭头坐标点
var R1 = new Vector3(width * 0.5f, 0, 0);//右箭头顶点共用点
var R2 = new Vector3(width * 0.5f - height * 0.5f, -height * 0.5f, 0);
var R3 = new Vector3(width * 0.5f - height * 0.5f - arrowPixel, -(height * 0.5f - arrowPixel), 0);
var R4 = new Vector3(width * 0.5f - arrowPixel, arrowPixel, 0);//矩形共用点
var R5 = new Vector3(width * 0.5f - height * 0.5f, height * 0.5f, 0);
var R6 = new Vector3(width * 0.5f - height * 0.5f - arrowPixel, height * 0.5f - arrowPixel, 0);
var R7 = new Vector3(width * 0.5f - arrowPixel, -arrowPixel, 0);//矩形共用点
var R8 = new Vector3(-width * 0.5f, arrowPixel, 0);
var R9 = new Vector3(-width * 0.5f, -arrowPixel, 0);
//定义左箭头坐标点,与右箭头顶点的X轴相反
var L1 = new Vector3(-R1.x, R1.y, R1.z);//左箭头顶点共用点
var L2 = new Vector3(-R2.x, R2.y, R2.z);
var L3 = new Vector3(-R3.x, R3.y, R3.z);
var L4 = new Vector3(-R4.x, R4.y, R4.z);//矩形共用点
var L5 = new Vector3(-R5.x, R5.y, R5.z);
var L6 = new Vector3(-R6.x, R6.y, R6.z);
var L7 = new Vector3(-R7.x, R7.y, R7.z);//矩形共用点
var L8 = new Vector3(-R8.x, R8.y, R8.z);
var L9 = new Vector3(-R9.x, R9.y, R9.z);
switch (arrowDirection)
{
case DirectionType.Right://绘制右箭头
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, R1, R2, R3, R4));//右箭头的头部下半部分矩形
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, R1, R5, R6, R7));//右箭头的头部上半部分矩形
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, R4, R8, R9, R7));//右箭头的箭杆矩形
break;
case DirectionType.Left://绘制左箭头
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, L1, L2, L3, L4));
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, L1, L5, L6, L7));
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, L4, L8, L9, L7));
break;
case DirectionType.Both://绘制左右双箭头
//右箭头部分两个矩形
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, R1, R2, R3, R4));
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, R1, R5, R6, R7));
//左箭头部分两个矩形
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, L1, L2, L3, L4));
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, L1, L5, L6, L7));
//中间箭杆矩形
vh.AddUIVertexQuad(GetRectangleQuad(arrowColor, R4, R7, L7, L4));
break;
}
}
/// <summary>
/// 获取矩形面片,四点顶点信息绘制成一个矩形
/// </summary>
private UIVertex[] GetRectangleQuad(Color _color, params Vector2[] vector2s)
{
UIVertex[] vertexs = new UIVertex[vector2s.Length];
for (int i = 0; i < vertexs.Length; i++)
{
vertexs[i] = GetUIVertex(vector2s[i], _color);
}
return vertexs;
}
/// <summary>
/// 获取 UI顶点
/// </summary>
/// <param name="point"></param>
/// <param name="color"></param>
/// <returns></returns>
private UIVertex GetUIVertex(Vector2 point, Color _color)
{
UIVertex vertex = new UIVertex
{
position = point,
color = _color,
uv0 = Vector2.zero
};
return vertex;
}
}
将该脚本挂载到UI空物体对象上,调整其宽高(最好是2:1或者更高),设置箭头类型或颜色即可。
2、实现效果
右箭头:
左箭头:
左右双箭头:
三、推荐阅读
当你理解了MaskableGraphic类绘制图形的原理之后,你就可以利用它来画出你想要的图案了。你也可以对本博客的画箭头代码加以拓展,画出渐变色的箭头线段或者任何你想要的箭头样式图案。下面是一些利用MaskableGraphic画其他图形的博客,供大家参考学习:
边栏推荐
- dotConnect for DB2数据提供者
- MySQL
- How to design interface test cases? Teach you a few tips to draft easily
- The annual salary of general test is 15W, and the annual salary of test and development is 30w+. What is the difference between the two?
- Common fitting models and application methods of PCL
- 如何设计好接口测试用例?教你几个小技巧,轻松稿定
- Software testing -- common assertions of JMeter interface testing
- KYSL 海康摄像头 8247 h9 isapi测试
- MySQL
- 普通测试年薪15w,测试开发年薪30w+,二者差距在哪?
猜你喜欢
随机推荐
Huitong programming introductory course - 2A breakthrough
MySQL
C语言练习题_1
普通测试年薪15w,测试开发年薪30w+,二者差距在哪?
Read fast RCNN in one article
Qpushbutton- "function refinement"
安德鲁斯—-多媒体编程
Kubernetes源码分析(二)----资源Resource
基于ensp防火墙双击热备二层网络规划与设计
[node learning notes] the chokidar module realizes file monitoring
MySQL
你不可不知道的Selenium 8种元素定位方法,简单且实用
测试优惠券要怎么写测试用例?
Oracle中日期的使用方法实例
电气工程及其自动化
安全交付工程师
The annual salary of general test is 15W, and the annual salary of test and development is 30w+. What is the difference between the two?
How to build a 32core raspberry pie cluster from 0 to 1
Andrews - multimedia programming
牛客编程题--必刷101之双指针篇









