消除之间的延迟

时间:2018-12-24 18:45:13

标签: unity3d lerp

我制作了一个简单的脚本,该脚本先到达一个路标,然后到达下一个路标。

我的问题是从waypoint1到waypoint2似乎有点延迟,我不知道为什么: enter image description here

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

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);
 }
 }

3 个答案:

答案 0 :(得分:3)

这种情况正在发生,因为您使用的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。如果为true,则您处于最终位置。通过除以currentT,您还可以控制运动持续时间。

答案 1 :(得分: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),您可以将step与变量相乘以控制速度,两者均有效真的很好 在大多数情况下,使用它会容易得多 示例-

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

希望这会有所帮助。抱歉,我无法正确设置答案的格式,希望答案会更好。欢迎进行任何改进答案的修改:)

答案 2 :(得分: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