如何防止在统一对象中倾斜

时间:2017-03-09 00:49:51

标签: unity3d

我有一个悬浮水箱,我正在为它控制一个控制器。目标是将浮子放在地面上,但我不希望它倾斜超过一两度。我希望它基本上保持水平。

我在坦克上使用Rigidbody来控制.MovePosition.MoveRotation。您可以在下面看到FixedUpdate功能。我在下面有一节保持思考水平,我检查是否有坦克超过其maxTilt金额。如果是,则将其保持在最大值

这使坦克一直非常紧张。它看起来很快就会上下跳动。我认为这是由于悬停力量,但我不确定。

如何保持坦克水平,同时仍让它胡佛?

FixedUdpate

void FixedUpdate () {
    if (!isServer) {
        return;
    }

    CheckGrounded ();
    Hoover ();

    if (_moveForward) {
        float moveAmount = moveSpeed * Time.deltaTime;
        _rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
    }
    if (_moveBackward) {
        float moveAmount = (-moveSpeed * 0.6f) * Time.deltaTime;
        _rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.forward * moveAmount);
    }

    if (_turnLeft) {
        Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, -angularSpeed, 0f) * Time.deltaTime);
        _rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
    }
    if (_turnRight) {
        Quaternion rotateAmount = Quaternion.Euler(new Vector3(0f, angularSpeed, 0f) * Time.deltaTime);
        _rigidbody.MoveRotation(_rigidbody.rotation * rotateAmount);
    }

    if (_jump && _isGrounded) {
        _isJumping = true;
    }

    if (_isJumping && _jumpTimeLeft > 0) {
        float moveAmount = jumpSpeed * Time.deltaTime;
        _rigidbody.MovePosition(_rigidbody.position + _rigidbody.transform.up * moveAmount);

        _jumpTimeLeft -= Time.deltaTime;
    } else if (_isJumping) {
        _isJumping = false;
        _jumpTimeLeft = jumpTime;

    }

    // Keep things level
    Vector3 rotation = _rigidbody.rotation.eulerAngles;
    if (rotation.x > maxTilt) {
        rotation.x = maxTilt;
    } else if (rotation.x < -maxTilt) {
        rotation.x = -maxTilt;
    }
    if (rotation.y > maxTilt) {
        rotation.y = maxTilt;
    } else if (rotation.y < -maxTilt) {
        rotation.y = -maxTilt;
    }
    if (rotation.z > maxTilt) {
        rotation.z = maxTilt;
    } else if (rotation.z < -maxTilt) {
        rotation.z = -maxTilt;
    }
    Quaternion q = new Quaternion ();
    q.eulerAngles = rotation;
    _rigidbody.rotation = q;
}

胡佛

void Hoover() {
    foreach (Transform hoverPoint in hooverPoints) {
        Ray ray = new Ray (hoverPoint.position, -hoverPoint.up);
        RaycastHit hitInfo;

        if (Physics.Raycast (ray, out hitInfo, hooverHeight)) {
            float distance = Vector3.Distance (hoverPoint.position, hitInfo.point);

            if (distance < hooverHeight) {
                _rigidbody.AddForceAtPosition (hoverPoint.up * hooverForce * (1f - distance / hooverHeight), hoverPoint.position, ForceMode.Force);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我认为你看到的原因是紧张的&#39;是因为......

  

所有物理计算和更新在FixedUpdate之后立即发生。   https://docs.unity3d.com/Manual/ExecutionOrder.html

因为您正在调整FixedUpdate()中的倾斜度,然后物理引擎会立即执行其计算,否则有时会改变倾斜值,从而产生“抖动”# 39 ;.我有时说的原因是因为FixedUpdate()每帧可以运行多次(取决于FPS),这可能意味着单个帧的以下调用顺序:

  1. FixedUpdate() // start frame
  2. PhysicsEngine
  3. FixedUpdate() // end frame
  4. 在上面的例子中,会有无抖动,因为你在物理引擎完成它之后重新校正了倾斜 - 完全侥幸。但是,如果您没有在相框上进行第二次FixedUpdate()来电,您将拥有:

    1. FixedUpdate() // start frame
    2. PhysicsEngine // end frame
    3. 这将导致您的抖动。

      所以我的建议是拆分你的FixedUpdate()并将任何倾斜修正偏移到LateUpdate()。因此,在呈现帧之前,始终LateUpdate()始终是最后一次更新调用。