0

我正在尝试基于计时器在两个对象之间创建一个目标 lerp。

目前,我有以下代码:

   float distCovered = (Time.time - waitTime) * speed;
    float fracJourney = distCovered / journeyLength;
    if (_moveDown == false)
    {
        if (startTime + waitTime < Time.time)
        {

            transform.position = Vector3.Lerp(start.position, end.position, fracJourney);

            if (transform.position == end.position)
            {
                Debug.Log("going down");
               _moveDown = true;

                transform.position = Vector3.Lerp(end.position, start.position, fracJourney);
            }


        }
    }

    if (_moveDown == true)
    {
        float distCovered1 = (Time.time - goDowntimer) * speed;
        float fracJourney1 = distCovered1 / journeyLength;
        transform.position = Vector3.Lerp(end.position, start.position, fracJourney1);

        if (transform.position == start.position)
        {
            Debug.Log("going up");
           // waitTime = 20;
            _moveDown = false;

        }

    }

此代码在我的更新函数中,并附加到我要上下移动的每个对象。每个对象都可以独立于其他对象设置它们的等待时间,因此我可以在 5 秒后移动 1 次,在 10 秒后移动一次,以此类推。

然后,每个目标等待几秒钟,然后向下移动。但是,运动并不顺畅,而且往往会跳跃一段设定的距离。但是,当它回到底部时,它会在 _movedown 布尔值之间变得疯狂并且不会移动。

有谁知道我可以解决这些问题的方法?

我知道 Mathf.PingPong 方法会不断地在两点之间来回移动对象,但这不允许我在每个部分暂停移动。不过,如果有人知道我可以做到这一点的方法,也请告诉我。

4

3 回答 3

1

这是对代码的快速破解。它可能更清洁,但它应该在紧要关头做。我已经用“方向”变量替换了 OPs if/then 块,该变量指示我们是从开始移动到结束还是从结束移动到开始。

Vector3.Lerp () 采用 [0,1] 范围内的t值,名义上是从起点到终点的 % 距离。如果您想反转该方向,您需要做的就是从 1 中减去,以便范围变为 [1,0](反转方向)。这就是我在下面使用direction_所做的一切。一旦 fracJourney 超出范围,我们就会切换方向、触发暂停并重置主计时器。

我将暂停代码放在Update () 中以将其与移动代码分开,但没有任何理由两个代码块都不能在FixedUpdate () 或Update () 中。

此示例是Vector3.Lerp 文档中的示例的修改版本:

// additional data members beyond Vector3.Lerp's documentation
public float PauseTime = 2.0f;
int direction_ = 1;
bool doPause_ = false;

void Update(){
    float elapsedTime = Time.time - startTime;

    //  if the elapsed time has exceeded the pause time and we're paused
    //  unpause and reset the startTime;
    if(elapsedTime > PauseTime && doPause_){
        doPause_ = false;
        startTime = Time.time;
    }
}
void FixedUpdate(){
    if(doPause_)return;

    float distCovered = (Time.time - startTime) * Speed;
    float fracJourney = distCovered / journeyLength;

    // +direction means we are going from [0,1], -direction means [1,0]
    fracJourney = (direction_>0)?fracJourney:1.0f-fracJourney;
    transform.position = Vector3.Lerp(StartPt.position, EndPt.position, fracJourney);

    // When fracJourney is not in [0,1], flip direction and pause
    if(fracJourney > 1.0 || fracJourney < 0.0){
        direction_ = -direction_;
        startTime = Time.time;
        doPause_ = true;
    }
}

我的“方向”成员也可以很容易地成为布尔值,但我喜欢为其他目的签署方向。

于 2013-03-28T18:35:33.513 回答
0

我在下面添加了一些评论,可以帮助您澄清您的意图。

float distCovered = (Time.time - waitTime) * speed;
float fracJourney = distCovered / journeyLength;

// Going up...
if (_moveDown == false)
{
    // Should we be checking this in the other half of the statement too?
    // Or, outside the conditional altogether?
    if (startTime + waitTime < Time.time)
    {
        transform.position = Vector3.Lerp(start.position, end.position, fracJourney);

        if (transform.position == end.position)
        {
            Debug.Log("going down");

           // The way this is structured, we're going to *immediately* fall into the
           // following block, even if that's not your intended behavior.
           _moveDown = true;

            // Going down, but with the fracJourney value as though we were going up?
            transform.position = Vector3.Lerp(end.position, start.position, fracJourney);
        }
    }
}

// As noted above, we're going to fall directly into this block on the current pass,
// since there's no *else* to differentiate them.
if (_moveDown == true)
{
    // Doesn't follow the same pattern as in the previous block, though that may be intended
    float distCovered1 = (Time.time - goDowntimer) * speed;
    float fracJourney1 = distCovered1 / journeyLength;
    transform.position = Vector3.Lerp(end.position, start.position, fracJourney1);

    if (transform.position == start.position)
    {
        Debug.Log("going up");
       // waitTime = 20;
        _moveDown = false;

       // Should there be a Lerp here, as above, to start heading back the other way again?  Or, do you need to remove the other one?
    }
}
于 2013-03-28T15:18:57.727 回答
0

尝试这个 :

transform.position = Vector3.Lerp(start.position, end.position, fracJourney * Time.deltaTime);

甚至可能是这样:

transform.position = Vector3.Lerp(start.position, end.position, speed * Time.deltaTime);

x *Time.deltaTime 在这种情况下基本上是指示移动方法以每秒 x 米的速度移动对象。如果没有 deltaTime,它会以每帧 x 米的速度执行这些运动。

于 2013-03-28T15:15:10.727 回答