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;
}
我建议您使用 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.right
、Vector3.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);
有关四元数 *
运算符的更多信息。
我是 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;
}
我建议您使用 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.right
、Vector3.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);
*
运算符的更多信息。