來自《遊戲程式設計精粹1》尋路部分文章,使用CatmullRom插值來達到平滑,算是對書中内容的練習。
在尋路上經常會用到此功能。
using UnityEngine;
using System.Collections;
public class Practice : MonoBehaviour
{
public Transform[] points;
void OnDrawGizmos()
{
//DrawSegmentPath();
DrawSmoothPath();
}
void DrawSegmentPath()
{
for (int i = 1, j = 0; i < points.Length; i++, j++)
{
var a = points[i];
var b = points[j];
Gizmos.DrawLine(a.position, b.position);
}
}
void DrawSmoothPath()
{
for (int i = 3; i < points.Length; i++)
{
var a = points[i - 3];
var b = points[i - 2];
var c = points[i - 1];
var d = points[i];
DrawCurve(a.position, b.position, c.position, d.position);
}
var fixA = points[0];
var fixB = points[1];
var fixC = points[2];
var diff = fixB.position - fixA.position;
var fill = fixA.position + diff.normalized * diff.magnitude;
DrawCurve(fill, fixA.position, fixB.position, fixC.position);
fixA = points[points.Length - 3];
fixB = points[points.Length - 2];
fixC = points[points.Length - 1];
diff = fixC.position - fixB.position;
fill = fixC.position + diff.normalized * diff.magnitude;
DrawCurve(fixA.position, fixB.position, fixC.position, fill);
}
void DrawCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
for (float i = 1, j = 0, iMax = 20f; i <= iMax; i++, j++)
{
var t1 = i / iMax;
var t2 = j / iMax;
var tempP0 = CatmullRom(p0, p1, p2, p3, t1);
var tempP1 = CatmullRom(p0, p1, p2, p3, t2);
Gizmos.DrawLine(tempP0, tempP1);
}
}
Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float u)
{
var r = p0 * (-0.5f * u * u * u + u * u - 0.5f * u) +
p1 * (1.5f * u * u * u + -2.5f * u * u + 1f) +
p2 * (-1.5f * u * u * u + 2f * u * u + 0.5f * u) +
p3 * (0.5f * u * u * u - 0.5f * u * u);
return r;
}
}