平滑将物体旋转朝向目标物体

5

我想将我的玩家车辆旋转到目标物体的方向/侧面。 通过以下图像,我试图更好地解释我的观点:

enter image description here

我想将我的坦克对象朝向另一个坦克对象旋转,以便它可以指向该方向。

我为此编写了以下代码,但它没有起作用:

IEnumerator DoRotationAtTargetDirection(Transform opponentPlayer)
{
    Quaternion targetRotation = Quaternion.identity;
    do
    {
        Debug.Log("do rotation");
        Vector3 targetDirection = opponentPlayer.position - transform.position;
        targetRotation = Quaternion.LookRotation(targetDirection);
        Quaternion nextRotation = Quaternion.Lerp(transform.localRotation, targetRotation, Time.deltaTime);
        transform.localRotation = nextRotation;
        yield return null;

    } while (Quaternion.Angle(transform.localRotation, targetRotation) < 0.01f);
}

我只想顺畅地旋转并停止在目标物体上。 请分享你对此的建议。
编辑: 以下是更新过的代码,但仍然无法正常工作,坦克对象会像上面的图像一样卡在旋转状态中:
 IEnumerator DoRotationAtTargetDirection(Transform opponentPlayer)
{
    Quaternion targetRotation = Quaternion.identity;
    do
    {
        Debug.Log("do rotation");

        Vector3 targetDirection = (opponentPlayer.position - transform.position).normalized;
        targetRotation = Quaternion.LookRotation(targetDirection);
        transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, Time.deltaTime);

        yield return null;

    } while (Quaternion.Angle(transform.rotation, targetRotation) < 0.01f);
}

坦克对象前进方向:

enter image description here


1
与其完全旋转到目标对象,它只是像上面的图像一样停止了。 - Siddharth
由于您的编辑,这已成为一个非常高质量的问题! - Ruzihm
1个回答

2
Time.deltaTime不是一个合适的lerp参数。相反,定义一个float rotationSpeed,并使用rotationSpeed * Time.deltaTime作为maxDegreesDelta参数传递给Quaternion.RotateTowards
此外,以这种方式使用LookRotation将会给你一个世界空间旋转。因此,应该将结果分配给transform.rotation而不是transform.localRotation
总体而言,这些更改可能如下所示:
public float rotationSpeed;

IEnumerator DoRotationAtTargetDirection(Transform opponentPlayer)
{
    Quaternion targetRotation = Quaternion.identity;
    do
    {
        Debug.Log("do rotation");
        Vector3 targetDirection = opponentPlayer.position - transform.position;
        targetRotation = Quaternion.LookRotation(targetDirection);
        Quaternion nextRotation = Quaternion.RotateTowards(
                transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
        transform.rotation = nextRotation;
        yield return null;

    } while (Quaternion.Angle(transform.rotation, targetRotation) > 0.01f);
}

请检查我的更新代码,它仍然无法工作,我已将localRotation更改为normal rotation - 另外,无论我们是否乘以Time.deltaTime都没有关系,因为我已经为此目的编写了完整的枚举器,尽管这可能需要更长的时间。 - Siddharth
仅使用 Time.deltaTime 相当于将 rotationSpeed = 1f,所以没问题 :) 我会继续研究为什么问题还没有解决。 - Ruzihm
@Siddharth 我意识到 while 语句应该是当它大于 0.01f 时。如果这样修复了问题,请告诉我。 - Ruzihm
1
哦,你真是个天才 :) 非常感谢...... - 从上面的代码中移除本地旋转即可,虽然我还没有测试过,不过可能会有影响。 - Siddharth
2
RotateTowards永远不会超过目标。如果您使用LerpTime.deltaTime,并且由于某种原因设备出现滞后,以至于您有一个帧具有真正大的Time.deltaTime> 1,那么它将输出一个结果,其中它可能旋转超出应该去的位置。如果Time.deltaTime> 2,则它将比之前更远离目标。理论上,您可以使用Lerp(a,b,Mathf.Min(1f,Time.deltaTime)) - Ruzihm
1
@Siddharth 使用..Towards方法总是一个好习惯,特别是在基于增量的连续累积操作时。 Mathf包含了像intfloat这样的原始数据类型的版本。还有Vector2Vector3以及Quaternion中的版本。 - CosmicGiant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接