Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
使用 RigidBody¶
什么是刚体?¶
A rigid body is one that is directly controlled by the physics engine in order to simulate the behavior of physical objects. In order to define the shape of the body, it must have one or more Shape3D objects assigned. Note that setting the position of these shapes will affect the body's center of mass.
如何控制刚体¶
A rigid body's behavior can be altered by setting its properties, such as mass and weight. A physics material needs to be added to the rigid body to adjust its friction and bounce, and set if it's absorbent and/or rough. These properties can be set in the Inspector or via code. See RigidBody3D and PhysicsMaterial for the full list of properties and their effects.
有几种方法可以控制刚体的运动, 这取决于您的应用程序.
If you only need to place a rigid body once, for example to set its initial location, you can use the methods provided by the Node3D node, such as set_global_transform()
or look_at()
. However, these methods cannot be called every frame or the physics engine will not be able to correctly simulate the body's state.
As an example, consider a rigid body that you want to rotate so that it points towards another object. A common mistake when implementing this kind of behavior is to use look_at()
every frame, which breaks the physics simulation. Below, we'll demonstrate how to implement this correctly.
你不能使用 set_global_transform()
或 look_at()
方法并不意味着你不能完全控制一个刚体. 相反, 你可以通过使用 _integrate_forces()
回调来控制它. 在这个方法中, 你可以添加 力 , 应用 冲量 , 或者设置 速度 , 以实现你想要的任何运动.
“look at”方法¶
As described above, using the Node3D's look_at()
method can't be used each frame to follow a target.
Here is a custom look_at()
method that will work reliably with rigid bodies:
extends RigidBody3D
func look_follow(state, current_transform, target_position):
var up_dir = Vector3(0, 1, 0)
var cur_dir = current_transform.basis * Vector3(0, 0, 1)
var target_dir = current_transform.origin.direction_to(target_position)
var rotation_angle = acos(cur_dir.x) - acos(target_dir.x)
state.angular_velocity = up_dir * (rotation_angle / state.step)
func _integrate_forces(state):
var target_position = $my_target_node3d_node.global_transform.origin
look_follow(state, global_transform, target_position)
using Godot;
public partial class MyRigidBody3D : RigidBody3D
{
private void LookFollow(PhysicsDirectBodyState state, Transform3D currentTransform, Vector3 targetPosition)
{
var upDir = new Vector3(0, 1, 0);
var curDir = currentTransform.Basis * new Vector3(0, 0, 1);
var targetDir = currentTransform.Origin.DirectionTo(targetPosition);
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<Node3D>("MyTargetNode3DNode").GetGlobalTransform().Origin;
LookFollow(state, GetGlobalTransform(), targetPosition);
}
}
This method uses the rigid body's angular_velocity
property to rotate the body. It first calculates the difference between the current and desired angle and then adds the velocity needed to rotate by that amount in one frame's time.
备注
This script will not work with rigid bodies in character mode because then, the body's rotation is locked. In that case, you would have to rotate the attached mesh node instead using the standard Node3D methods.