Как нарисовать синусоидальную волну с помощью рендера линии из точки А в точку Б - PullRequest
0 голосов
/ 13 июня 2019

После этого урока я пытаюсь использовать компонент 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 Ответ

2 голосов
/ 13 июня 2019

В качестве альтернативы я бы предложил вместо этого использовать

lineRenderer.useWorlsSpace = false;

, чтобы точки больше не устанавливались в мировом пространстве, а в локальном пространстве относительно преобразования linerenderer.

Теперь вы можетепросто поверните преобразование linerenderer, чтобы указать на последнюю позицию пользовательского ввода.

Я не мог использовать ваш пример кода, так как я не знаю, какие у вас префабы, и поэтому я создал свой собственный изкод в данном видео.Я надеюсь, что вы можете повторно использовать / воссоздать необходимые детали

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полностью


Для принятия этой позиции локального пространства также для префабов точки строки, которые вы создаете, просто создайте их как дочерние элементы преобразования linerenderer или порождайте их и linerenderer под тем же родителем, чтобы относительные позиции были одинаковыми,В этом случае вы бы не поворачивали linerenderer, а весь родительский объект, поэтому порожденные точки линии вращаются вместе с ним

...