뭐 ㅈ도 없긴한데 그래도 혹시 쓸사람 있을까봐 올려봄 ㅇㅇ 16차까지 지원함


이건 시연 링크




소스코드


using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

namespace RPG.Utility{
public class BezierDebugger : MonoBehaviour
  {
    [SerializeField]
    private GameObject gameObject;


    // 시점 t
    [Range(0, 1)]
    [SerializeField]
    private float t;

    public List<Vector3> vectors;

    // 16!까지 팩토리얼 미리계산 팩토리얼은 계산비용이 비싸고 15~16차 이상으로 베지어함수가 가는 경우는
    // 비용문제도있고 그렇게까지 복잡한 곡선이 필요한 경우가 거의 없기때문에 미리 상수로 계산해도 문제 없을듯?
    private float[] factorial = new float[]
  {
        1.0f,
        1.0f,
        2.0f,
        6.0f,
        24.0f,
        120.0f,
        720.0f,
        5040.0f,
        40320.0f,
        362880.0f,
        3628800.0f,
        39916800.0f,
        479001600.0f,
        6227020800.0f,
        87178291200.0f,
        1307674368000.0f,
        20922789888000.0f,
  };

    // n차 베지어 함수 구현에 필요한 이항계수 구현함수
    private float Binomial(int n, int i)
    {
      float ni;
      float a1 = factorial[n];
      float a2 = factorial[i];
      float a3 = factorial[n - i];
      ni = a1 / (a2 * a3);
      return ni;
    }

    // 번스타인 함수 고닥교땐가 배웟던 이항계수가 앞에 붙은 형태의 함수인듯?
    private float Bernstein(int n, int i, float t)
    {
      float t_i = Mathf.Pow(t, i);
      float t_n_minus_i = Mathf.Pow((1 - t), (n - i));

      float basis = Binomial(n, i) * t_i * t_n_minus_i;
      return basis;
    }

    // 제어점들이 주어져있을때 시점 t에서의 베지어 곡선의 위치
    public Vector3 Point3(float t, List<Vector3> controlPoints)
    {
      int N = controlPoints.Count - 1;
      if (N > 16)
      {
        Debug.Log("You have used more than 16 control points. The maximum control points allowed is 16.");
        controlPoints.RemoveRange(16, controlPoints.Count - 16);
      }
      if (t <= 0) return controlPoints[0];
      if (t >= 1) return controlPoints[controlPoints.Count - 1];

      Vector3 p = new Vector3();

      for (int i = 0; i < controlPoints.Count; ++i)
      {
        Vector3 bn = Bernstein(N, i, t) * controlPoints[i];
        p += bn;
      }

      return p;
    }

    public List<Vector3> PointList3(List<Vector3> controlPoints, float interval = 0.01f){

        int n = controlPoints.Count -1;
        if (n > 16){
            Debug.Log("16차 이상은 지원하지 않습니다");
            controlPoints.RemoveRange(16, controlPoints.Count - 16);
        }

        List<Vector3> points = new List<Vector3>();
        for (float t = 0.0f; t <= 1.0f + interval - 0.0001f; t += interval)
        {
            Vector3 p = new Vector3();
            for (int i = 0; i < controlPoints.Count; ++i)
            {
            Vector3 bn = Bernstein(n, i, t) * controlPoints[i];
            p += bn;
            }
            points.Add(p);
        }

        return points;
    }
  }

  [CanEditMultipleObjects]
  [CustomEditor(typeof(BezierDebugger))]
  public class BezierDebuggerEditor : Editor{

    private void OnSceneGUI() {

        BezierDebugger generator = (BezierDebugger)target;

        for (int i = 0; i < generator.vectors.Count; i++){
            generator.vectors[i] = Handles.PositionHandle(generator.vectors[i], Quaternion.identity);
        }

        for (float i = 0; i < 100; i++){

            float value_before = i / 10;
            Vector3 before = generator.Point3(value_before, generator.vectors);

            float value_after = (i + 1) / 10;
            Vector3 after = generator.Point3(value_after, generator.vectors);

            Handles.DrawLine(before, after);
        }
    }

  }
}




레퍼런스


https://www.youtube.com/watch?v=KTEX2L4T4zE&t=0s

https://faramira.com/implement-bezier-curve-using-csharp-in-unity/

https://blog.naver.com/PostView.naver?blogId=kyuniitale&logNo=40022945907&redirect=Dlog&widgetTypeCall=true&directAccess=false