使用 RigidBody

什么是刚体?

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

如何控制刚体

刚体的行为可以通过设置其属性来改变,比如质量和重量。需要给刚体添加一个物理材质来调整它的摩擦力和反弹力,并设置它是否具有吸收性、粗糙度。这些属性可以在检查器中或通过代码来设置。参见 RigidBodyPhysicsMaterial 获取完整的属性列表和它们的效果。

有几种方法可以控制刚体的运动, 这取决于您的应用程序.

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

你不能使用 set_global_transform()look_at() 方法并不意味着你不能完全控制一个刚体. 相反, 你可以通过使用 _integrate_forces() 回调来控制它. 在这个方法中, 你可以添加 , 应用 冲量 , 或者设置 速度 , 以实现你想要的任何运动.

“look at”方法

如上所述, 使用Spatial节点的 look_at() 方法不能每一帧都用来跟踪一个目标. 这里有一个自定义的 look_at() 方法, 它可以可靠地工作在刚体上:

GDScriptC#

  1. extends RigidBody
  2. func look_follow(state, current_transform, target_position):
  3. var up_dir = Vector3(0, 1, 0)
  4. var cur_dir = current_transform.basis.xform(Vector3(0, 0, 1))
  5. var target_dir = (target_position - current_transform.origin).normalized()
  6. var rotation_angle = acos(cur_dir.x) - acos(target_dir.x)
  7. state.set_angular_velocity(up_dir * (rotation_angle / state.get_step()))
  8. func _integrate_forces(state):
  9. var target_position = $my_target_spatial_node.get_global_transform().origin
  10. look_follow(state, get_global_transform(), target_position)
  1. class Body : RigidBody
  2. {
  3. private void LookFollow(PhysicsDirectBodyState state, Transform currentTransform, Vector3 targetPosition)
  4. {
  5. var upDir = new Vector3(0, 1, 0);
  6. var curDir = currentTransform.basis.Xform(new Vector3(0, 0, 1));
  7. var targetDir = (targetPosition - currentTransform.origin).Normalized();
  8. var rotationAngle = Mathf.Acos(curDir.x) - Mathf.Acos(targetDir.x);
  9. state.SetAngularVelocity(upDir * (rotationAngle / state.GetStep()));
  10. }
  11. public override void _IntegrateForces(PhysicsDirectBodyState state)
  12. {
  13. var targetPosition = GetNode<Spatial>("my_target_spatial_node").GetGlobalTransform().origin;
  14. LookFollow(state, GetGlobalTransform(), targetPosition);
  15. }
  16. }

使用刚体的 set_angular_velocity() 方法来旋转刚体. 它首先计算当前角度和期望角度之间的差值, 然后加上一帧时间内旋转所需的速度.

备注

这个脚本不能用于 character模式 下的刚体, 因为这样的话, 刚体的旋转就会被锁定. 在这种情况下, 你必须使用标准的 Spatial 方法来旋转附加的网格节点.