UGUI draws line segments

describe

Click the left mouse button to draw a line segment on the screen

Prepare

  1. VertexHelper grid drawing tool class
  2. vector, cross product
  3. RectTransformUtility.ScreenPointToLocalPointInRectangle
  4. SetVerticesDirty
  5. OnPopulateMesh

Ideas

  1. Press the mouse to record the starting point of the line segment;
  2. Keep pressing the mouse and record the movement vector of the current frame of the mouse;
  3. Use the cross product to obtain the unit vectors of the vertical and motion vectors;
  4. Get four vertices according to the set width; set vertex dirty data and update the grid

Example

Create a new script and inherit MaskableGraphic;
create an Image, remove the Image component and add a new script.
The script content is as follows:

Introduce namespace

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

Attributes

private List<List<UIVertex>> vertexList = new List<List<UIVertex>>();//缓存线段上的网格顶点
private Vector3 lastPoint;//上一帧的点击点
private Vector3 lastLeftPoint;
private Vector3 lastRightPoint;
bool isNewLine;//绘制新的线段
[SerializeField] private float lineWidth = 4f;//线段宽度

Method to draw the grid

protected override void OnPopulateMesh(VertexHelper vh)//绘制网格
{
    
    
    vh.Clear();
    for (int i = 0; i < vertexList.Count; i++)
        vh.AddUIVertexQuad(vertexList[i].ToArray());
}

Method to convert screen coordinates to local coordinates

Vector2 ScreenPointToLocalPoint(Vector2 mousePoint)
{
    
    
    var Rect = GetComponent<RectTransform>();
    Vector2 result = Vector2.zero;
    switch (canvas.renderMode)
    {
    
    
        case RenderMode.ScreenSpaceOverlay:
            RectTransformUtility.ScreenPointToLocalPointInRectangle(Rect, mousePoint, null, out result);
            break;
        case RenderMode.ScreenSpaceCamera:
            RectTransformUtility.ScreenPointToLocalPointInRectangle(Rect, mousePoint, canvas.worldCamera, out result);
            break;
        case RenderMode.WorldSpace:
            RectTransformUtility.ScreenPointToLocalPointInRectangle(Rect, mousePoint, canvas.worldCamera, out result);
            break;
    }
    return result;
}

Method to set mesh vertices

private void Update()
{
    
    
    if (Input.GetMouseButtonDown(0))//按下鼠标坐标表示 绘制新的线段
    {
    
    
        lastPoint = ScreenPointToLocalPoint(Input.mousePosition);//屏幕点转换到当前recttransform上的点
        isNewLine = true;
        vertexList.Clear();//清除上一次绘制的线段 若要保留 可不清除
    }
    else
    {
    
    
        if (Input.GetMouseButton(0))
        {
    
    
            Vector3 currentPoint = ScreenPointToLocalPoint(Input.mousePosition);
            Vector3 dir = currentPoint - lastPoint;//移动向量
            if (dir.magnitude < 10)//移动量过小 不绘制网格
                return;
            Vector3 normal = Vector3.Cross(dir.normalized, transform.forward);//移动向量和当前ui的朝向 进行叉乘
            if (isNewLine)
            {
    
    
                isNewLine = false;
                lastLeftPoint = lastPoint + normal * lineWidth;//绘制新的线段时 作为左侧起点
                lastRightPoint = lastPoint - normal * lineWidth;
            }
            Vector3 leftPoint = currentPoint + normal * lineWidth;//当前线段的左侧终点
            Vector3 rightPoint = currentPoint - normal * lineWidth;
            
            List<UIVertex> ver = new List<UIVertex>();
            UIVertex uIVertex = new UIVertex();//网格顶点列表
            uIVertex.position = lastLeftPoint;
            uIVertex.color = color;
            ver.Add(uIVertex);
            UIVertex uIVertex2 = new UIVertex();
            uIVertex2.position = lastRightPoint;
            uIVertex2.color = color;
            ver.Add(uIVertex2);
            UIVertex uIVertex3 = new UIVertex();
            uIVertex3.position = rightPoint;
            uIVertex3.color = color;
            ver.Add(uIVertex3);
            UIVertex uIVertex4 = new UIVertex();
            uIVertex4.position = leftPoint;
            uIVertex4.color = color;
            ver.Add(uIVertex4);
            vertexList.Add(ver);
            
            lastLeftPoint = leftPoint;//更新起点 当前帧的终点作为下一帧的起点
            lastRightPoint = rightPoint;
            lastPoint = currentPoint;
            SetVerticesDirty();//设置顶点脏数据 更新网格
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_43796392/article/details/133276108