Unity中使用LineRenderer进行画线

一:世界空间下绘制

挂载到任意游戏物体身上

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

/// <summary>
/// 画线控制器
/// </summary>
public class DrawLineController : MonoSingleton<DrawLineController>
{
    private bool m_EnableDraw = true;//是否开启绘制
    public bool EnableDraw
    {
        get { return m_EnableDraw; }
        set { m_EnableDraw = value; }
    }

    public bool openOptimize;//是否开启优化(顶点数增加会带来性能消耗)
    public int optimizeAddVertexCount;//优化后两个点之间添加的顶点数

    private bool m_IsMouseDown;//鼠标是否按下

    private Vector2 m_LastMousePos;//上一次的鼠标位置
    private List<LineRenderer> m_LineRendererList = new List<LineRenderer>();//存储所有的LineRenderer
    private LineRenderer m_CurLineRenderer;//当前的LineRenderer

    public float drawLineMinDist = 0.2f;//绘制线段的最小距离
    public LayerMask ignoreLayer;//忽略的层

    //线段参数
    public float lineWidth = 0.2f;//线的宽度
    public Material lineMat;//线的材质
    public int lineCapVertices;//线顶点平滑度
    public int lineCornerVertices;//线拐点顶点数
    public Color startColor;//线的颜色
    public Color endColor;//线的颜色

    private Action<LineRenderer> m_OnBeginDrawLine;//开始绘制的回调
    private Action<LineRenderer, Vector2, bool> m_OnMouseDrag;//鼠标拖拽时的回调
    private Action<LineRenderer, Vector2, Vector2> m_OnDrawLine;//绘制的回调(只有绘制的时候才会调用)
    private Action<LineRenderer> m_OnEndDrawLine;//结束绘制的回调

    public void RegisterOnBeginDrawLineCallback(Action<LineRenderer> onBeginDrawLine)
    {
        m_OnBeginDrawLine = onBeginDrawLine;
    }

    public void RegisterOnMouseDragCallback(Action<LineRenderer, Vector2, bool> onMouseDrag)
    {
        m_OnMouseDrag = onMouseDrag;
    }

    public void RegisterOnDrawLineCallback(Action<LineRenderer, Vector2, Vector2> onDrawLine)
    {
        m_OnDrawLine = onDrawLine;
    }

    public void RegisterOnEndDrawLineCallback(Action<LineRenderer> onEndDrawLine)
    {
        m_OnEndDrawLine = onEndDrawLine;
    }

    /// <summary>
    /// 创建LineRenderer
    /// </summary>
    private void CreateLineRenderer()
    {
        GameObject go = new GameObject("LineRenderer");
        go.transform.SetParent(transform);
        m_CurLineRenderer = go.AddComponent<LineRenderer>();
        m_CurLineRenderer.positionCount = 0;
        m_CurLineRenderer.startWidth = lineWidth;
        m_CurLineRenderer.endWidth = lineWidth;
        m_CurLineRenderer.material = lineMat;
        m_CurLineRenderer.numCapVertices = lineCapVertices;
        m_CurLineRenderer.numCornerVertices = lineCornerVertices;
        m_CurLineRenderer.useWorldSpace = false;
        m_CurLineRenderer.startColor = startColor;
        m_CurLineRenderer.endColor = endColor;
        m_LineRendererList.Add(m_CurLineRenderer);
    }

    private void Update()
    {
        if (!m_EnableDraw)
        {
            return;
        }
        if (Input.GetMouseButtonDown(0))
        {
            BeginDrawLine();
            m_IsMouseDown = true;
        }
        if (Input.GetMouseButtonUp(0))
        {
            EndDrawLine();
            m_IsMouseDown = false;
        }
        if (m_IsMouseDown)
        {
            InDrawLine();
        }
    }

    /// <summary>
    /// 开始画线
    /// </summary>
    private void BeginDrawLine()
    {
        CreateLineRenderer();
        AddPosition(CTUtils.Screen2World(Input.mousePosition));

        m_OnBeginDrawLine?.Invoke(m_CurLineRenderer);
    }

