孙广东 2015.6.28
看了看 Unity的官方案例,就顺便看了 wayPoint相关。
效果:
WaypointProgressTracker.cs 【固定】
WaypointCircuit.cs 【固定】
using System;
using System.Collections;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityStandardAssets.Utility
{
public class WaypointCircuit : MonoBehaviour
{
public WaypointList waypointList = new WaypointList();
[SerializeField] private bool smoothRoute = true;
private int numPoints;
private Vector3[] points;
private float[] distances;
public float editorVisualisationSubsteps = 100;
public float Length { get; private set; }
public Transform[] Waypoints
{
get { return waypointList.items; }
}
// 这是在这里会保存 GC 分配
private int p0n;
private int p1n;
private int p2n;
private int p3n;
private float i;
private Vector3 P0;
private Vector3 P1;
private Vector3 P2;
private Vector3 P3;
// Use this for initialization
private void Awake()
{
if (Waypoints.Length > 1)
{
CachePositionsAndDistances();
}
numPoints = Waypoints.Length;
}
public RoutePoint GetRoutePoint(float dist)
{
// 位置和方向
Vector3 p1 = GetRoutePosition(dist);
Vector3 p2 = GetRoutePosition(dist + 0.1f);
Vector3 delta = p2 - p1;
return new RoutePoint(p1, delta.normalized);
}
public Vector3 GetRoutePosition(float dist)
{
int point = 0;
if (Length == 0)
{
Length = distances[distances.Length - 1];
}
dist = Mathf.Repeat(dist, Length);
while (distances[point] < dist)
{
++point;
}
// get nearest two points, ensuring points wrap-around start & end of circuit
// 得到最近的两个点,确保点环绕电路的开始与结束
p1n = ((point - 1) + numPoints)%numPoints;
p2n = point;
// found point numbers, now find interpolation value between the two middle points
// 发现点的数目,现在找到中间两点之间内的一个插值
i = Mathf.InverseLerp(distances[p1n], distances[p2n], dist);
if (smoothRoute)
{
// 有关两点之间的光滑catmull-rom计算。
// 获取周围的 2 点的指数,因为catmull-rom 函数要求四个点
p0n = ((point - 2) + numPoints)%numPoints;
p3n = (point + 1)%numPoints;
// 第二个点可能已经是最后的 'last' 点了 - a dupe of the first,
// (to give a value of max track distance instead of zero)
// but now it must be wrapped back to zero if that was the case.
p2n = p2n%numPoints;
P0 = points[p0n];
P1 = points[p1n];
P2 = points[p2n];
P3 = points[p3n];
return CatmullRom(P0, P1, P2, P3, i);
}
else
{
// 两个点之间的简单线性插值:
p1n = ((point - 1) + numPoints)%numPoints;
p2n = point;
return Vector3.Lerp(points[p1n], points[p2n], i);
}
}
private Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float i)
{
// 这是 catmull-rom 方程
// Un-magic this, lord vector!
return 0.5f*
((2*p1) + (-p0 + p2)*i + (2*p0 - 5*p1 + 4*p2 - p3)*i*i &