using UnityEngine; /// <summary> /// 拉格朗日曲线插值类 /// </summary> public sealed class LagrangeCurve { /// <summary> /// 拉格朗日曲线插值算法 /// </summary> /// <param name="points">型值点</param> /// <param name="t">插值参数,取值范围[0,1]</param> /// <returns></returns> public static Vector3 Lerp(Vector3[] points, float t) { //--参数有效性检测-- if (t < 0) t = 0; if (t > 1) t = 1; if (points == null || points.Length == 0) return Vector3.zero; if (points.Length == 1) return points[0]; //--End-- //直接返回起始点 if (t <= 0) return points[0]; //直接返回终点 if (t >= 1) return points[points.Length-1]; Vector3 result = Vector3.zero; //路径总长度 float s = 0; //存放每个型值点所在位置的路径长度 float[] lengths = new float[points.Length]; lengths[0] = 0; for (int i = 1; i < points.Length; i++) { float d = Vector3.Distance(points[i - 1], points[i]); s += d; lengths[i] = s; } //计算线性插值距离 float l = s * t; //临时变量 float x=0, y=0, z=0; int count = points.Length; //算法实现 for (int i = 0; i < count; i++) { Vector3 p = points[i]; x = p.x; y = p.y; z = p.z; //型值点的值与混合函数值相乘 for (int j = 0; j < count; j++) { if (i == j) continue; float ti = lengths[i]; float tj = lengths[j]; t = (l - tj) / (ti - tj); x *= t; y *= t; z *= t; } //线性组合 result.x += x; result.y += y; result.z += z; } return result; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LagrangeCurveTest : MonoBehaviour { [SerializeField] private List<Transform> transforms = new List<Transform>(); private Vector3[] points; private void Update() { points = new Vector3[transforms.Count]; for (int i = 0; i < transforms.Count; i++) { points[i] = transforms[i].position; } float step = 0.01f; float t = 0f; while(t < 1) { Vector3 v0 = LagrangeCurve.Lerp(points, t); t += step; Vector3 v1 = LagrangeCurve.Lerp(points, t); Debug.DrawLine(v0, v1, Color.red); } } }