上篇博客给读者介绍了关于曲线编辑器控制点的制作,最后给读者介绍如何使用曲线编辑器。
我们已经用样条做了一段时间了,但是还没有告诉读者如何使用它们。可以用样条做许多事情,例如,移动一个物体的路径,我们来创建一个SplineWalker组件。
using UnityEngine;
public class SplineWalker : MonoBehaviour {
public BezierSpline spline;
public float duration;
private float progress;
private void Update () {
progress += Time.deltaTime / duration;
if (progress > 1f) {
progress = 1f;
}
transform.localPosition = spline.GetPoint(progress);
}
}
现在我们可以创建一个walker对象,分配我们的样条,设置一个持续时间,然后在我们进入播放模式后看它移动。在这里只是用了一个立方体,你可以看到它的方向。
现在它还没有朝向,我们可以为它添加一个选项。
public bool lookForward;
private void Update () {
progress += Time.deltaTime / duration;
if (progress > 1f) {
progress = 1f;
}
Vector3 position = spline.GetPoint(progress);
transform.localPosition = position;
if (lookForward) {
transform.LookAt(position + spline.GetDirection(progress));
}
}
这是一种方法,另一种方法是继续循环,而不是只走一次,当我们在它的时候,我们也可以让立方体来回移动,让我们创建一个枚举来在这些模式之间选择。
public enum SplineWalkerMode {
Once,
Loop,
PingPong
}
现在SplineWalker必须记住它是向前还是向后,它还需要根据其模式在传递样条末端时调整进度。
public SplineWalkerMode mode;
private bool goingForward = true;
private void Update () {
if (goingForward) {
progress += Time.deltaTime / duration;
if (progress > 1f) {
if (mode == SplineWalkerMode.Once) {
progress = 1f;
}
else if (mode == SplineWalkerMode.Loop) {
progress -= 1f;
}
else {
progress = 2f - progress;
goingForward = false;
}
}
}
else {
progress -= Time.deltaTime / duration;
if (progress < 0f) {
progress = -progress;
goingForward = true;
}
}
Vector3 position = spline.GetPoint(progress);
transform.localPosition = position;
if (lookForward) {
transform.LookAt(position + spline.GetDirection(progress));
}
}
我们还可以做的另一件事是创建一个装饰器,它会在样条上实例化一个项目序列,我们也给它一个前瞻性的选项,它适用于它产生的项目。这个项目序列有一定的频率,允许重复。当然,如果频率是零或者没有物体,我们什么都不做。我们需要一些物体,因此也要创建一些prefabs。
using UnityEngine;
public class SplineDecorator : MonoBehaviour {
public BezierSpline spline;
public int frequency;
public bool lookForward;
public Transform[] items;
private void Awake () {
if (frequency <= 0 || items == null || items.Length == 0) {
return;
}
float stepSize = 1f / (frequency * items.Length);
for (int p = 0, f = 0; f < frequency; f++) {
for (int i = 0; i < items.Length; i++, p++) {
Transform item = Instantiate(items[i]) as Transform;
Vector3 position = spline.GetPoint(p * stepSize);
item.transform.localPosition = position;
if (lookForward) {
item.transform.LookAt(position + spline.GetDirection(p * stepSize));
}
item.transform.parent = transform;
}
}
}
}
这对于使用循环很有效,但它不会一直到没有循环的样条的末尾。我们可以通过增加我们的步长来解决这个问题,只要它不是一个循环,而且我们有不止一个项。
if (frequency <= 0 || items == null || items.Length == 0) {
return;
}
float stepSize = frequency * items.Length;
if (spline.Loop || stepSize == 1) {
stepSize = 1f / stepSize;
}
else {
stepSize = 1f / (stepSize - 1);
}
最后,其实还有很多方法可以使用splines,而且还有更多的特性可以添加到splines本身。比如移除曲线,或者将一条曲线分成两个较小的曲线,或者将两条曲线合并在一起。
代码下载地址:链接:http://pan.baidu.com/s/1gfrJVrl 密码:ft1o 中的名字为curves-and-splines-finished的包。