简体   繁体   English

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

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

Following this tutorial , I'm trying to use Line Renderer component to draw a sine wave from point A to B.I'm using the input mouse position. 本教程之后 ,我尝试使用Line Renderer组件从A点到B点绘制正弦波。我使用输入鼠标的位置。 However what I did so far is not working, it just draw the sine wave along the x axis, I need to draw it from the start point to the input mouse position. 但是到目前为止,我所做的工作没有用,它只是沿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);
}

As an alternative I would suggest to instead use 作为替代方案,我建议改为使用

lineRenderer.useWorlsSpace = false;

so the points are no longer set in worldspace but in the local space relative to the linerenderer transform. 因此,相对于线性渲染器变换,这些点不再在世界空间中设置,而是在局部空间中设置。

Now you can simply rotate the linerenderer transform to point towards the latest user input position. 现在,您可以简单地旋转线性渲染器变换以指向最新的用户输入位置。

I couldn't use your code example since I don't know what your prefabs are and do so I created my own from the code in the given Video. 我无法使用您的代码示例,因为我不知道您的预制件是什么,因此我根据给定视频中的代码创建了自己的预制件。 I hope you can reuse/recreate the parts necessary 我希望您可以重用/重建必要的零件

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

在此处输入图片说明


Btw I just assume here that GameObject.FindGameObjectsWithTag("PointMarker"); 顺便说一句,我只是在这里假设GameObject.FindGameObjectsWithTag("PointMarker"); actually retuns all the so far spawned linePointPrefab objects. 实际重新调整所有迄今为止产生的linePointPrefab对象。

It would be better to store them right away when you spawn them like 当您像生成它们一样立即存储它们会更好

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

...

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

then you can skip the usage of FindObjectsWithType completely 那么您可以完全跳过FindObjectsWithType的用法


For adopting this local space position also for the line point prefabs you instantiate simply instantiate them as child of the linerenderer transform or spawn them and the linerenderer under the same parent so the relative positions are the same. 为了在线点预制件上也采用此局部空间位置,您只需实例化即可将它们实例化为线性渲染器转换的​​子对象,或将它们和线性渲染器生成在同一父对象下,因此相对位置相同。 In this case you wouldn't rotate the linerenderer but the entire parent object so the spawned linepoints are rotated along with it 在这种情况下,您将不会旋转线性渲染器,而是旋转整个父对象,因此生成的线点会随之旋转

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM