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...
Personaje cinemático (2D)¶
Introducción¶
Sí, el nombre suena extraño. "Personaje Cinemático". ¿Qué es eso? La razón es que cuando aparecieron los motores de físicas, fueron llamados motores de "Dinámicas" (porque tratan principalmente con respuestas de colisiones). Se llevaron a cabo muchos intentos para crear un controlador de personajes utilizando los motores de dinámicas, pero no fue tan fácil como parecía. Godot tiene una de las mejores implementaciones de controlador de personajes dinámicos (como puede verse en la demo 2d/plataformas), pero usarlo requiere un considerable nivel de habilidad y conocimiento de motores de físicas (o mucha paciencia con el ensayo y error).
Algunos motores de física como Havok parecen apostar por los controladores de personaje dinámico como la mejor alternativa, mientras que otros (PhysX) prefieren promover los de personaje cinemático.
Entonces, ¿cuál es la diferencia?:
Un controlador de personaje dinámico utiliza un cuerpo rígido con tensor de inercia infinita. Básicamente, es un cuerpo rígido que no puede rotar. Los motores de física siempre dejan que los objetos se muevan y colisionen, después resuelven sus colisiones todas juntas. Esto hace que los controladores de personaje dinámico sean capaces de interactuar con otros objetos físicos sin inconvenientes, como se ve en la demo del juego de plataformas. Sin embargo estas interacciones no son siempre predecibles. Las colisiones pueden tardar más de un frame en ser resueltas, así que unas pocas colisiones pueden verse desplazadas un poquito. Esos problemas pueden solucionarse, pero requieren de cierta habilidad.
Un controlador cinemático de personaje asume siempre en un estado de no colisión, y siempre se moverá a un estado de no colisión. Si comienza en un estado de colisión, intentará liberarse como lo hacen los cuerpos rígidos, pero esta es la excepción, no la regla. Esto hace que su control y movimiento sean mucho más predecibles y fáciles de programar. Sin embargo, como desventaja, no pueden interactuar directamente con otros objetos de la física, a menos que se haga a mano en código.
This short tutorial focuses on the kinematic character controller. It uses the old-school way of handling collisions, which is not necessarily simpler under the hood, but well hidden and presented as an API.
Proceso físico¶
Para manejar la lógica de un personaje o cuerpo cinemático, siempre se aconseja utilizar el proceso de la física, ya que es llamado antes del paso de la física y su ejecución está sincronizada con el servidor de física, también siempre es llamado la misma cantidad de veces por segundo. Esto hace que la física y el cálculo de movimiento funcionen de una manera más predecible que el proceso normal, que puede tener picos o perder precisión si la frecuencia de imagen es demasiado alta o demasiado baja.
extends CharacterBody2D
func _physics_process(delta):
pass
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
public override void _PhysicsProcess(double delta)
{
}
}
Configuración de la escena¶
To have something to test, here's the scene (from the tilemap tutorial): kinematic_character_2d_starter.zip. We'll be creating a new scene for the character. Use the robot sprite and create a scene like this:

Notarás que hay un icono de advertencia junto al nodo CollisionShape2D, esto es porque no hemos definido una forma para él. Crea un nuevo CircleShape2D en la propiedad shape de CollisionShape2D. Haz clic en <CircleShape2D> para ir a las opciones correspondientes, y establece el radio en 30:

Nota: Como se mencionó anteriormente en el tutorial de física, el motor de física no puede manejar la escala en la mayoría de los tipos de formas (sólo funcionan los polígonos de colisión, planos y segmentos), así que cambia siempre los parámetros (como el radio) de la forma en lugar de escalarla. Lo mismo ocurre con los cuerpos cinemáticos/rígidos/estáticos, ya que su escala afecta a la escala de la forma.
Ahora crea un script para el personaje, el que se usa como ejemplo anterior debería funcionar como base.
Por último, instancia la escena del personaje en el tilemap, y haz que la escena del mapa sea la principal, para que se ejecute al presionar play.

Moviendo el personaje cinemático¶
Go back to the character scene, and open the script, the magic begins
now! Kinematic body will do nothing by default, but it has a
useful function called CharacterBody2D.move_and_collide()
.
This function takes a Vector2 as
an argument, and tries to apply that motion to the kinematic body. If a
collision happens, it stops right at the moment of the collision.
Entonces, movamos nuestro sprite hacia abajo hasta que toque el suelo:
extends CharacterBody2D
func _physics_process(delta):
move_and_collide(Vector2(0, 1)) # Move down 1 pixel per physics frame
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
public override void _PhysicsProcess(double delta)
{
// Move down 1 pixel per physics frame
MoveAndCollide(new Vector2(0, 1));
}
}
El resultado es que el personaje se moverá, pero se detendrá justo cuando golpee el suelo. Bastante genial, ¿no?
El siguiente paso será añadir gravedad a la combinación, de esta manera se comporta de una manera más parecida a la de un personaje real de un juego:
extends CharacterBody2D
const GRAVITY = 200.0
func _physics_process(delta):
velocity.y += delta * GRAVITY
var motion = velocity * delta
move_and_collide(motion)
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
private const float Gravity = 200.0f;
public override void _PhysicsProcess(double delta)
{
var velocity = Velocity;
velocity.Y += (float)delta * Gravity;
Velocity = velocity;
var motion = velocity * (float)delta;
MoveAndCollide(motion);
}
}
Ahora el personaje cae suavemente. Hagamos que camine hacia los lados, izquierda y derecha, cuando se presionen las teclas de dirección. Recuerda que los valores utilizados (al menos para la velocidad) son píxeles/segundo.
This adds basic support for walking when pressing left and right:
extends CharacterBody2D
const GRAVITY = 200.0
const WALK_SPEED = 200
func _physics_process(delta):
velocity.y += delta * GRAVITY
if Input.is_action_pressed("ui_left"):
velocity.x = -WALK_SPEED
elif Input.is_action_pressed("ui_right"):
velocity.x = WALK_SPEED
else:
velocity.x = 0
# "move_and_slide" already takes delta time into account.
move_and_slide()
using Godot;
public partial class MyCharacterBody2D : CharacterBody2D
{
private const float Gravity = 200.0f;
private const int WalkSpeed = 200;
public override void _PhysicsProcess(double delta)
{
var velocity = Velocity;
velocity.Y += (float)delta * Gravity;
if (Input.IsActionPressed("ui_left"))
{
velocity.X = -WalkSpeed;
}
else if (Input.IsActionPressed("ui_right"))
{
velocity.X = WalkSpeed;
}
else
{
velocity.X = 0;
}
Velocity = velocity;
// "MoveAndSlide" already takes delta time into account.
MoveAndSlide();
}
}
E inténtalo.
Este es un buen punto de partida para un juego de plataformas. Se puede encontrar una demostración más completa en el zip de demostración distribuido con el motor, o en https://github.com/godotengine/godot-demo-projects/tree/master/2d/kinematic_character.