将对象在 -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):

  1. 时间:0 - 旋转:360
  2. 时间:0,02 - 旋转:380
  3. 时间:0,02 - 旋转:420
  4. 时间: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;
    }
}