Unity3D 在右(x 或 z)轴上调整 CUBE "endRotation"

Unity3D Adjusting CUBE "endRotation" on right ( x or z) axis

我是 Unity3D 脚本的新手,尤其是涉及到 Transform、Quaternions、Vector3 的细节时。 下面有一个脚本。当我滚动立方体时,它会朝正确的方向翻转。但是,当立方体的本地轴与世界轴不匹配时,立方体的 endRotation 会在错误的轴上执行。 任何人都可以帮我解决这个问题 :“endRotation” 会在右轴 上翻转立方体,而不管 LOCAL axis <=> WorldAxis 之间的关系如何。 我试图解决它一个星期。因为没有成功。 再往下就是代码和视频了。

      if (Input.GetAxis("Horizontal") > buttonDown)
        {
            StartCoroutine(FlipTheCube(Vector3.right));
            return
        }...

。 . .

    public IEnumerator FlipTheCube(Vector3 direction)
{
    startFliping = false;

    float rollStartTime = 0;
    float rollAngle = 90;
    float halfWidth = transform.localScale.z / 2;
    Vector3 pointAround = transform.position + (Vector3.down * halfWidth) + (direction * halfWidth);
    Vector3 rollAxis = Vector3.Cross(Vector3.up, direction);

    Quaternion rotation = transform.rotation;
    Quaternion **endRotation** = rotation * Quaternion.Euler(rollAxis * rollAngle);
    Vector3 endPlacement = transform.position + direction;

    float oldAngle = 0;

    while (rollStartTime < rollDurtnTime)
    {
        yield return new WaitForEndOfFrame();
        rollStartTime += Time.deltaTime;
        float newAngle = (rollStartTime / rollDurtnTime) * rollAngle;
        float rotateThrough = newAngle - oldAngle;
        oldAngle = newAngle;

        transform.RotateAround(pointAround, rollAxis, rotateThrough);
    }

    transform.position = endPlacement;
    transform.rotation = **endRotation**;

    startFliping = true;
}

这是一个 link 到 youtube 的视频 视频的第一部分如果立方体的局部轴与世界轴匹配,则“endRotation”正确翻转视频的第二部分只要立方体的局部轴不匹配匹配世界轴“endRotation”出错。

我建议您使用 DoTween 资源 (https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676):

DORotate(Vector3 to, float duration);

使用补间动画将为您节省大量编写自己的动画的时间。

您的问题在于以下几行:

Vector3 rollAxis = Vector3.Cross(Vector3.up, direction);

Quaternion rotation = transform.rotation;
Quaternion endRotation = rotation * Quaternion.Euler(rollAxis * rollAngle);

// ...

    transform.RotateAround(pointAround, rollAxis, rotateThrough);

第一个问题是 Euler vs angle/axis 用法。

如果您只针对 Vector3.rightVector3.forward 和他们的底片进行轮换,您可能还没有注意到这一点。

在第一部分中,您使用 rollAxis 作为欧拉角表示,在第二部分中作为轴。

问题是对于旋转,它的轴通常与该旋转的欧拉表示不同!例如,绕(0.7,0.0,0.7)旋转90°的旋转与欧拉旋转(63°,0°,63°)完全不同!

相反,只需始终如一地使用 rollAxis 作为 angle/axis 表示。您可以使用 Quaternion.AngleAxis.

获得四元数形式

第二个问题是全局与局部旋转。

这个问题的影响您肯定已经注意到了。

在第一部分中,您应用 rollAxis 作为局部旋转。这是因为 rollAxis* 运算符的第二项。

在第二部分中,RotateAround 围绕由 rollAxis 定义的全局轴旋转。

两者都保持全局或局部。全局比较简单,出现就是你要做的(从transform.position + direction判断),所以你应该把rotation作为第二项* 运算符。


总而言之,只需更改 Quaternion endRotation = rotation * Quaternion.Euler(rollAxis * rollAngle); 行即可解决问题:

Vector3 rollAxis = Vector3.Cross(Vector3.up, direction);

Quaternion rotation = transform.rotation;
Quaternion endRotation = Quaternion.AngleAxis(rollAngle, rollAxis) * rotation;

// ...

    transform.RotateAround(pointAround, rollAxis, rotateThrough);

有关四元数 * 运算符的更多信息。