Unity-LineRenderer

我要画线!

正文

How To Draw a Line in Unity | Line Renderer Tutorial 1

png

往一个 GameObject 里加上 LineRenderer 组件,Positions 里设好坐标点的坐标,Materials 里设好线条的材质,即可在游戏场景里画线。

写一个脚本,SetupLine() 功能是在 Transform 的坐标处连线:

c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class lr_LineController : MonoBehaviour
{
    private LineRenderer lr;
    private Transform[] points;
 
    private void Awake()
    {
        lr = GetComponent<LineRenderer>();
    }
 
    public void SetupLine(Transform[] points)
    {
        lr.positionCount = points.Length;
        this.points = points;
    }
 
    private void Update()
    {
        for(int i = 0; i < points.Length; i++)
        {
            lr.SetPosition(i, points[i].position);
        }
    }
}

再写一个脚本调用 SetupLine():

c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class lr_Testing : MonoBehaviour
{
    [SerializeField] private Transform[] points;
    [SerializeField] private lr_LineController line;
 
    private void Start()
    {
        line.SetupLine(points);
    }
}

给这个 lr_Testing 绑定若干 Transform,开跑!

png

How to Draw UI Lines in Unity in 10 Minutes | Line Renderer Tutorial 2

png

如何在 UI 层画线?将 Canvas 里的 Render Mode 设为 Screen Space - Camera。

png

上一节的代码就可以对 Canvas 里的 Transform 生效。

How to Draw Shapes in Unity | Line Renderer Unity Tutorial 3

png

构建场景如图所示。设计两个 Render Mode 为 Screen Space - Camera 的画布:Pen Tool Canvas 和 Dots Canvas。

png

绑定着 Pen Tool,控制画线的逻辑。

c#
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System;
 
public class PenCanvas : MonoBehaviour, IPointerClickHandler {
    public Action OnPenCanvasLeftClickEvent;
    public Action OnPenCanvasRightClickEvent;
    void IPointerClickHandler.OnPointerClick(PointerEventData eventData) {
        if (eventData.pointerId == -1) {
            OnPenCanvasLeftClickEvent?.Invoke();
        }
        else if (eventData.pointerId == -2) {
            OnPenCanvasRightClickEvent?.Invoke();
        }
    }
}

这段 Unity 代码定义了一个名为 PenCanvas 的脚本,实现了 IPointerClickHandler 接口,用于处理在画布上的点击事件。主要功能如下:

  1. 定义了两个事件处理函数 OnPenCanvasLeftClickEvent 和 OnPenCanvasRightClickEvent,分别表示在画布上左键点击和右键点击事件。
  2. 实现了 IPointerClickHandler 接口中的 OnPointerClick 方法,用于处理点击事件。当用户在画布上点击时,根据 eventData 中的 pointerId 判断点击的是左键(-1)还是右键(-2),然后触发相应的事件处理函数。

这段代码的作用是在 Unity 中实现了对画布上左键和右键点击事件的监听,并在点击事件发生时触发相应的事件处理函数。

How to Detect COLLISIONS on a Line Renderer in Unity

给 Line Prefab 绑上两个脚本:

png
c#
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
 
[RequireComponent(typeof(LineController), typeof(PolygonCollider2D))]
public class LineCollision : MonoBehaviour {
 
    LineController lineController;
    PolygonCollider2D polygonCollider;
 
    private void Awake() {
        lineController = GetComponent<LineController>();
        polygonCollider = GetComponent<PolygonCollider2D>();
    }
 
    private void LateUpdate() { 
 
        //Get all the positions from the line renderer
        Vector3[] positions = lineController.GetPositions();
 
        //If we have enough points to draw a line
        if (positions.Count() >= 2) {
 
            //Get the number of line between two points
            int numberOfLines = positions.Length - 1;
 
            //Make as many paths for each different line as we have lines
            polygonCollider.pathCount = numberOfLines;
 
            //Get Collider points between two consecutive points
            for (int i = 0; i < numberOfLines; i++) {
                //Get the two next points
                List<Vector2> currentPositions = new List<Vector2> {
                    positions[i],
                    positions[i+1]
                };
 
                List<Vector2> currentColliderPoints = CalculateColliderPoints(currentPositions);
                polygonCollider.SetPath(i, currentColliderPoints.ConvertAll(p => (Vector2)transform.InverseTransformPoint(p)));
            }
        }
        else {
 
            polygonCollider.pathCount = 0;
        }
    }
 
    private List<Vector2> CalculateColliderPoints(List<Vector2> positions) {
        //Get The Width of the Line
        float width = lineController.GetWidth();
 
        // m = (y2 - y1) / (x2 - x1)
        float m = (positions[1].y - positions[0].y) / (positions[1].x - positions[0].x);
        float deltaX = (width / 2f) * (m / Mathf.Pow(m * m + 1, 0.5f));
        float deltaY = (width / 2f) * (1 / Mathf.Pow(1 + m * m, 0.5f));
 
        //Calculate Vertex Offset from Line Point
        Vector2[] offsets = new Vector2[2];
        offsets[0] = new Vector2(-deltaX, deltaY);
        offsets[1] = new Vector2(deltaX, -deltaY);
 
        List<Vector2> colliderPoints = new List<Vector2> {
            positions[0] + offsets[0],
            positions[1] + offsets[0],
            positions[1] + offsets[1],
            positions[0] + offsets[1]
        };
 
        return colliderPoints;
    }
}

如此,生成线条时就会附带对应的碰撞体。