    /// <summary>
    /// 画线中
    /// </summary>
    private void InDrawLine()
    {
        Vector2 curLineWorldPos = CTUtils.Screen2World(Input.mousePosition);
        Vector2 lastLineWorldPos = m_CurLineRenderer.GetPosition(m_CurLineRenderer.positionCount - 1);
        bool isMoving = curLineWorldPos != m_LastMousePos;
        m_OnMouseDrag?.Invoke(m_CurLineRenderer, curLineWorldPos, isMoving);
        if (Vector2.Distance(lastLineWorldPos, curLineWorldPos) >= drawLineMinDist && CanDraw(lastLineWorldPos, curLineWorldPos))
        {
            if (openOptimize)
            {
                //为两个点之间再添加多个点,让线段看起来更平滑
                optimizeAddVertexCount = optimizeAddVertexCount == 0 ? 1 : optimizeAddVertexCount;
                Vector2 deltaPos = (curLineWorldPos - lastLineWorldPos) / optimizeAddVertexCount;
                for (int i = 1; i <= optimizeAddVertexCount; i++)
                {
                    AddPosition(lastLineWorldPos + deltaPos * i);
                }
            }
            else
            {
                AddPosition(curLineWorldPos);
            }
            m_OnDrawLine?.Invoke(m_CurLineRenderer, lastLineWorldPos, curLineWorldPos);
        }
        m_LastMousePos = curLineWorldPos;
    }

    /// <summary>
    /// 结束画线
    /// </summary>
    private void EndDrawLine()
    {
        m_OnEndDrawLine?.Invoke(m_CurLineRenderer);

        if (m_CurLineRenderer.positionCount <= 1)
        {
            ClearLine(m_CurLineRenderer);
        }
        m_CurLineRenderer = null;
    }

    /// <summary>
    /// 向LineRenderer添加点
    /// </summary>
    private void AddPosition(Vector2 curLineWorldPos)
    {
        m_CurLineRenderer.SetPosition(m_CurLineRenderer.positionCount++, curLineWorldPos);
    }

    /// <summary>
    /// 能否画线
    /// </summary>
    private bool CanDraw(Vector2 lastPos, Vector2 nextPos)
    {
        //是否画在忽略的层上
        Vector2 dir = (nextPos - lastPos).normalized;
        float dist = (nextPos - lastPos).magnitude;
        RaycastHit2D raycastHit2D = Physics2D.Raycast(lastPos, dir, dist, ignoreLayer.value);
        if (raycastHit2D.collider != null)
        {
            return false;
        }
        return true;
    }

    /// <summary>
    /// 清除全部线
    /// </summary>
    public void ClearAllLine()
    {
        for (int i = m_LineRendererList.Count - 1; i >= 0; i--)
        {
            ClearLine(m_LineRendererList[i]);
        }
    }

    /// <summary>
    /// 清除线
    /// </summary>
    private void ClearLine(LineRenderer lineRenderer)
    {
        lineRenderer.positionCount = 0;
        m_LineRendererList.Remove(lineRenderer);
        Destroy(lineRenderer.gameObject);
    }

    /// <summary>
    /// 设置是否开启绘制
    /// </summary>
    public void SetEnableDraw(bool isEnable)
    {
        m_EnableDraw = isEnable;
    }
}

二:UI上绘制

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
Vectorsity是一款在Unity游戏引擎使用画线插件。它通过提供简单易用的API,使开发者能够方便地在3D场景绘制直线、曲线等几何形状。Vectorsity具有许多强大的功能和特点。 首先,Vectorsity提供了丰富的画线选项。开发者可以定义线段的起点和终点,设置线段的颜色、宽度以及透明度。此外,还可以调整线段的端点样式,如箭头、圆形等,以及线段的虚线样式。 其次,Vectorsity支持绘制曲线。开发者可以通过指定控制点来创建贝塞尔曲线,还可以设置曲线的分段数和平滑度。此外,可以通过添加锚点来使曲线在不同的地方有不同的弯曲程度。 另外,Vectorsity还提供了多种画线方法。开发者可以绘制直线、折线、曲线等各种几何形状。此外,还可以在已有的线段上继续绘制,使得绘制复杂的路径变得更加便捷。 除此之外,Vectorsity还支持画线的交互性。开发者可以通过监听鼠标点击或触摸事件,在用户交互的情况下动态绘制线段。这在制作绘画类游戏或实现交互式的路径规划系统时非常有用。 总之,Vectorsity是一款功能强大、易于使用Unity画线插件。它提供了丰富的画线选项,支持绘制直线、曲线等各种几何形状,并且还可以实现交互性。无论是制作游戏还是开发其他类型的应用程序,Vectorsity都是一款极具价值的工具。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello Bug.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值