Использование RigidBody
Что такое твёрдое тело?
Твёрдое тело — это тело, которое напрямую управляется физическим движком для моделирования поведения физических объектов. Для определения формы тела ему должен быть назначен один или несколько объектов Shape3D. Обратите внимание, что установка положения этих объектов повлияет на центр масс тела.
Как управлять твёрдым телом
Поведение твердого тела можно изменить, задав его свойства, такие как масса и вес. К твердому телу необходимо добавить физический материал, чтобы отрегулировать его трение и отскок, а также установить, является ли он поглощающим и/или шероховатым. Эти свойства можно задать в Инспекторе или через код. См. RigidBody3D и PhysicsMaterial для полного списка свойств и их эффектов.
Существует несколько способов управления движением твёрдого тела в зависимости от потребности приложения.
Если вам нужно разместить твердое тело только один раз, например, чтобы задать его начальное местоположение, вы можете использовать методы, предоставляемые узлом Node3D, такие как set_global_transform() или look_at(). Однако эти методы невозможно вызывать в каждом кадре, иначе физический движок не сможет правильно моделировать состояние тела. В качестве примера рассмотрим твердое тело, которое вы хотите повернуть так, чтобы оно было направлено в сторону другого объекта. Распространенной ошибкой при реализации такого поведения является использование look_at() в каждом кадре, что нарушает физическую симуляцию. Ниже мы покажем, как это правильно реализовать.
Тот факт, что Вы не можете использовать методы set_global_transform() или look_at(), не означает, что вы не можете иметь полный контроль над твёрдым телом. Вместо этого можно управлять им с помощью обратного вызова _integrate_forces (). В этом методе можно добавлять силы, прикладывать импульсы, или задавать скорость для достижения любого нужного движения.
Метод «look at»
Как описано выше, метод look_at() из Node3D не может применяться в каждом кадре для отслеживания цели. Вот пользовательский метод look_at(), называемый look_follow(), который будет работать с твёрдыми телами:
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);
}
}
Этот метод использует свойство angular_velocity твёрдого тела для вращения. Ось вращения определяется векторным произведением текущего направления и направления, в котором требуется посмотреть. clamp — это простой метод, позволяющий предотвратить выход угла поворота за пределы направления, в котором требуется посмотреть, поскольку общий угол поворота определяется арккосинусом скалярного произведения. Этот метод также можно использовать с axis_lock_angular_*. Если требуется более точное управление, могут потребоваться решения, основанные на Quaternion, как описано в Использование 3D-преобразований.