vviolka
vviolka

Reputation: 35

Making line drawn with LineRender clickable

I'm drawing dynamic lines using LineRender in Unity3d. And now I need to delete this lines by clicking right mouse button on line. But I can't get the click on line. Is there any way to do it or I must use something instead of LineRender?

I tried to add to line EdgeCollider and then catch mouse click like RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0)), Vector2.zero);

       if (hit.collider != null)
       {
           Destroy(hit.collider.gameObject);
       }

But this way I can delete only the last drawn line

Here is the way I create lines:

void Update(){
if (Input.GetMouseButtonDown(0))
      {
            if (_line == null)
                CreateLine(material);

            _mousePos = (Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, 
                Input.mousePosition.y, -transform.position.z)));
            _line.SetPosition(0, _mousePos);
            _line.SetPosition(1, _mousePos);
        }

        else if (Input.GetMouseButtonUp(0) && _line)
        {
            _mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y,
                -transform.position.z));
        _line.SetPosition(1, _mousePos);
        _line = null;
        }

        else if (Input.GetMouseButton(0) && _line)
        {
            _mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y,
                -transform.position.z));
        _line.SetPosition(1, _mousePos);
        }

    }


    private void CreateLine(Material material)
{
    _line = new GameObject("wall" + walls.Count).AddComponent<LineRenderer>();
    _line.material = material;
    _line.gameObject.AddComponent<EdgeCollider2D>();
    _line.positionCount = 2;
    _line.startWidth = 0.15f;
    _line.endWidth = 0.15f;
_line.numCapVertices = 50;
    }

Upvotes: 2

Views: 2560

Answers (1)

Marco Elizondo
Marco Elizondo

Reputation: 562

Solution for destroying independent lines

So you want to destroy independent lines by a mouse click. Probably the reason you are having the problem of clicking anywhere and destroying the last line, is that you are leaving EdgeCollider2D with default data, so all lines have the edge collider in the same points; and somehow your Scene and Camera are in a position where no matter where you click, the Raycast2D hits them all, and you delete only one, the first one it hits.

Now the best solution is using the BakeMesh method, but how to implement it correctly.

First, when you create the line instead of _line.gameObject.AddComponent<EdgeCollider2D>(); add a MeshCollider.

Then, after you create the line and let the button up in else if (Input.GetMouseButtonUp(0) && _line) you need to bake the line mesh and attached it to the mesh collider.

else if (Input.GetMouseButtonUp(0) && _line)
    {
        _mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y,
            -transform.position.z));
        _line.SetPosition(1, _mousePos);

        //Bake the mesh
        Mesh lineBakedMesh = new Mesh(); //Create a new Mesh (Empty at the moment)
        _line.BakeMesh(lineBakedMesh, true); //Bake the line mesh to our mesh variable
        _line.GetComponent<MeshCollider>().sharedMesh = lineBakedMesh; //Set the baked mesh to the MeshCollider
        _line.GetComponent<MeshCollider>().convex = true; //You need it convex if the mesh have any kind of holes

        _line = null;
    }

Also, depending on how your scene is setup you may try making the line not use world space as the default being true, like _line.useWorldSpace = false;

To this point, we should have a LineRenderer with a MeshCollider attached where the MeshCollider is the baked mesh of the LineRenderer.

Lastly, how to destroyed them, it's almost the same as you have previously, but instead of Raycast2d, use the normal 3d method (Physics.Raycast) because MeshCollider is from 3d physics.

Please read more about:

Solution if you want just one line

The problem is that you creating new independent lines (LineRenderer) each time, so when you want to delete the full line, you are deleting only one of them and not all.

You can continue doing that way but you need to somehow save each independent line in a list and then delete all the line game objects that complete your whole line.

But the best solution is to use LineRenderer to add more points to your line, every time you want a new point yo should increase your LineRendere's _line.positionCount = line.positionCount + 1; and then save the position to that point, like _line.SetPosition(line.positionCount-1, _mousePos);

Now using BakeMesh (as @Iggy suggested) would work because you have just one LineRenderer with all points, you just need to use the Mesh you got to a MeshCollider, and use it like this example.

EDIT: After reading all the comments and code I understand what is what @vviolka wanted, so I add a new solution.

Upvotes: 1

Related Questions