如何使用线渲染器从A点到B点绘制正弦波 [英] How to draw a sine wave using line renderer from point A to point B

查看:81
本文介绍了如何使用线渲染器从A点到B点绘制正弦波的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照


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

当您像这样生成它们时,最好立即存储它们

 私有列表<转换>allPoints = new List< Transform>();...allPoints.Add(Instantiate(linePointPrefab,pointPosition,Quaternion.identity).transform); 

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


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

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. 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.

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"); actually retuns all the so far spawned linePointPrefab objects.

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


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

这篇关于如何使用线渲染器从A点到B点绘制正弦波的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