当前位置:网站首页>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画其他图形的博客,供大家参考学习:
边栏推荐
- Apifox,你的API接口文档卷成这样了吗?
- Ali yunyili: how does yunyuansheng solve the problem of reducing costs and improving efficiency?
- 记一次JAP查询导致OOM的问题分析
- 6-6 vulnerability exploitation SSH security defense
- Application analysis of face recognition
- Andrews - multimedia programming
- C # / vb. Net supprime le filigrane d'un document word
- 服装企业部署MES管理系统的五个原因
- Number theory --- fast power, fast power inverse element
- Kubernetes源码分析(二)----资源Resource
猜你喜欢

Go swagger use

3 -- Xintang nuc980 kernel supports JFFS2, JFFS2 file system production, kernel mount JFFS2, uboot network port settings, and uboot supports TFTP

Pioneer of Web3: virtual human

What are the applications and benefits of MES management system

【Socket】①Socket技术概述

Classify the features of pictures with full connection +softmax

Station B's June ranking list - feigua data up main growth ranking list (BiliBili platform) is released!
MySQL is an optimization artifact to improve the efficiency of massive data query

C#/VB.NET 删除Word文檔中的水印

Niuke programming problem -- double pointer of 101 must be brushed
随机推荐
C # / vb. Net supprime le filigrane d'un document word
左程云 递归+动态规划
Redis入门完整教程:复制拓扑
Qpushbutton- "function refinement"
leetcode:5. Longest palindrome substring [DP + holding the tail of timeout]
Redis入门完整教程:AOF持久化
INS/GPS组合导航类型简介
MySQL
导数、偏导数、方向导数
Metaforce force meta universe fossage 2.0 smart contract system development (source code deployment)
慧通编程入门课程 - 2A闯关
Django数据库(SQlite)基本入门使用教程
Apifox, is your API interface document rolled up like this?
实施MES管理系统时,哪些管理点是需要注意的
How to write test cases for test coupons?
Common fitting models and application methods of PCL
进程管理基础
Matlb| economic scheduling with energy storage, opportunity constraints and robust optimization
Niuke programming problem -- double pointer of 101 must be brushed
Douban average 9 x. Five God books in the distributed field!