Using RigidBody
什么是刚体?
刚体是直接由物理引擎控制以模拟物理对象行为的物体.为了定义物体的形状,必须分配一个或多个 Shape 对象.注意,设置这些形状的位置将影响物体的重心.
如何控制刚体
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 RigidBody and PhysicsMaterial for the full list of properties and their effects.
有几种方法可以控制刚体的运动,这取决于您的应用程序.
如果你只需要放置一次刚体,例如设置它的初始位置,你可以使用 Spatial 节点提供的方法,例如 set_global_transform()
或 look_at()
.但是,这些方法不能每一帧都被调用,否则物理引擎将无法正确地模拟物体的状态.举个例子,考虑一个刚体,你想旋转它,使它指向另一个对象.在实现这种行为时,一个常见的错误是每一帧都使用 look_at()
,这样会破坏物理模拟.下面,我们将演示如何正确地实现这一点.
你不能使用 set_global_transform()
或 look_at()
方法并不意味着你不能完全控制一个刚体.相反,你可以通过使用 _integrate_forces()
回调来控制它.在这个方法中,你可以添加 力 ,应用 冲量 ,或者设置 速度 ,以实现你想要的任何运动.
“look at” 方法
如上所述,使用Spatial节点的 look_at()
方法不能每一帧都用来跟踪一个目标.这里有一个自定义的 look_at()
方法,它可以可靠地工作在刚体上:
GDScript
C#
extends RigidBody
func look_follow(state, current_transform, target_position):
var up_dir = Vector3(0, 1, 0)
var cur_dir = current_transform.basis.xform(Vector3(0, 0, 1))
var target_dir = (target_position - current_transform.origin).normalized()
var rotation_angle = acos(cur_dir.x) - acos(target_dir.x)
state.set_angular_velocity(up_dir * (rotation_angle / state.get_step()))
func _integrate_forces(state):
var target_position = $my_target_spatial_node.get_global_transform().origin
look_follow(state, get_global_transform(), target_position)
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()
方法来旋转刚体.它首先计算当前角度和期望角度之间的差值,然后加上一帧时间内旋转所需的速度.
注解
这个脚本不能用于 character模式 下的刚体,因为这样的话,刚体的旋转就会被锁定.在这种情况下,你必须使用标准的 Spatial 方法来旋转附加的网格节点.