Side trip: How to draw a line in Unity

I’ve been secretly working on a another game project (codename ”Grow Some Ball”). For that game I implemented a line drawing script since the Unity’s own Line Renderer was too restricted. The script draws a line during mouse dragging – between the start click point and the current mouse position. The line is a quad drawn with two adjacent triangles.

Untitled
Mouse drag line drawn with red material (thickness increased to show the quad)

The code is quite straightforward and I though it might be useful to some of your starting with Unity (and mesh generation). It simply transforms the mouse drag screen coordinates to world coordinates (with z -1.0) and calculates the positions of the four vertices that form the line quad. So here it is!

using UnityEngine;

public class LineDrawer : MonoBehaviour
{
    public Material lineMaterial;
    public float lineZ = -1.0f;
    public float lineThickness;

    bool dragOn = false;

    GameObject lineGO;
    Mesh lineMesh;
    Vector3[] lineNormals = new Vector3[4];
    Vector3[] lineVertices = new Vector3[4];
    int[] lineTriangles = new int[6];

    Vector3 dragStartPosition;
    Vector3 mouseCurrentPosition;

    void Start ()
    {
        lineGO = new GameObject("DragLine");
        MeshRenderer renderer =
            lineGO.AddComponent<MeshRenderer>();
        renderer.shadowCastingMode = 
            UnityEngine.Rendering.ShadowCastingMode.Off;
        renderer.material = lineMaterial;

        lineMesh = new Mesh();
        MeshFilter meshFilter = lineGO.AddComponent<MeshFilter>();
        meshFilter.mesh = lineMesh;

        lineTriangles[0] = 0;
        lineTriangles[1] = 1;
        lineTriangles[2] = 2;
        lineTriangles[3] = 0;
        lineTriangles[4] = 2;
        lineTriangles[5] = 3;
        lineNormals[0] = new Vector3(-1.0f, 0.0f, 0.0f);
        lineNormals[1] = new Vector3(-1.0f, 0.0f, 0.0f);
        lineNormals[2] = new Vector3(-1.0f, 0.0f, 0.0f);
        lineNormals[3] = new Vector3(-1.0f, 0.0f, 0.0f);
        lineVertices[0] = new Vector3(0.0f, 0.0f, lineZ);
        lineVertices[1] = new Vector3(0.0f, 0.0f, lineZ);
        lineVertices[2] = new Vector3(0.0f, 0.0f, lineZ);
        lineVertices[3] = new Vector3(0.0f, 0.0f, lineZ);
    }

    void DrawDragLine()
    {
        Debug.Assert(dragOn);

        if (dragStartPosition == mouseCurrentPosition) return;

        Vector3 lineStart;
        Vector3 lineEnd;

        if (dragStartPosition.x > mouseCurrentPosition.x)
        {
            lineStart = mouseCurrentPosition;
            lineEnd = dragStartPosition;
        }
        else
        {
            lineStart = dragStartPosition;
            lineEnd = mouseCurrentPosition;
        }

        float angle = Mathf.Atan2(
            lineEnd.y - lineStart.y, lineEnd.x - lineStart.x);
        float angle2 = Mathf.PI / 2.0f - angle;
        float dx = lineThickness * Mathf.Cos(angle2);
        float dy = lineThickness * Mathf.Sin(angle2);

        lineVertices[0].x = lineStart.x + dx;
        lineVertices[0].y = lineStart.y - dy;

        lineVertices[1].x = lineStart.x - dx;
        lineVertices[1].y = lineStart.y + dy;

        lineVertices[2].x = lineEnd.x - dx;
        lineVertices[2].y = lineEnd.y + dy;

        lineVertices[3].x = lineEnd.x + dx;
        lineVertices[3].y = lineEnd.y - dy;

        lineMesh.vertices = lineVertices;
        lineMesh.triangles = lineTriangles;
        lineMesh.normals = lineNormals;
    }

    void Update ()
    {
        if (!dragOn)
        {
            if (Input.GetMouseButtonDown(0))
            {
                dragStartPosition = Camera.main.ScreenToWorldPoint(
                    Input.mousePosition);
                dragOn = true;
            }
        }
        else
        {
            if (Input.GetMouseButton(0))
            {
                mouseCurrentPosition =
                    Camera.main.ScreenToWorldPoint(
                    Input.mousePosition);
                DrawDragLine();
            }
            else
            {
                if (Input.GetMouseButtonUp(0))
                {
                    lineMesh.Clear();
                    dragOn = false;
                }
            }
        }
    }
}

Sorry for the lack of syntax highlighting 🙁 If your want to test the script create a new 2D project in Unity, create an empty GameObject to the scene and drag the script to it (so it becomes a Component). Assign a material to the script in the Inspector and select the desired line thickness. Have fun!