LineRender에서 만든 다이어그램 애니메이션

14876 단어 Unity
LineRendererPositions 이 배열에서 여러 점을 지정하면 최초의 것부터 순서대로 선을 연결하여 표시하는 구성 요소입니다.
한편, Vector3.Lerp 은 두 점 사이에 선형 삽입값을 하는 함수이다.
https://docs.unity3d.com/ja/current/ScriptReference/Vector3.Lerp.html
Line Render에서 그래프를 애니메이션으로 만들려면 고려해야 할 점이 2시라면 Lerp로 포지션을 만지작거리면 애니메이션이 되지만 3시 이상이면 그 구성 요소를 직접 만드는 것이 좋기 때문에 만들기로 했습니다.
결국 이런 느낌이었어.

여러 점 기반 Lerp


여러 점을 뛰어넘을 수 있는 Lerp 같은 것을 실현합니다.먼저 모든 점 간의 거리 목록을 작성하여 0.0~1.0의 값을 바탕으로 점이 어느 선분에 속하는지 구한 다음에 이 선분에 Lerp를 설치합니다.
바로 코드 전문입니다.
LineRendererProgressor.cs
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

[ExecuteInEditMode]
[RequireComponent(typeof(LineRenderer))]
public class LineRendererProgressor : MonoBehaviour
{
    private LineRenderer LineRenderer
    {
        get
        {
            if (lineRenderer) return lineRenderer;
            return lineRenderer = GetComponent<LineRenderer>();
        }
    }
    private LineRenderer lineRenderer;

    [SerializeField] private Vector3[] positions;

    public float Progress
    {
        get => progress;
        set { 
            progress = value;

            if (positions == null || positions.Length == 0) return;
            UpdateLineRenderer();
        }
    }
    [SerializeField] private float progress;

    private void OnValidate()
    {
        if (positions == null || positions.Length == 0) return;
        UpdateLineRenderer();
    }

    private void UpdateLineRenderer()
    {
        // 値の制限と終了判定
        progress = Mathf.Clamp01(progress);
        if (positions.Length == 1 || progress <= 0.0f)
        {
            LineRenderer.positionCount = 1;
            LineRenderer.SetPosition(0, positions[0]);
            return;
        }
        if (progress >= 1.0f)
        {
            LineRenderer.positionCount = positions.Length;
            LineRenderer.SetPositions(positions);
            return;
        }

        // 距離リストと合計
        var distanceList = MakeDistanceList(positions);
        var totalDistance = distanceList.Sum();

        // 現在どの線分にあるか取得
        var distanceCompleted = totalDistance * progress;
        var currentIndex = GetIndexByDistanceCompleted(positions,
                                 distanceList, distanceCompleted);

        // 先端位置を計算
        var distanceArrayToCurIdx = distanceList.Take(currentIndex);
        var completedDistInCurSeg = distanceCompleted - distanceArrayToCurIdx.Sum();
        var currentSegLength = distanceList[currentIndex];
        var t = completedDistInCurSeg / currentSegLength;
        var edgePos = Vector3.Lerp(positions[currentIndex], positions[currentIndex + 1], t);

        // 更新
        LineRenderer.positionCount = currentIndex + 2;

        for (var i = 0; i < currentIndex + 2; ++i)
        {
            LineRenderer.SetPosition(i, i > currentIndex ? edgePos : positions[i]);
        }
    }

    private IReadOnlyList<float> MakeDistanceList(Vector3[] points)
    {
        var distanceList = new List<float>();
        for (var i = 0; i < points.Length - 1; ++i)
        {
            distanceList.Add(Vector3.Distance(points[i], points[i + 1]));
        }

        return distanceList;
    }

    private int GetIndexByDistanceCompleted(Vector3[] points, IReadOnlyList<float> distanceList, float distanceCompleted)
    {
        var distanceProcessed = 0f;
        for (var i = 0; i < points.Length - 1; ++i)
        {
            if (distanceList[i] + distanceProcessed > distanceCompleted)
            {
                return i;
            }

            distanceProcessed += distanceList[i];
        }

        return points.Length - 1;
    }
}

기본적으로 평론 중의 일만 하면 간단하다.수학 능력이 있으면 더 영리한 설치가 있을 수 있지만 제가 없어서 포기했는데...
세그먼트의 길이가 자주 사용되기 때문에 목록에 저장합니다.
또한 첨단 위치의 계산을 준비했던 Lerp에서 그곳만 되돌아오는 Multi Lerp 같은 함수를 정의하면 다른 클래스도 사용할 수 있다.그러나 이런 상황에서 Multi Lerp에서 진행된 것과 같은 계산은 다시 Update Line Render에서 해야 한다는 것이 미묘할 수 있기 때문에 이번에는 모두 Update Line Render에 넣었다.

좋은 웹페이지 즐겨찾기