Bootstrap

Unity中在UI上画线

在UI中画一条曲线

我封装了一个组件,可以实现基本的画线需求.

效果

按住鼠标左键随手一画.

用起来也很简单,将组件挂到空物体上就行了,红色的背景是Panel.

你可以将该组件理解为一个Image,只不过形状更灵活一些罢了,所以它要放在下面的层级(不然可能会被挡住).

代码

可以调整一些基本的属性,如线的颜色和粗细.

using System;
using UnityEngine.UI;
using UnityEngine;
using System.Collections.Generic;
using Unity.VisualScripting;

[RequireComponent(typeof(CanvasRenderer))] //需要该组件才能生效
public class UILineRenderer : Graphic
{
    private readonly List<Vector2> points = new List<Vector2>(); // 用于存储线条的点

    [SerializeField] private float lineWidth = 5f; // 线条宽度
    [SerializeField] private Color lineColor = Color.white; // 默认线条颜色

    //----用来测试,你应当使用自己的办法调用DrawLine方法,后续删除这部分-----
    private List<Vector2> points1 = new List<Vector2>(); // 用于存储线条的点

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            points1.Clear();
        }
        else if (Input.GetMouseButton(0))
        {
            points1.Add(Input.mousePosition);
            DrawLine(points1);
        }
        else if (Input.GetMouseButtonUp(0))
        {
            foreach (var VARIABLE in points1)
            {
                Debug.Log(VARIABLE);
            }
        }
    }
    //--------------------------------------------------------

    // 每次需要重新绘制UI时调用
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear(); // 清空当前顶点数据

        // 如果没有足够的点,则不绘制任何东西
        if (points == null || points.Count < 2)
            return;

        // 遍历每个点,创建线段
        for (int i = 0; i < points.Count - 1; i++)
        {
            Vector2 start = points[i];
            Vector2 end = points[i + 1];

            // 计算垂直方向的法线,使线条有宽度
            Vector2 direction = (end - start).normalized;
            Vector2 perpendicular = new Vector2(-direction.y, direction.x) * lineWidth / 2f;

            // 四个顶点(左下、左上、右上、右下)
            UIVertex vertex = UIVertex.simpleVert;
            vertex.color = lineColor; // 定义颜色

            // 左下
            vertex.position = new Vector3(start.x - perpendicular.x, start.y - perpendicular.y);
            vh.AddVert(vertex);

            // 左上
            vertex.position = new Vector3(start.x + perpendicular.x, start.y + perpendicular.y);
            vh.AddVert(vertex);

            // 右上
            vertex.position = new Vector3(end.x + perpendicular.x, end.y + perpendicular.y);
            vh.AddVert(vertex);

            // 右下
            vertex.position = new Vector3(end.x - perpendicular.x, end.y - perpendicular.y);
            vh.AddVert(vertex);

            // 添加两个三角形来组成矩形线条
            int index = vh.currentVertCount;
            vh.AddTriangle(index - 4, index - 3, index - 2);
            vh.AddTriangle(index - 4, index - 2, index - 1);
        }
    }


    public void DrawLine(List<Vector2> pointArray)
    {
        if (pointArray == null || pointArray.Count < 2) return;

        List<Vector2> newPoints = new List<Vector2>();
        foreach (Vector2 v2 in pointArray)
        {
            Vector2 localPoint;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(
                rectTransform, // 当前 UILineRenderer 的 RectTransform
                v2,
                null,
                out localPoint // 输出的局部坐标
            );
            newPoints.Add(localPoint);
        }

        this.points.Clear();
        this.points.AddRange(newPoints);

        SetVerticesDirty();
    }

    /// <summary>
    /// 设置线的颜色
    /// </summary>
    /// <param name="newColor"></param>
    public void SetLineColor(Color newColor)
    {
        lineColor = newColor;
        SetVerticesDirty();
    }

    /// <summary>
    /// 设置线的宽带
    /// </summary>
    /// <param name="width"></param>
    public void SetWidth(float width)
    {
        lineWidth = width;
        SetVerticesDirty();
    }

    /// <summary>
    /// 重置组件
    /// </summary>
    public void ResetSelf()
    {
        points.Clear();
        lineColor = Color.white;
        lineWidth = 5f;
        SetVerticesDirty();
    }
}

 

 

;