将对象在 -45 到 45 度之间旋转未按预期运行
Rotating an object between -45 and 45 degrees not behaving as expected
我想让一个物体在 -45 到 45 度之间摆动,下面是我使用的代码。请注意,direction
初始化为 1,zRotation
初始化为 360,speed
初始化为 100。这工作得很好。但是,当我将 speed
更改为 1000 时,对象会在继续正确振荡之前进行完整的 360 度旋转。我很困惑为什么会这样。
这是我的代码(在 Update
方法中):
zRotation += speed * Time.deltaTime * direction;
var newRotation =
Quaternion.Euler(
new Vector3(
0,
0,
zRotation));
if (zRotation < 315)
direction = 1;
if (zRotation > 405)
direction = -1;
transform.rotation = newRotation;
我使用的值是 315(-45 度)和 405(45 度),因为这样更容易确定我的对象是否达到了 -45 和 45 度。
我知道使用 Lerp 可以更轻松、更干净地实现这种行为,但这是一项作业,我们还没有涉及 Lerp,所以我不想使用 material还没教过。
问题是您没有将 zRotation
值限制在您想要的值之间。在您的代码的当前状态下,您只依赖于您的计算机速度快且 Time.deltaTime
值很少(自上一帧以来经过的时间)。
如果你有任何类型的卡顿(通常发生在启动后的前几帧),Time.deltaTime
值会相对较大,导致 zRotation
太大以至于它return 进入 [-45...45] 范围需要更长的时间。您可以通过添加一行
来检查这一点
Debug.Log($"Time: {Time.deltaTime} - Rotation: {zRotation}");
到您的更新方法。
这样会出现下面的场景(每一行是一帧的log):
- 时间:0 - 旋转:360
- 时间:0,02 - 旋转:380
- 时间:0,02 - 旋转:420
- 时间:0,333 - 旋转:733,33
在最后一步中,有一个 deltaTime
值太大,导致 zRotation
松动并偏离您想要的范围。
如果您使用
限制旋转值
zRotation = Mathf.Min(Mathf.Max(zRotation, 315), 405);
你不会超出预期的范围。 (当然,您必须将 if 语句从 <
更新为 <=
,或者您可以在 Min(Max())
部分保留某种阈值。
我还建议您使用模运算符 (%
) 并将 zRotation
的值初始化为 0
这样您就不必经常跟踪360-minAngle、360+minAngle 值,您可以更轻松地使用角度,模运算符可帮助您保持在 [-360...360] 范围内。
我更新了你的代码:
public class Rotator : MonoBehaviour
{
private float direction = 1;
private float zRotation = 0; // zRotation initialized to 0 instead of 360
public float speed = 1000;
void Update()
{
zRotation += (speed * Time.deltaTime * direction) % 360; // Use of the modulo operator
zRotation = Mathf.Min(Mathf.Max(zRotation, -45), 45); // Limiting the angles so the object does not 'spin out'
//If you want to see what's going on in the log
Debug.Log($"Time: {Time.deltaTime} - Rotation: {zRotation}");
var newRotation =
Quaternion.Euler(
new Vector3(
0,
0,
zRotation));
if (zRotation <= -45) // LTE because of the limitation to -45
direction = 1;
if (zRotation >= 45) /// GTE because of the limitation to 45
direction = -1;
transform.rotation = newRotation;
}
}
我想让一个物体在 -45 到 45 度之间摆动,下面是我使用的代码。请注意,direction
初始化为 1,zRotation
初始化为 360,speed
初始化为 100。这工作得很好。但是,当我将 speed
更改为 1000 时,对象会在继续正确振荡之前进行完整的 360 度旋转。我很困惑为什么会这样。
这是我的代码(在 Update
方法中):
zRotation += speed * Time.deltaTime * direction;
var newRotation =
Quaternion.Euler(
new Vector3(
0,
0,
zRotation));
if (zRotation < 315)
direction = 1;
if (zRotation > 405)
direction = -1;
transform.rotation = newRotation;
我使用的值是 315(-45 度)和 405(45 度),因为这样更容易确定我的对象是否达到了 -45 和 45 度。
我知道使用 Lerp 可以更轻松、更干净地实现这种行为,但这是一项作业,我们还没有涉及 Lerp,所以我不想使用 material还没教过。
问题是您没有将 zRotation
值限制在您想要的值之间。在您的代码的当前状态下,您只依赖于您的计算机速度快且 Time.deltaTime
值很少(自上一帧以来经过的时间)。
如果你有任何类型的卡顿(通常发生在启动后的前几帧),Time.deltaTime
值会相对较大,导致 zRotation
太大以至于它return 进入 [-45...45] 范围需要更长的时间。您可以通过添加一行
Debug.Log($"Time: {Time.deltaTime} - Rotation: {zRotation}");
到您的更新方法。
这样会出现下面的场景(每一行是一帧的log):
- 时间:0 - 旋转:360
- 时间:0,02 - 旋转:380
- 时间:0,02 - 旋转:420
- 时间:0,333 - 旋转:733,33
在最后一步中,有一个 deltaTime
值太大,导致 zRotation
松动并偏离您想要的范围。
如果您使用
zRotation = Mathf.Min(Mathf.Max(zRotation, 315), 405);
你不会超出预期的范围。 (当然,您必须将 if 语句从 <
更新为 <=
,或者您可以在 Min(Max())
部分保留某种阈值。
我还建议您使用模运算符 (%
) 并将 zRotation
的值初始化为 0
这样您就不必经常跟踪360-minAngle、360+minAngle 值,您可以更轻松地使用角度,模运算符可帮助您保持在 [-360...360] 范围内。
我更新了你的代码:
public class Rotator : MonoBehaviour
{
private float direction = 1;
private float zRotation = 0; // zRotation initialized to 0 instead of 360
public float speed = 1000;
void Update()
{
zRotation += (speed * Time.deltaTime * direction) % 360; // Use of the modulo operator
zRotation = Mathf.Min(Mathf.Max(zRotation, -45), 45); // Limiting the angles so the object does not 'spin out'
//If you want to see what's going on in the log
Debug.Log($"Time: {Time.deltaTime} - Rotation: {zRotation}");
var newRotation =
Quaternion.Euler(
new Vector3(
0,
0,
zRotation));
if (zRotation <= -45) // LTE because of the limitation to -45
direction = 1;
if (zRotation >= 45) /// GTE because of the limitation to 45
direction = -1;
transform.rotation = newRotation;
}
}