如何使用线渲染器绘制从 A 点到 B 点的正弦波

How to draw a sine wave using line renderer from point A to point B

this tutorial 之后,我正在尝试使用 Line Renderer 组件使用输入的鼠标位置绘制从 A 点到 B.I' 的正弦波。但是到目前为止我所做的没有用,它只是沿着 x 轴绘制正弦波,我需要从起点到输入鼠标位置绘制它。

private void Update()
{
    if (Input.GetMouseButtonDown(0))
    {
        Vector3 newPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        newPos.z = 0;
        CreatePointMarker(newPos);
        GenerateNewLine();
    }
}

private void CreatePointMarker(Vector3 pointPosition)
{
    Instantiate(linePointPrefab, pointPosition, Quaternion.identity);
} 

private void GenerateNewLine()
{
    GameObject[] allPoints = GameObject.FindGameObjectsWithTag("PointMarker");
    Vector3[] allPointPositions = new Vector3[allPoints.Length];
    var pointList = new List<Vector3>();
    for (int i = 0; i < 50; i ++)
        {
            var dir = allPoints[0].transform.position - allPoints[1].transform.position;
            float x = dir.x * i;
            float y = Mathf.Sin(x * Time.time);
            var sine = new Vector3(x, y, 0f);
            var tangentLine = allPoints[0].transform.position + sine;

            pointList.Add(tangentLine);
        }
        SpawnLineGenerator(pointList.ToArray());
    }
}

private void SpawnLineGenerator(Vector3[] linePoints)
{
    GameObject newLineGen = Instantiate(lineGeneratorPrefab);
    LineRenderer lRend = newLineGen.GetComponent<LineRenderer>();

    lRend.positionCount = linePoints.Length;
    lRend.SetPositions(linePoints);
}

作为替代方案,我建议改用

lineRenderer.useWorlsSpace = false;

所以这些点不再设置在世界space中,而是在相对于线性渲染器变换的局部space中。

现在您可以简单地旋转 linerenderer 变换以指向最新的用户输入位置。

我无法使用您的代码示例,因为我不知道您的预制件是什么,所以我根据给定视频中的代码创建了自己的预制件。我希望你能reuse/recreate需要的部分

public class SinusWave : MonoBehaviour
{
    public Vector3 initalPosition;
    public int pointCount = 10;
    public LineRenderer line;

    private Vector3 secondPosition;
    private Vector3[] points;
    private float segmentWidth;

    private void Awake()
    {
        line = GetComponent<LineRenderer>();

        line.positionCount = pointCount;

        // tell the linerenderer to use the local 
        // transform space for the point coorindates
        line.useWorldSpace = false;

        points = new Vector3[pointCount];
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // Camera.main.ScreenToWorldPoint needs a value in Z
            // for the distance to camera
            secondPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition - Vector3.forward * Camera.main.transform.position.z);
            secondPosition.z = 0;

            var dir = secondPosition - initalPosition;
            // get the segmentWidth from distance to end position
            segmentWidth = Vector3.Distance(initalPosition, secondPosition) / pointCount;

            // get the difference angle in the Z axis between the current transform.right
            // and the direction
            var angleDifference = Vector3.SignedAngle(transform.right, dir, Vector3.forward);
            // and rotate the linerenderer transform by that angle in the Z axis
            // so the result will be that it's transform.right
            // points now towards the clicked position
            transform.Rotate(Vector3.forward * angleDifference, Space.World);
        }

        for (var i = 0; i < points.Length; ++i)
        {
            float x = segmentWidth * i;
            float y = Mathf.Sin(x * Time.time);
            points[i] = new Vector3(x, y, 0);
        }
        line.SetPositions(points);
    }
}


顺便说一句,我只是假设 GameObject.FindGameObjectsWithTag("PointMarker"); 实际上会重新调整所有到目前为止生成的 linePointPrefab 对象。

当你像

一样生成它们时,最好立即存储它们
private List<Transform> allPoints = new List<Transform>();

...

allPoints.Add(Instantiate(linePointPrefab, pointPosition, Quaternion.identity).transform);

那么你可以完全跳过FindObjectsWithType的用法


为了采用此本地 space 位置也适用于您实例化的线点预制件,只需将它们实例化为 linerenderer 变换的子级或在同一父级下生成它们和 linerenderer,以便相对位置相同。在这种情况下,您不会旋转线性渲染器,而是旋转整个父对象,因此生成的线点会随之旋转