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...
Usando RigidBody
O que é um corpo rígido?
Um corpo rígido é aquele que é diretamente controlado pelo motor de física para simular o comportamento de objetos físicos. Para definir a forma do corpo, ele deve ter um ou mais objetos Shape3D atribuídos. Note que definir a posição dessas formas afetará o centro de massa do corpo.
Como controlar um corpo rígido
O comportamento de um corpo rígido pode ser alterado definindo suas propriedades, como massa e peso. Um material físico precisa ser adicionado ao corpo rígido para ajustar seu atrito e quique, e definir se ele é absorvente e/ou rugoso. Essas propriedades podem ser definidas no Inspetor ou via código. Veja RigidBody3D e PhysicsMaterial para a lista completa de propriedades e seus efeitos.
Existem várias maneiras de controlar o movimento de um corpo rígido, dependendo da aplicação desejada.
Se você só precisa posicionar um corpo rígido uma vez, por exemplo para definir seu local inicial, você pode usar os métodos fornecidos pelo nó Node3D, como set_global_transform() ou look_at(). No entanto, esses métodos não podem ser chamados a cada quadro, caso contrário o motor de física não será capaz de simular corretamente o estado do corpo. Como exemplo, considere um corpo rígido que você deseja rotacionar para que ele aponte em direção a outro objeto. Um erro comum ao implementar esse tipo de comportamento é usar look_at() a cada quadro, o que quebra a simulação de física. Abaixo, demonstraremos como implementar isso corretamente.
O fato de você não poder usar os métodos set_global_transform() ou look_at() não significa que você não possa ter controle total de um corpo rígido. Em vez disso, você pode controlá-lo usando o callback _integrate_forces(). Neste método, você pode adicionar forças, aplicar impulsos ou definir a velocidade para alcançar qualquer movimento que desejar.
O método "look at"
Como descrito acima, o método look_at() do Node3D não pode ser usado a cada quadro para seguir um alvo. Aqui está um método look_at() customizado chamado look_follow() que funcionará com corpos rígidos:
extends RigidBody3D
var speed: float = 0.1
func look_follow(state: PhysicsDirectBodyState3D, current_transform: Transform3D, target_position: Vector3) -> void:
var forward_local_axis: Vector3 = Vector3(1, 0, 0)
var forward_dir: Vector3 = (current_transform.basis * forward_local_axis).normalized()
var target_dir: Vector3 = (target_position - current_transform.origin).normalized()
var local_speed: float = clampf(speed, 0, acos(forward_dir.dot(target_dir)))
if forward_dir.dot(target_dir) > 1e-4:
state.angular_velocity = local_speed * forward_dir.cross(target_dir) / 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 float _speed = 0.1f;
private void LookFollow(PhysicsDirectBodyState3D state, Transform3D currentTransform, Vector3 targetPosition)
{
Vector3 forwardLocalAxis = new Vector3(1, 0, 0);
Vector3 forwardDir = (currentTransform.Basis * forwardLocalAxis).Normalized();
Vector3 targetDir = (targetPosition - currentTransform.Origin).Normalized();
float localSpeed = Mathf.Clamp(_speed, 0.0f, Mathf.Acos(forwardDir.Dot(targetDir)));
if (forwardDir.Dot(targetDir) > 1e-4)
{
state.AngularVelocity = forwardDir.Cross(targetDir) * localSpeed / state.Step;
}
}
public override void _IntegrateForces(PhysicsDirectBodyState3D state)
{
Vector3 targetPosition = GetNode<Node3D>("MyTargetNode3DNode").GlobalTransform.Origin;
LookFollow(state, GlobalTransform, targetPosition);
}
}
Este método usa a propriedade angular_velocity do corpo rígido para girar o corpo. O eixo em torno do qual girar é dado pelo produto vetorial entre a direção de frente atual e a direção para a qual se deseja olhar. O clamp é um método simples usado para evitar que a quantidade de rotação ultrapasse a direção para a qual se deseja olhar, pois a quantidade total de rotação necessária é dada pelo arco cosseno do produto escalar. Este método também pode ser usado com axis_lock_angular_*. Se for necessário um controle mais preciso, soluções como as que dependem de Quaternion podem ser necessárias, conforme discutido em Usando transformadores 3D.