使使用 LineRender 绘制的线条可点击

Making line drawn with LineRender clickable

我在 Unity3d 中使用 LineRender 绘制动态线条。现在我需要通过在线单击鼠标右键来删除此行。但是我无法在线点击。有什么方法可以做到这一点,或者我必须使用一些东西而不是 LineRender?

我尝试添加到 EdgeCollider 行然后捕捉鼠标点击 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);
       }

但是这样我只能删除最后画的线

这是我创建线条的方式:

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;
    }

破坏独立行的解决方法

所以你想通过鼠标点击来破坏独立的线条。您在任意位置单击并破坏最后一行时遇到问题的原因可能是您将 EdgeCollider2D 保留为默认数据,因此所有行都在相同的点具有边缘碰撞器;不知何故,你的场景和相机处于一个位置,无论你点击哪里,Raycast2D 都会击中它们,而你只删除一个,它击中的第一个。

现在最好的解决办法是使用BakeMesh方法,但是如何正确实现呢

首先,当您创建行而不是 _line.gameObject.AddComponent<EdgeCollider2D>(); 时,添加 MeshCollider.

然后,在创建线并让按钮在 else if (Input.GetMouseButtonUp(0) && _line) 中向上后,您需要烘焙线网格并将其附加到网格碰撞器。

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;
    }

此外,根据您的场景设置方式,您可以尝试使该行不使用世界 space 作为默认值,例如 _line.useWorldSpace = false;

至此,我们应该有一个带有 MeshCollider 的 LineRenderer,其中 MeshCollider 是 LineRenderer 的烘焙网格。

最后,如何销毁它们,它和你之前的几乎一样,但是不是Raycast2d,而是使用普通的3d方法(Physics.Raycast),因为MeshCollider来自3d物理。

请详细阅读:

只需要一行的解决方案

问题是你每次都创建新的独立行(LineRenderer),所以当你想删除整行时,你只是删除其中一个而不是全部。

您可以继续这样做,但您需要以某种方式将每条独立的线保存在列表中,然后删除完成整条线的所有线游戏对象。

但最好的解决方案是使用 LineRenderer 向你的线条添加更多点,每次你想要一个新点时你应该增加你的 LineRendere 的 _line.positionCount = line.positionCount + 1; 然后保存到那个点的位置,比如 _line.SetPosition(line.positionCount-1, _mousePos);

现在使用 BakeMesh(正如@Iggy 建议的那样)会起作用,因为您只有一个包含所有点的 LineRenderer,您只需要使用您获得的网格 MeshCollider,并像这个例子.

一样使用它

编辑:阅读所有评论和代码后,我明白了@vviolka 想要什么,所以我添加了一个新的解决方案。