【问题标题】:I want an Object lerping in the y-axis to move along the Z-Axis?我想要一个在 y 轴上弯曲的物体沿 Z 轴移动?
【发布时间】:2018-10-16 01:15:36
【问题描述】:

我目前正在 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 个空对象,然后我将危险和两个 lerping 点放在另一个空对象下,我们称之为父对象(所以父对象 > -危险 - 开始 - 结束)。然后我将沿 Z 轴的移动脚本添加到空的父级,它有点工作,但就像跳跃一样。所以 lerping 工作,但它不会沿着 Z 轴移动,直到 lerping 功能完成,对象跳转到 Z 轴上的新位置。所以它看起来非常跳跃和小故障。

我该怎么做才能沿着 Z 轴平滑移动,而 lerp 仍然沿着 Y 轴工作?

谢谢!!

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

【问题讨论】:

  • 问题被标记为您的接受答案得到了满意的回答(正如您在此处所做的那样)。不要在标题中编辑某些内容。

标签: c# unity3d velocity rigid-bodies lerp


【解决方案1】:

协程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;

【讨论】:

  • 非常感谢!它确实奏效了。但我会听从你的建议,用刚体移动我的对象
猜你喜欢
  • 2019-12-11
  • 2020-11-09
  • 2022-01-18
  • 2020-11-19
  • 2016-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多