使用LineRender单击可绘制线

问题描述 投票:0回答:1

我正在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;
    }
c# unity3d raycasting
1个回答
0
投票

销毁独立线路的解决方案

所以您想通过单击鼠标破坏独立的行。可能是您单击任意位置并破坏了最后一行的问题,原因是您为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;
    }

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

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

最后,如何销毁它们,与以前几乎一样,但是请使用常规的3d方法(Physics.Raycast)代替Raycast2d,因为MeshCollider来自3d物理学。

请阅读更多有关:

如果您只想一行的解决方案

问题是您每次都创建新的独立行(LineRenderer),因此,当您要删除整行时,您将仅删除其中一行而不是全部。

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

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

现在使用BakeMesh(如@Iggy建议)将起作用,因为您只有一个LineRenderer包含所有点,您只需要使用到达MeshCollider的网格,并像this example一样使用它。

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

© www.soinside.com 2019 - 2024. All rights reserved.