发布时间:2014-10-17 00:00 来源:最终幻想
为了平滑游戏对象在 Unity 中的行进路线,我们经常会在 Unity 中使用 ITweenPath 插件,但有时候我们或许只会使用到通过 ITweenPath 绘制出来的点(比如把这些点放到配置文件中),并不希望加载 ITweenPath 插件或者通过自己的函数去实现游戏对象的移动,通过查看 ITweenPath 的代码,很容易就把 ITweenPath 绘制曲线点的方法给提取出来了,主函数并不多,只有三个方法,希望能给你带来帮助!
先来看看最终的 Demo 实现方式:
Demo 代码:
using UnityEngine; using System.Collections.Generic; public class PointPath : MonoBehaviour { private Vector3[] pathList; public GameObject sphere; public GameObject path; void Awake() { Transform[] transformList = path.GetComponentsInChildren<Transform> (); int length = transformList.Length; pathList = new Vector3[length]; for (int index = 0; index < length; index ++) { pathList[index] = transformList[index].transform.position; } Vector3[] resultList = PointController.PointList (this.pathList, 20); foreach (Vector3 point in resultList) { GameObject gameObject = (GameObject)Instantiate(sphere); gameObject.transform.localPosition = point; gameObject.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); } } }
PointController.cs
using UnityEngine; using System; using System.Collections; public class PointController { /// <summary> /// 获取曲线上面的所有点 /// </summary> /// <returns>The list.</returns> /// <param name="path">需要穿过的点列表</param> /// <param name="pointSize">两个点之间的节点数量</param> public static Vector3[] PointList(Vector3[] path, int pointSize) { Vector3[] controlPointList = PathControlPointGenerator(path); int smoothAmount = path.Length * pointSize; Vector3[] pointList = new Vector3[smoothAmount]; for (int index = 1; index <= smoothAmount; index++) { Vector3 currPt = Interp(controlPointList, (float) index / smoothAmount); pointList[index - 1] = currPt; } return pointList; } /// <summary> /// 获取控制点 /// </summary> /// <returns>The control point generator.</returns> /// <param name="path">Path.</param> private static Vector3[] PathControlPointGenerator(Vector3[] path) { int offset = 2; Vector3[] suppliedPath = path; Vector3[] controlPoint = new Vector3[suppliedPath.Length + offset]; Array.Copy(suppliedPath, 0, controlPoint, 1, suppliedPath.Length); controlPoint[0] = controlPoint[1] + (controlPoint[1] - controlPoint[2]); controlPoint[controlPoint.Length - 1] = controlPoint[controlPoint.Length - 2] + (controlPoint[controlPoint.Length - 2] - controlPoint[controlPoint.Length - 3]); if(controlPoint[1] == controlPoint[controlPoint.Length - 2]) { Vector3[] tmpLoopSpline = new Vector3[controlPoint.Length]; Array.Copy(controlPoint, tmpLoopSpline, controlPoint.Length); tmpLoopSpline[0] = tmpLoopSpline[tmpLoopSpline.Length - 3]; tmpLoopSpline[tmpLoopSpline.Length - 1] = tmpLoopSpline[2]; controlPoint = new Vector3[tmpLoopSpline.Length]; Array.Copy(tmpLoopSpline, controlPoint, tmpLoopSpline.Length); } return(controlPoint); } /// <summary> /// 根据 T 获取曲线上面的点位置 /// </summary> /// <param name="pts">Pts.</param> /// <param name="t">T.</param> private static Vector3 Interp(Vector3[] pts, float t) { int numSections = pts.Length - 3; int currPt = Mathf.Min(Mathf.FloorToInt(t * (float) numSections), numSections - 1); float u = t * (float) numSections - (float) currPt; Vector3 a = pts[currPt]; Vector3 b = pts[currPt + 1]; Vector3 c = pts[currPt + 2]; Vector3 d = pts[currPt + 3]; return .5f * ( (-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b ); } }