天天看点

游戏开发中的物理之刚体

什么是刚体?

刚体是由物理引擎直接控制以模拟物理对象行为的刚体。为了定义主体的形状,必须为其分配一个或多个Shape对象。请注意,设置这些形状的位置会影响人体的重心。

如何控制刚体

刚体的行为可以通过设置其属性(例如,摩擦力,质量,弹跳等)来更改。这些属性可以在检查器中或通过代码设置。有关属性及其效果的完整列表,请参见RigidBody。

有多种方法可以控制刚体的运动,具体取决于您所需的应用程序。

如果只需要放置一次刚体(例如设置其初始位置),则可以使用Spatial节点提供的方法,例如set_global_transform()或look_at()。但是,这些方法不能在每一帧都调用,否则物理引擎将无法正确模拟人体的状态。例如,考虑要旋转的刚体,使其指向另一个对象。实现这种行为的一个常见错误是使用look_at()每帧,这会破坏物理模拟。下面,我们将演示如何正确实现这一点。

您不能使用set_global_transform()或look_at()方法的事实并不意味着您无法完全控制刚体。相反,您可以通过使用_integrate_forces()回调来控制它。在此方法中,您可以添加力,施加脉冲或设置速度以实现所需的任何运动。

“看”方法

如上所述,使用空间节点的look_at()方法不能在每一帧都遵循目标。这是一种look_at()可以与刚体可靠结合的自定义方法:

class Body : RigidBody
{
    private void LookFollow(PhysicsDirectBodyState state, Transform currentTransform, Vector3 targetPosition)
    {
        var upDir = new Vector3(0, 1, 0);
        var curDir = currentTransform.basis.Xform(new Vector3(0, 0, 1));
        var targetDir = (targetPosition - currentTransform.origin).Normalized();
        var rotationAngle = Mathf.Acos(curDir.x) - Mathf.Acos(targetDir.x);
        state.SetAngularVelocity(upDir * (rotationAngle / state.GetStep()));
    }
    public override void _IntegrateForces(PhysicsDirectBodyState state)
    {
        var targetPosition = GetNode<Spatial>("my_target_spatial_node").GetGlobalTransform().origin;
        LookFollow(state, GetGlobalTransform(), targetPosition);
    }
}      

此方法使用刚体的set_angular_velocity()方法旋转本体。它首先计算当前角度与所需角度之间的差,然后在一帧时间内将旋转所需的速度相加。

注意

该脚本不适用于角色模式下的刚体,因为那样会锁定刚体的旋转。在这种情况下,您将不得不使用标准的Spatial方法来旋转附加的网格节点。

继续阅读