0

我制作了一个简单的脚本,它先到一个航点,然后再到下一个。

我的问题是,从 waypoint1 到 waypoint2 似乎有延迟,我不知道为什么: 在此处输入图像描述

¿ 为什么会发生这种延迟,我该如何消除它?

using UnityEngine;
using System.Collections;

public class Missile : MonoBehaviour
{
 public Vector3 finalTarget;
 public Transform forwardObject;

 public GameObject impactAreaPrefab;

 float smoothingDelay = 0.1f;
 bool fired = false;
 bool powerPhase = true;
 Vector3 currentTarget;

 private void OnEnable() {
     fire(new Vector3(-25.29f, 0.5f, -10.638f));
 }

 void fire(Vector3 coords) {
     currentTarget = forwardObject.position;
     finalTarget = coords;
     Instantiate(impactAreaPrefab, finalTarget, Quaternion.identity);
     fired = true;
 }

 void Update() {
     if (!fired) {
         return;
     }

     if (powerPhase && transform.position == currentTarget) {
         powerPhase = false;
         currentTarget = finalTarget;
         smoothingDelay = 0.05f;
     }

     transform.position = Vector3.Lerp(transform.position, currentTarget, Time.deltaTime / smoothingDelay);
     transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(Vector3.RotateTowards(transform.forward, currentTarget, 1, 0.0f)), Time.deltaTime / smoothingDelay);
 }
 }
4

3 回答 3

2

正在发生这种情况,因为您使用的 lerp 并不完全正确。如果你想获得线性运动,你应该缓存你的第一个参数(开始时的位置/旋转)并提供增加的第三个参数。发生这种延迟是因为如果您的子弹非常接近最终位置并且它仍在尝试到达那里,但是您当前的距离 |finalPos - transform.position| 是如此之小,以至于您的步骤 Time.deltaTime/smoothingDelay 几乎没有移动它。

Vector3 startPos;
Vector3 finalPos;
float currentT = 0.0f;

void Update()
{
    currentT += Time.deltaTime;
    transform.position = Vector3.Lerp(startPos, finalPos, currentT);
}

检查 Vector3 == Vector3 是否也不是一个好主意。使用上面的模式并检查 currentT 是否大于或等于 1。如果它是真的,那么你就在最终位置。您还可以通过划分 currentT 来控制运动持续时间。

于 2018-12-24T22:23:06.297 回答
1

所以首先阅读这些帖子以更好地理解 Lerp 功能 - https://chicounity3d.wordpress.com/2014/05/23/how-to-lerp-like-a-pro/ http://www.kinematicsoup。 com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8

您现在应该对 lerp 有了更好的了解。总之,lerp 做了一件非常简单的事情。假设你有两个值 X 和 Y。对于这个例子,让我们给它们一些值,X = 0,Y = 1,现在你想得到它们之间的某个百分比的值,比如你想得到一个 50% 的值从 X 和 Y。你可以猜到答案是 0.5。对此的 lerp 方程将是

Mathf.Lerp(0, 1, 0.5f);

如此简单——给定两个值,x 和 y,Mathf.Lerp 返回一个值,它们之间的百分比为 t。

现在要正确使用 Lerp,您需要在启动 lerp 之前缓存位置。大多数时候我使用协程来获得这个效果非常好,然后你可以使用动画曲线来改变第三个参数来创造一些疯狂的好效果。例如,在使用动画曲线时,只需评论我会写它。

对于您的这个问题,您有两个选择-

1)像专业人士一样使用动画曲线来操纵速度。请记住,您也可以在运行时创建动画曲线。

IENumerator Move(Transform toMove, Vector3 end, float duration){
    Vector3 startPos = toMove.position;
    float elapsed = 0f;
    while(elapsed < duration){
        elapsed += Time.deltaTime;
        toMove.position = Vector3.Lerp(startPos, end, elapsed / duration);//manipulate the last parameter to move the object linearly
        yield return null;//basically wait for next frame
    }
    toMove.position = end;//after lerp ends
}

现在您可以使用速度代替持续时间,然后用它计算所需的时间并更改速度以使其更快

float distance = Vector3.Distance(startPos, end);
toMove.position = Vector3.Lerp(startPos, end, elapsed / (distance/(speed * multiplier)));

2) 使用 Vector3.MoveTowards - 这个函数以给定的最大步长将一个点移动到一个端点,需要三个参数,(currentPosition, end, step),你可以将步长与变量相乘来控制速度,两者都很好用。在大多数情况下使用它要容易得多示例-

float step = speed * Time.deltaTime;//to make it framerate independent
transform.position = Vector3.MoveTowards(transform.position, end, step * multiplier);

希望这可以帮助。很抱歉我无法正确格式化我的答案,希望能更好地回答。欢迎进行任何修改以改进答案:)

于 2018-12-26T13:16:08.060 回答
0

我建议使用 iTween 进行平滑移动。

我在某个时候修改了 iTween,以便能够做任何我想做的事情。像这样:

    public static void Rotate (Transform transform, Vector3 target, float transitionTime, Action onEnd = null, bool ignoreTimescale = false, iTween.EaseType ease = iTween.EaseType.easeInOutQuad, float delay = 0)
    {
        Vector3 from, to;

        from = transform.localEulerAngles;
        to = target;

        Action <object> onUpdateAction = (rotation => 
        {
            transform.localEulerAngles = (Vector3) rotation;
        });

        Action <object> onCompleteAction = (data => 
        {
            if (onEnd != null)
                onEnd ();
        });

        Hashtable hash = new Hashtable ();
        hash.Add ("from", from);
        hash.Add ("to", to);
        hash.Add ("time", transitionTime);
        hash.Add ("delay", delay);
        hash.Add ("easetype", iTween.EaseType.easeInOutQuad);
        hash.Add ("ignoretimescale", ignoreTimescale);
        hash.Add ("onupdate", onUpdateAction);
        hash.Add ("oncomplete", onCompleteAction);

        iTween.ValueTo (transform.gameObject, hash);
    }

这使我可以在各种情况下完全控制。

如果你想实现它,这里是代码。

https://drive.google.com/open?id=1nLEEYTp-q4Kfh2n3nWQJcMXmPNtVPLLP

于 2018-12-25T00:00:07.030 回答