Mover un personaje en Unity con física realista exige decisiones precisas. Aquí verás cómo aplicar una velocidad horizontal constante, por qué usar FixedUpdate para un movimiento fluido y cómo preparar un controlador que avanza a la derecha mientras preserva el salto. Además, se proponen ejercicios para ampliar el gameplay con teclas y animaciones.
¿Cómo mover al personaje con física en Unity sin perder fluidez?
Para actualizar la velocidad del RigidBody, la recomendación es usar FixedUpdate. A diferencia de Update, que corre por frame, FixedUpdate funciona con un ritmo fijo. Así evitas que las bajadas de FPS provoquen un movimiento entrecortado o "lageado". Cualquier ajuste de física dentro de FixedUpdate se percibe más estable. El resultado: un desplazamiento horizontal que se mantiene suave incluso cuando la escena se vuelve más pesada.
¿Qué diferencia hay entre Update y FixedUpdate?
Update: se ejecuta por frame. Si caen los FPS, el movimiento se resiente.
FixedUpdate: se ejecuta con un reloj a intervalos fijos. Movimiento estable.
Física: configura velocidades y fuerzas en FixedUpdate para consistencia.
¿Qué variables y código necesitas para la velocidad horizontal?
Crea una variable pública de velocidad para editarla en el editor: un valor mayor o menor cambia de forma directa la dificultad. El ejemplo usa 2.0 como valor inicial, colocada junto a jumpForce en el player controller. Luego, en FixedUpdate, fuerza la componente horizontal del RigidBody hasta alcanzar la runningSpeed, preservando la velocidad vertical del salto.
¿Cómo queda el código mínimo en el player controller?
// Dentro del script del Player Controllerpublicfloat runningSpeed =2f;// editable desde el editorvoidFixedUpdate(){// Si no alcanzamos la velocidad objetivo en X, la imponemos.if(rigidBody.velocity.x < runningSpeed){ rigidBody.velocity =newVector2( runningSpeed,// velocidad horizontal constante rigidBody.velocity.y // preservar velocidad vertical del salto);}}
Puntos clave:
Variable pública para ajustar la velocidad desde el inspector de Unity.
Movimiento automático hacia la derecha en el eje X.
La componente vertical la gobierna el sistema de salto existente.
Guarda el script antes de probar: si no, no verás cambios.
Al llegar al final de la plataforma, el personaje cae y sale de pantalla si la cámara no lo sigue.
¿Qué experimentos y ejercicios mejoran el gameplay y la animación?
El controlador base avanza a ritmo fijo y el jugador solo puede saltar con la barra espaciadora. A partir de aquí, se sugiere experimentar con física y añadir controles para transformar el gameplay.
¿Qué pasa si desactivas freeze rotation en Z?
Al quitar la restricción en Z, el personaje puede volcar y girar como una peonza.
Con colisionadores circulares, el giro es más evidente y menos estable.
Duplicar plataformas ayuda a observar el comportamiento al aterrizar y al rodar.
¿Qué ejercicios propuestos amplían tu controlador?
Usar teclas A y D para mover a izquierda y derecha.
Implementar el flip de la animación para mirar en ambos sentidos.
Añadir booleanos: mirando a izquierda/derecha, estados de animación.
Crear animaciones extra: agacharse o una animación tras un tiempo quieto.
Ajustar la runningSpeed para modular dificultad y ritmo.
¿Te animas a compartir cómo adaptarías el controlador y qué variantes de movimiento probarías? Comenta tus ideas y resultados.
Movimiento automático y control del personaje en Unity
Para hacer que el personaje voltee cuando camine necesitamos recuperar el componente SpriteRenderer del personaje y llamar a un metodo que lo voltee en X dependiendo de la velocidad del personaje.
A tener en cuenta.
Ya que el frame rate del Update es diferente del FixedUpdate, esto causa ciertos impedimentos al momento de ejecutar acciones.
El FixedUpdate se suele usar para Physics(Físicas), pero aquellos cálculos físicos, ya que el frame rate es estable, aunque muy diferente al real manejado.
Ya explicado esto, es recomendado usar Update para Input y FixedUpdate para ejecutar los cálculos físicos, de esta maneras evitaras malos cálculos y tendrás mas precision en lo que haces.
Un ejemplo es con el salto, puede variar mucho al momento de ejecutarlo en el Update los cálculos
El profe explica muy bien y además nos intensiva a investigar y hacer cosas por nuestra cuenta, claro dándonos las bases. Me parece algo genial.
Les paso la solucion extraida de mi Obsidian.
Reto 2: Completado
Movimiento lateral del jugador y flip de sprite.
Solucion:
Primero declare el componente y lo inicialicé
SpriteRenderer spriteRenderer;voidAwake(){//rigidBody = GetComponent<Rigidbody2D>(); No importa 🥱//animator = GetComponent<Animator>(); Tampoco importa esto 🥱 spriteRenderer =GetComponent<SpriteRenderer>();// Esto es!}
Y ahora creé el metodo SpriteRendererFlip donde con Input.GetAxis("Horizontal")
puedo obtener el input horizontal.
Explico: Input.GetAxis("Horizontal") Devuelve un float entre -1, 0 y 1
Donde:
-1 es izquierda
0 es sin movimiento, osea sin apretar las teclas A D
1 es derecha
Y le digo si el input es mayor que 0, que vaya al componente spriteRenderer y en su variable flipX le de el valor false.
E inversamente lo mismo si el input es menor que 0, ahi si lo flipea.
De esta forma cuando apreto D le da el valor false y se voltea el sprite, y cuando apreto A el valor true y lo voltea.
voidUpdate(){// Codigos 👌SpriteRendererFlip()// Mas codigo 👌}voidSpriteRendererFlip(){if(Input.GetAxis("Horizontal")>0){ spriteRenderer.flipX =false;}elseif(Input.GetAxis("Horizontal")<0){ spriteRenderer.flipX =true;}}
Luego implemente el movimiento en FixedUpdate ya que estoy trabajando con fisicas.
Pensé:
“Bueno ya que el GetAxis me devuelve numeros entre -1, 0 y 1, a los cuales va llegando gradualmente mientras mantengo la tecla apretada, entonces multiplico es por la velocidad de correr, cuando Input vale 1 hay movimiento, cuando 0 no hay nada ya que runningSpeed se cancela, y cuando -1 es negativo por lo que velocity.x es -runningSpeed e ira en direccion contraria.”
Estoy haciendo un videojuego al estilo de pacman por lo tanto también el personaje puede subir y bajar por todo el esceanario
¿por qué si pongo este código para que mi personaje se mueva hacia arriba, al soltar la tecla sigue subiendo indefinidamente?
elseif(Input.GetKey(KeyCode.W)||Input.GetKey(KeyCode.UpArrow)){// moverse hacia arribarigidBody.velocity=newVector2(rigidBody.velocity.x, runningSpeed);}```
intenta usar GetKeyDown
Recuerden que no se necesita que vaya de izquierda a derecha porque es un Infinity Runner, camina hacia la derecha por si solo
Al momento de saltar mi personaje baja la velocidad en que se mueve en el eje x, como puedo solucionar esto?
¿Cómo puedo subir un gif, para mostrar mis resultados del reto?
Ya tengo el gif, solo que no me deja.
Hola @Rix.
Lo puedes Subir desde la página Gifyu es bastante buena, no necesitas registrarte y nada, solo la subes copias la dirección del Gif y lo metes en tu comentario y listo.
Espero que te sea de utilidad mi comentario y suerte en tus estudios.
Hola @CrisTEM
gracias por la info :)
tenia el problema de que el personaje se deslizaba así que le agregue un else para que parara su movimiento una vez uno deje de oprimir las teclas.
<privatevoidFixedUpdate()// un update que funciona a ritmo fijo, que no se retraza y no acelera {if(Input.GetKey(KeyCode.RightArrow))//Movimiento del personaje{ rigidBody.velocity=newVector2(runningSpeed,// eje x rigidBody.velocity.y// eje y); transform.localScale=newVector2(1f, 1f);//agarra la escala del transform del personaje y la modifica con un nuevo vector para la animación}elseif(Input.GetKey(KeyCode.LeftArrow))//Movimineto izquierda{ rigidBody.velocity=newVector2(runningSpeed *-1, rigidBody.velocity.y); transform.localScale=newVector2(-1f, 1f);}else//dejar de caminar para no deslizar{ rigidBody.velocity=newVector2(runningSpeed *0, rigidBody.velocity.y);}}>
Yo le di movilidad a mi personaje de esta forma en la cual de una vez modifico la escala del transform para hacerle flip a la animación.
<privatevoidFixedUpdate()// un update que funciona a ritmo fijo, que no se retraza y no acelera {if(Input.GetKey(KeyCode.RightArrow))//Movimiento del personaje{ rigidBody.velocity=newVector2(runningSpeed,// eje x rigidBody.velocity.y// eje y); transform.localScale=newVector2(1f, 1f);}if(Input.GetKey(KeyCode.LeftArrow)){ rigidBody.velocity=newVector2(runningSpeed *-1, rigidBody.velocity.y); transform.localScale=newVector2(-1f, 1f);}}>
privatevoidFixedUpdate(){ float direction =Input.GetAxis("Horizontal");if(direction !=0){ rigidBody.velocity=newVector2(direction * runningspeed, rigidBody.velocity.y); spriteRenderer.flipX= direction <0;}}
Hola a todos!!, ¿Cuándo es recomendable usar Update y cuando FixedUpdate? o al menos que se considera buena practica en este sentido
Al completar la clase me sale una ventana con este error "Can`t add script component ´playerController´ because the script class cannot be found. Make sure that there are no compile errors and that the file name and class name match." y no me deja realizar la animación del personaje, ¿alguien puede ayudarme o decirme como solucionarlo?
Este es mi codigo
using System.Collections;using System.Collections.Generic;using UnityEngine;publicclassPlayerController:MonoBehaviour{//Variables del movimiento del personajepublic float jumpForce = 6f;public float runningSpeed = 2f;Rigidbody2D rigidBody;Animator animator;const string STATE_ALIVE="isAlive";const string STATE_ON_THE_GROUND="isOnTheGround";publicLayerMask groundMask;voidAwake(){ rigidBody =GetComponent<Rigidbody2D>(); animator =GetComponent<Animator>();}// Use this for initializationvoidStart(){ animator.SetBool(STATE_ALIVE,true); animator.SetBool(STATE_ON_THE_GROUND,true);}// Update is called once per framevoidUpdate(){if(Input.GetKeyDown(KeyCode.Space)||Input.GetMouseButtonDown(0)){Jump();} animator.SetBool(STATE_ON_THE_GROUND,IsTouchingTheGround());Debug.DrawRay(this.transform.position,Vector2.down*1.5f,Color.red);}voidFixedUpdate(){if(rigidBody.velocity.x< runningSpeed){ rigidBody.velocity=newVector2(runningSpeed,//x rigidBody.velocity.y//y);}}voidJump(){if(IsTouchingTheGround()){ rigidBody.AddForce(Vector2.up* jumpForce,ForceMode2D.Impulse);}}//Nos indica si el personaje está o no tocando el suelo bool IsTouchingTheGround(){if(Physics2D.Raycast(this.transform.position,Vector2.down,1.5f, groundMask)){//TODO: programar lógica de contacto con el sueloreturntrue;}else{//TODO: programar lógica de no contactoreturnfalse;}}}
He seguido el curso al pie de la letra y no se porque sale eso
Suele pasar si es que tienes error de compilacion o lo mas comun, que el nombre del archivo no coincida con el de la public class, tiene que ser exactamente el mismo, si tiene espacios o algo que el programa no identifique los eliminara y asi ya no coincide, recomiendo que pongas un nombre del archivo sin espacios o numeros y que ese lo copies y peges en la public classs ejemplo:
public class PlayerController : MonoBehaviour
Yo lo logre pero justo antes de que acabe la animacion de caminar se acaba el flip.x y por un frame se ve la animacion hacia la derecha otra vez y no se porque ni como arreglarlo
tengo un pequeño bug, el personaje tiene una animacion adicional que seria como un idle state mas como un plataforma tradicional, lo que me sucede es que cuando intenta saltar mientras esta corriendo la animacion no se ejecuta