Drawing Lines with the Mouse in Unity

Summary

A simple and cheap way to draw LineRenderers and add EdgeCollider2Ds to them using the mouse (or touch if on mobile). Highly expandable and versatile gameplay mechanic.

Created for our upcoming game Hexagone

Main script. Place this anywhere and plug in a prefab that contains a LineRenderer and EdgeCollider2D component. Make sure it’s Transform is reset and the LineRenderer has no points.

So long as there is an Orthographic MainCamera present it should run. Though note position/orientation of the camera may effect adversely ScreenToWorldPoint(Input.mousePosition) so watch for this.

using UnityEngine;

namespace ArmanDoesStuff.ClickToDraw
{
    public class ClickToDraw : MonoBehaviour
    {
        [SerializeField] private LineRenderer pathPrefab; //Create prefab with LineRenderer and EdgeCollider2D, then assign it here
        private LineRenderer pathCurrent; //The current path
        private bool touchDown = false; //Whether or not the mouse (r touch if mobile) is down
        Vector3 lastPos = Vector3.zero; //To check distance between points

        void Update()
        {
            if (Input.GetMouseButtonDown(0)) //Wait for left click
            {
                TouchStart();
                return;
            }
            if (touchDown) //if dragging
            {
                if (Input.GetMouseButtonUp(0)) //wait for left unclick
                    TouchEnd();
                else
                    TouchDrag(); //otherwise drag
            }
            /* Same as above but with mobile controls
            if (Input.touchCount > 0)
            {
                Touch touch = Input.GetTouch(0);


                if (touch.phase == TouchPhase.Began)
                {
                    TouchStart();
                    return;
                }
                else if (touch.phase == TouchPhase.Ended)
                {
                    TouchEnd();
                    return;
                }

                if (touchDown)
                {
                    TouchDrag();
                }
            }
            */
        }

        //On Start - Start dragging and create a new pathPrefab
        private void TouchStart()
        {
            touchDown = true;
            pathCurrent = Instantiate(pathPrefab, Vector3.zero, Quaternion.identity, transform);
        }

        //On Drag - Add current mouse position to the LineRenderer
        private void TouchDrag()
        {
            Vector3 _pos = Input.mousePosition;
            if (Vector3.Distance(_pos, lastPos) > 30f) //Only add a point if the mouse has moved enough so it doesn't make loads on one spot
            {
                lastPos = _pos;
                Vector3 _pos = Camera.main.ScreenToWorldPoint(Input.mousePosition); //get the new mouse position reletive to the screen
                _pos.z = 0;
                pathCurrent.positionCount++; //add it to the end of the array
                pathCurrent.SetPosition(pathCurrent.positionCount - 1, _pos);
            }
        }

        //On End - Stop dragging and add an EdgeCollider2D
        private void TouchEnd()
        {
            touchDown = false;
            Vector3[] points = new Vector3[pathCurrent.positionCount]; //Create array large enough to hold all the LineRenderer points
            pathCurrent.GetPositions(points); //Assign the points to the Array
            EdgeCollider2D eCol = pathCurrent.GetComponent<EdgeCollider2D>(); //Get the EdgeCollider2D which we added to the prefab when creating it
            eCol.points = ToVector2Array(points); //Assugb the EdgeCollider2D points after converting the Vec3 array to a Vec3 Array
        }

        private Vector2[] ToVector2Array(Vector3[] v3)
        {
            return System.Array.ConvertAll<Vector3, Vector2>(v3, getV3fromV2);
        }

        private Vector2 getV3fromV2(Vector3 v3)
        {
            return new Vector2(v3.x, v3.y);
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.