我想要一个对象在 y 轴上 lerping 以沿 Z 轴移动?
I want an Object lerping in the y-axis to move along the Z-Axis?
我目前正在制作一款跑酷类游戏,不是在 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 点放在另一个空对象下,我们称之为父对象(所以父对象 > -Hazard -Start - End)。然后我将沿 Z 轴的移动脚本添加到父空,它有点工作,但就像跳跃一样。所以 lerping 有效,但它不会沿着 Z 轴移动,直到 lerping 函数完成,对象跳到 Z 轴中的新位置。所以它看起来非常跳跃和故障。
我该怎么做才能沿着 Z 轴平滑移动并且 lerp 仍然沿着 Y 轴工作?
谢谢!!
PS:我知道我可以移动角色和相机等,但现在我想保持这种状态。
协程 RepeatLerp
跨多个帧运行,但接收类型 Vector3
的输入。参考点的实际位置会随时间改变,但参数值 a
和 b
在协程终止之前不会改变。
所以 立即 解决方案很简单:不是传递 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;
我目前正在制作一款跑酷类游戏,不是在 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 点放在另一个空对象下,我们称之为父对象(所以父对象 > -Hazard -Start - End)。然后我将沿 Z 轴的移动脚本添加到父空,它有点工作,但就像跳跃一样。所以 lerping 有效,但它不会沿着 Z 轴移动,直到 lerping 函数完成,对象跳到 Z 轴中的新位置。所以它看起来非常跳跃和故障。
我该怎么做才能沿着 Z 轴平滑移动并且 lerp 仍然沿着 Y 轴工作?
谢谢!!
PS:我知道我可以移动角色和相机等,但现在我想保持这种状态。
协程 RepeatLerp
跨多个帧运行,但接收类型 Vector3
的输入。参考点的实际位置会随时间改变,但参数值 a
和 b
在协程终止之前不会改变。
所以 立即 解决方案很简单:不是传递 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;