我想让y轴上的对象沿Z轴移动吗?

时间:2018-10-16 01:15:37

标签: c# unity3d velocity rigid-bodies lerp

我目前正在制作一款不是在Unity中随机生成的亚军类型的游戏。播放器,相机和背景保持在同一位置(夹紧了播放器的移动),并且危险通过以下简单的代码行沿负Z轴传向播放器:

public float speed;

private Rigidbody rb;

void Start () {
    rb = GetComponent<Rigidbody> ();
    rb.velocity = transform.forward * -speed;
}

它工作正常。现在,我想添加不仅会朝向玩家的小行星,而且还会使小行星向上和向下移动(并重复),我尝试使用Lerp()进行操作。我不是Lerp的专业人士,因此我使用了在网上找到的有效代码:

public Transform startPos, endPos;
public bool repeatable = true;
public float speed = 1.0f;
public float duration = 3.0f;

float startTime, totalDistance;

IEnumerator Start () {
    startTime = Time.time;

    while(repeatable) {
        yield return RepeatLerp(startPos.position, endPos.position, duration);
        yield return RepeatLerp(endPos.position, startPos.position, duration);
    }
}

void Update () {
    totalDistance = Vector3.Distance(startPos.position, endPos.position);
    if(!repeatable) {
        float currentDuration = (Time.time - startTime) * speed;
        float journeyFraction = currentDuration / totalDistance;
        this.transform.position = Vector3.Lerp(startPos.position, endPos.position, journeyFraction);
    }
}

public IEnumerator RepeatLerp(Vector3 a, Vector3 b, float time) {
    float i = 0.0f;
    float rate = (1.0f / time) * speed;
    while (i < 1.0f) {
        i += Time.deltaTime * rate;
        this.transform.position = Vector3.Lerp(a, b, i);
        yield return null;
    }
}

我所做的是在起点和终点位置创建2个空对象,然后将危险和两个危险点放在另一个空对象下,我们将其称为“父对象”(因此,“父对象”>“-危害-开始-结束”)。然后,我将沿Z轴移动的脚本添加到了父级空白中,这有点奏效,但就像跳跃一样。因此,拉幅有效,但直到完成拉幅功能,对象才沿Z轴移动,对象跳到Z轴的新位置。因此,它看起来非常跳跃和小故障。

我该怎么做,这样才能使沿Z轴的运动平稳,而束带仍沿Y轴工作?

谢谢!

PS:我知道我可以移动角色和照相机等,但是现在我想保持这种方式。

1 个答案:

答案 0 :(得分:0)

协程RepeatLerp在多个帧中起作用,但是接收类型为Vector3的输入。参考点的实际位置会随着时间而改变,但是参数值ab直到协程终止之前都不会改变。

因此,立即解决方案很简单:与其传递Vector3,而是传递对Transform的引用,并在每一帧获取其新位置。将功能更改为此:

public IEnumerator RepeatLerp(Transform a, Transform b, float time)
{
    float i = 0.0f;
    float rate = (1.0f / time) * speed;
    while (i < 1.0f)
    {
        i += Time.deltaTime * rate;
        this.transform.position = Vector3.Lerp(a.position, b.position, i);
        yield return null;
    }
}

Start功能中,调用现在为:

yield return RepeatLerp(startPos, endPos, duration);
yield return RepeatLerp(endPos, startPos, duration);

这将解决您的问题,但是,我强烈建议您重新考虑移动对象的方式。您将Rigidbody语义与使用transform的移动对象混合使用,这是非常糟糕的做法。该引擎并非旨在执行此操作,将来可能会导致性能问题。

通常,如果物体上有碰撞器(看起来像是有碰撞器),则应仅使用Rigidbody并对其施加速度/力来移动物体。如果您想使用Lerp,也许可以看看Rigidbody.MovePosition,但最好使用Rigidbody.velocity,例如(以下代码仅是示意图):

if (transform.position.x > highLimit) rigidbody.velocity -= 2*pulsingSpeed;
if (transform.position.x < lowLimit) rigidbody.velocity += 2*pulsingSpeed;