当前位置:网站首页>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画其他图形的博客,供大家参考学习:
边栏推荐
- Convert widerperson dataset to Yolo format
- Andrews - multimedia programming
- LeetCode 77:组合
- 你不可不知道的Selenium 8种元素定位方法,简单且实用
- 进程管理基础
- [node learning notes] the chokidar module realizes file monitoring
- Five reasons for clothing enterprises to deploy MES management system
- What management points should be paid attention to when implementing MES management system
- Use of fiddler
- [Mori city] random talk on GIS data (II)
猜你喜欢
Fundamentals of process management
Have fun | latest progress of "spacecraft program" activities
KYSL 海康摄像头 8247 h9 isapi测试
Remember the problem analysis of oom caused by a Jap query
leetcode:5. Longest palindrome substring [DP + holding the tail of timeout]
基于ensp防火墙双击热备二层网络规划与设计
慧通编程入门课程 - 2A闯关
Redis入门完整教程:复制配置
导数、偏导数、方向导数
如何设计好接口测试用例?教你几个小技巧,轻松稿定
随机推荐
Code line breaking problem of untiy text box
Have fun | latest progress of "spacecraft program" activities
Google Earth engine (GEE) -- 1975 dataset of Landsat global land survey
[leetcode]Search for a Range
差异与阵列和阵列结构和链表的区别
What management points should be paid attention to when implementing MES management system
CDB PDB 用户权限管理
安德鲁斯—-多媒体编程
服装企业部署MES管理系统的五个原因
C#/VB. Net to delete watermarks in word documents
Code debugging core step memory
Statistics of radar data in nuscenes data set
C language exercises_ one
Software testing -- common assertions of JMeter interface testing
数字滚动增加效果
C#/VB.NET 删除Word文檔中的水印
巴比特 | 元宇宙每日必读:IP授权是NFT的破圈之路吗?它的难点在哪里?Holder该如何选择合作平台?...
从零安装Redis
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?
Leetcode:minimum_ depth_ of_ binary_ Tree solutions