Search code examples
c#unity-game-enginedrawingterrain

How can i create an in-game system that lets me draw lines with the cursor that can act as walkable terrain


Hi im creating a 2D platformer, and i want to be able to draw for example lines ingame (playmode) with my cursor (like paint) that can act as walkable terrain. Im pretty new to coding and c# which im using, and im having a really hard time imagining how this can be achieved let alone if its possible? Would appreciate if you guys could give me some ideas and maybe could help me push it in the right direction. Thanks!

EDIT: So i got got some code now which makes me being able to draw in playmode. The question now is how i can implement a type of collider to this? Maybe each dot can represent a little square or something? How can i go through with it? Heres some code. Thanks.

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

public class DrawLine : MonoBehaviour 
{
    private LineRenderer line;
    private bool isMousePressed;
    private List<Vector3> pointsList;
    private Vector3 mousePos;

    // Structure for line points
    struct myLine
    {
        public Vector3 StartPoint;
        public Vector3 EndPoint;
    };
    //    -----------------------------------    
    void Awake()
    {
        // Create line renderer component and set its property
        line = gameObject.AddComponent<LineRenderer>();
        line.material =  new Material(Shader.Find("Particles/Additive"));
        line.SetVertexCount(0);
        line.SetWidth(0.1f,0.1f);
        line.SetColors(Color.green, Color.green);
        line.useWorldSpace = true;    
        isMousePressed = false;
        pointsList = new List<Vector3>();
    }
    //    -----------------------------------    
    void Update () 
    {
        // If mouse button down, remove old line and set its color to green
        if(Input.GetMouseButtonDown(0))
        {
            isMousePressed = true;
            line.SetVertexCount(0);
            pointsList.RemoveRange(0,pointsList.Count);
            line.SetColors(Color.green, Color.green);
        }
        else if(Input.GetMouseButtonUp(0))
        {
            isMousePressed = false;
        }
        // Drawing line when mouse is moving(presses)
        if(isMousePressed)
        {
            mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            mousePos.z=0;
            if (!pointsList.Contains (mousePos)) 
            {
                pointsList.Add (mousePos);
                line.SetVertexCount (pointsList.Count);
                line.SetPosition (pointsList.Count - 1, (Vector3)pointsList [pointsList.Count - 1]);

            }
        }
    }

}

Solution

  • Regarding means and tools:

    Input.mousePosition

    Input.GetKey, Input.GetKeyDown, Input.GetKeyUp

    Line renderer manual

    Line renderer scripting API

    Regarding general idea:

    Your script may use Input.GetKey to trigger the feature functionality (keyboard key, for example).

    When the feature is activated the script awaits of mouse button to be clicked by the means of Input.GetKeyUp and when the event happens it must capture current mouse position using Input.mousePosition.

    Only two points are necessary to build a segment of line, so when the script detects input of the second point it may create game object that will represent a piece of walkable terrain.

    Visually such an object may be represented with line renderer. To enable iteraction with other game objects (like player character) it is usually enough to enhance object with a collider component (presumably, with a BoxCollider).

    Regarding of how-to-add-a-collider:

    GameObject CreateLineCollider(Vector3 point1, Vector3 point2, float width)
    {
      GameObject obj = new GameObject("LineCollider");
      obj.transform.position = (point1+point2)/2;
      obj.transform.right = (point2-point1).normalized;
    
      BoxCollider boxCollider = obj.AddComponent<BoxCollider>();
      boxCollider.size = new Vector3( (point2-point1).magnitude, width, width );
    
      return obj;
    }
    

    You can add collider to object with line renderer but you still must orient it properly.

    Example of integration in your code:

    void Update () 
    {
      ...
    
      // Drawing line when mouse is moving(presses)
      if(isMousePressed)
      {
        mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        mousePos.z=0;
        if (!pointsList.Contains (mousePos)) 
        {
          pointsList.Add (mousePos);
          line.SetVertexCount (pointsList.Count);
          line.SetPosition (pointsList.Count - 1, (Vector3)pointsList [pointsList.Count - 1]);
    
          const float ColliderWidth = 0.1f;
    
          Vector3 point1 = pointsList[pointsList.Count - 2];
          Vector3 point2 = pointsList[pointsList.Count - 1];
    
          GameObject obj = new GameObject("SubCollider");
          obj.transform.position = (point1+point2)/2;
          obj.transform.right = (point2-point1).normalized;
    
          BoxCollider boxCollider = obj.AddComponent<BoxCollider>();
          boxCollider.size = new Vector3( (point2-point1).magnitude, ColliderWidth , ColliderWidth );
    
          obj.transform.parent = this.transform;
        }
      }
    }