Search code examples
c#unity-game-enginegame-physics

Unity3d drawing with whitespaces


I drew lines using LineRenderer. Game is 2d. What I want now is to create whitespace in line with the line on the gameobject with collider.

Here is the code I use for drawing and adding collider to line. What I want is not to draw a line on gameobjects, like circles(with CircleCollider2D) or squares(with BoxCollider2D). I want to have two different LineRenderers: one is finishing on collider, second is starting on it. What I'm trying to achieve That square does not hide the line. There is not a line where the square is.

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

public class DrawLine : MonoBehaviour
{
    private LineRenderer line;
    private bool isMousePressed;
    public bool isLeftMousePressed = false;

    public List<Vector3> pointsList;

    private Vector3 mousePos;
    public float width = 0.05f;

    // 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 = (Material)Resources.Load("Materials/LineMat");

        line.startWidth = width;
        line.endWidth = width;

        line.useWorldSpace = true;
        isMousePressed = false;
        pointsList = new List<Vector3>();

    }
    //    -----------------------------------    
    void Update()
    {
        if (Input.GetMouseButtonDown(1))
        {
           isLeftMousePressed = true;
        }

        if (isLeftMousePressed||Game.currentLevel == 0) return;

        if (Input.GetMouseButton(0))
        {
            isMousePressed = true; 
        }

        // Drawing line when mouse is moving(pressed)
        if (isMousePressed)
        {
            if (Input.GetMouseButtonUp(0))
            {
                isMousePressed = false;

                GameObject curve = (GameObject)Instantiate(Resources.Load("Curve"), transform.parent);
                curve.GetComponent<DrawLine>().width = width;

                if (line.GetPosition(line.positionCount - 1).z == 1) Destroy(gameObject);
                else enabled = false;
            }

            mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            mousePos.z = 0;

            if (!pointsList.Contains(mousePos))
            {
                pointsList.Add(mousePos);
                line.positionCount = pointsList.Count;
                line.SetPosition(pointsList.Count - 1, (Vector3)pointsList[pointsList.Count - 1]);

                try
                {
                    AddColliderToLine(line, (Vector3)pointsList[pointsList.Count - 2], (Vector3)pointsList[pointsList.Count - 1]);
                }
                catch(Exception e)
                {

                }
            }   
        }
    }

    //    -----------------------------------    
    //    Following method checks whether given two points are same or not
    //    -----------------------------------    
    private bool checkPoints(Vector3 pointA, Vector3 pointB)
    {
        return (pointA.x == pointB.x && pointA.y == pointB.y);
    }

    private void AddColliderToLine(LineRenderer line, Vector3 startPoint, Vector3 endPoint)
    {
        //create the collider for the line
        GameObject lcObject = new GameObject("LineCollider");
        BoxCollider2D lineCollider = lcObject.AddComponent<BoxCollider2D>();

        lcObject.layer = 2; // ignore raycast

        //set the collider as a child of your line
        lineCollider.transform.parent = line.transform;
        // get width of collider from line 
        float lineWidth = line.endWidth;
        // get the length of the line using the Distance method
        float lineLength = Vector3.Distance(startPoint, endPoint);
        // size of collider is set where X is length of line, Y is width of line
        //z will be how far the collider reaches to the sky
        lineCollider.size = new Vector3(lineLength, lineWidth);
        // get the midPoint
        Vector3 midPoint = (startPoint + endPoint) / 2;

        // move the created collider to the midPoint
        lineCollider.transform.position = midPoint;


        //heres the beef of the function, Mathf.Atan2 wants the slope, be careful however because it wants it in a weird form
        //it will divide for you so just plug in your (y2-y1),(x2,x1)
        float angle = Mathf.Atan2((endPoint.y - startPoint.y), (endPoint.x - startPoint.x));

        // angle now holds our answer but it's in radians, we want degrees
        // Mathf.Rad2Deg is just a constant equal to 57.2958 that we multiply by to change radians to degrees
        angle *= Mathf.Rad2Deg;

        //were interested in the inverse so multiply by -1
        //angle *= -1;
        // now apply the rotation to the collider's transform, carful where you put the angle variable
        // in 3d space you don't wan't to rotate on your y axis
        lineCollider.transform.Rotate(0, 0, angle);
    }
}

Solution

  • If you want to make dotted line, you can see 2D Dotted LineRenderer

    And add the collider on the part you want

     gameObject.AddComponent<PolygonCollider2D>();
    

    Edit:

    Check if mouse is inside the square by raycast

    if (isMousePressed)
    {
        var stopDrawing = false;  
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit))
        {
            if(hit.transform.tag == "square" || hit.transform.tag == "circle") {
                stopDrawing  = true;
            }
        }
        if(stopDrawing) 
        {
            // Stop current line, prepare a new List<Vector3> for next line
        }
        else{
            // Continue draw current line
        }
    }