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

时间:2019-06-13 15:18:55

标签: c# unity3d math trigonometry spline

this tutorial之后,我试图使用Line Renderer组件从A点到B点绘制一个正弦波。我正在使用输入的鼠标位置。但是到目前为止,我所做的工作没有用,它只是沿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);
}

1 个答案:

答案 0 :(得分:2)

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

lineRenderer.useWorlsSpace = false;

因此,相对于线性渲染器变换,不再在世界空间中设置点,而是在局部空间中设置点。

现在,您只需旋转线性渲染器变换以指向最新的用户输入位置即可。

我无法使用您的代码示例,因为我不知道您的预制件是什么,因此我根据给定Video中的代码创建了自己的预制件。我希望您可以重复使用/重新创建必要的部分

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

enter image description here


顺便说一句,我只是在这里假设GameObject.FindGameObjectsWithTag("PointMarker");实际上重新调整了所有迄今为止产生的linePointPrefab对象。

最好在生成它们时立即存储它们

private List<Transform> allPoints = new List<Transform>();

...

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

然后您可以完全跳过FindObjectsWithType的使用


要在线点预制件上也采用此局部空间位置,只需实例化它们即可作为线性渲染器转换的​​子对象实例化,或将它们与线性渲染器生成在同一父对象下,以便相对位置相同。在这种情况下,您将不会旋转线性渲染器,而是旋转整个父对象,因此生成的线点会随之旋转