Sistema de movimiento en 2D en Unity ¿Cómo funciona?

in Develop Spanish4 years ago


movement2d.png

El sistema de movimiento

Dar vida a tu personaje

El movimiento es una parte primordial en la mayor parte de los juegos, con ella mandas información al jugador que esta manipulando un ser, una entidad y un elemento que depende de el y sigue las ordenes, es digitalizar un medio y llevarlo al plano de juego.

Conoce cómo funciona el desplazamiento en Unity

En este motor se utiliza múltiples sistemas y formas de desplazar un cuerpo, unas mas eficaces otras mas costosas en rendimiento, pero cada una cumple un elemento clave dependiendo lo que se quiera lograr, en esta guía trabajaremos con la noción mas básica, mover un elemento utilizando el sistema de coordenadas en 2D; arriba, abajo, izquierda y derecha.

Configuración necesaria

Ante que todo este proyecto debe ser agregado y configurado en una plantilla 2D para facilitar la configuración inicial. Recomiendo tener instalado Unity mediante Unity Hub y ubicar el botón ADD, luego seleccionar la respectiva plantilla.

image.png

Luego de ello podemos descargar un sprite de algún personaje en un sitio gratuito como OpenGameArt, por ejemplo yo utilice este Simple Space by Kenney; importamos el archivo o archivos de imagen del personaje. Al subir la imagen, hay que configurarla para que sirva como un Sprite2D y que pueda ser representado en el motor de juegos. Para ello te dejo una configuración básica para un sprite de 64x64, la imagen en mucho mas grande, por eso elijo Sprite Mode Multiple, luego me ubico en Sprite Editor y dividio la imagen una grilla de 64x64.
En Pixels Per Unit se coloca el tamaño de pixel que utiliza el sprite, si es 64x64 es recomendable colocar 64.
Tener en cuenta que si el sprite es de múltiples secciones, hay que colocar en el Sprite Mode Multiple, esto facilita que una imagen pueda ser dividida en varias secciones con una grilla o de forma automática, esto brinda que se puedan manipular animaciones de una manera mas sencilla.

image.png


Agregando lógica

A lo que vamos en esta pequeña guía es a mover este personaje (Sprite2D) en el escenario de una manera sencilla y practica. Recuerden agregar dicha imagen del personaje al escenario, basta con arrastrar la imagen a la pantalla de Scene en Unity.

Agregando un Script

Es primordial que para mover dicha imagen (nave en este caso) tengamos que recurrir a un poco de programación, hay maneras mas visuales de dar movimiento con una herramienta de programación visual llamada BOLT, pero en este caso no será con dicho método.

Primero que nada debes crear una carpeta en el directorio raíz de Project, se llamará Scripts (en realidad puede tener cualquier nombre pero es mejor ser ordenados, tu yo del futuro te lo agradecerá), dentro de dicha carpeta recurriremos a crear un C# Script, yo lo llame PlayerMovement.cs.

Unity_Zqk3QjfkQA.png

Las opciones extras que me sale en Script son una forma modificada que hice en mi Unity, ustedes deben buscar es una opción llamada C# Script.

Unity_wwI36fYCLv.png

Unity_pxD2qVJyCY.png

No olvide agregar el Script a la imagen, con solo arrastrarlo a la imagen funciona.

Abrimos el archivo recientemente creado con doble clic y abrira su IDE principal para ese archivo, Unity funciona muy bien con Visual Studio Community o Code, Rider, Sublime Text; en fin, este seria un codigo ejemplo de moviendo el personaje hacia arriba, lo más básico.

using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
    [SerializeField] private float movementSpeed = 5f;
private void Update()
{
    if (Input.GetKey(KeyCode.W)) // Esto mueve el personaje hacia arriba
    {
        this.transform.Translate(Vector3.up * (movementSpeed * Time.deltaTime));
    }
}

}




¿Qué hace [SerializeField]?

Esto logra resaltar elementos privados en el Inspector de Unity (este Atributo solo puede ser utilizado en clases heredadas de MonoBehaviour).

¿Para que sirve la función Translate()?

Es una funcion interna de Transform, es un componente de MonoBehaviour que maneja la posición del objeto, en pocas palabras la posición de la imagen de la nave, con Translate se modificar en tiempo real dicha posición enviándole un nuevo Vector3 (X,Y,Z), por ello le mando un Vector3.up que es igual a (0, 1, 0) es decir ira hacia arriba, multiplicado por la velocidad que tiene la nave por el tiempo del juego.


Ahora que tenemos el movimiento hacia arriba, prosigamos a los movimientos en las otras distintas direcciones.

    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            this.transform.Translate(Vector3.up * (movementSpeed * Time.deltaTime));
        }
    if (Input.GetKey(KeyCode.A))
    {
        this.transform.Translate(Vector3.left * (movementSpeed * Time.deltaTime));
    }
    
    if (Input.GetKey(KeyCode.D))
    {
        this.transform.Translate(Vector3.right * (movementSpeed * Time.deltaTime));
    }
    
    if (Input.GetKey(KeyCode.S))
    {
        this.transform.Translate(Vector3.down * (movementSpeed * Time.deltaTime));
    }
}

Esto funcionara sin ningún problema, pero sigue siendo un poco tosco y nos debemos valer de muchas comprobaciones en cada iteración del Update(), por ello recurriremos a encapsular en varios métodos para que sea mas comodo y cumpla la simple responsabilidad.

using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
    private const string INPUT_HORIZONTAL = "Horizontal", INPUT_VERTICAL = "Vertical";   
    [SerializeField] private float movementSpeed = 5f;
private Vector3 GetVerticalMove(float direction) => new Vector3(0, direction, 0);
private Vector3 GetHorizontalMove(float direction) => new Vector3(direction, 0, 0);

private void MoveVertical(Vector3 position)
{
    this.transform.Translate(position * (movementSpeed * Time.deltaTime));
}

private void MoveHorizontal(Vector3 position)
{
    this.transform.Translate(position * (movementSpeed * Time.deltaTime));
}

private void Move()
{
   MoveVertical(GetVerticalMove(Input.GetAxis(INPUT_VERTICAL)));
   MoveHorizontal(GetHorizontalMove(Input.GetAxis(INPUT_HORIZONTAL)));
}

private void Update()
{
    Move();
}

}

Como se puede apreciar dividí los métodos de movimientos en varias secciones, unas que comprueba la dirección Horizontal y otra la Vertical, Unity por defecto detecta que las teclas WASD o las flechas direcciones, e incluso las palancas de un Joystick como desplazamiento Horizontal y Vertical, por ello utilizaremos una funciona estática de Unity llamada Input.GetAxis(string) donde le pasamos el axis que queremos utilizar en un string que en la parte superior los asigne como constantes INPUT_VERTICAL e INPUT_HORIZONTAL, dicha función regresa un float de valor -1, 0 (si no se presiona) y 1, el cual podemos utilizar como lo que haciamos con Vector.up, Vector.right, Vector.left, Vector.down, lo cual lo asigne a unas funciones separadas que son GetVerticalMove(float) y GetHorizontalMove(float), ellos devuelven un Vector3 que usaremos en el transform.Translate prácticamente.


Resultado final

zYY5agZ7Y2.gif

Como es apreciable la nave se mueve, su velocidad es modificable en tiempo real y antes de su ejecución; ya tenemos nuestra nave y la primera señal de vida a nuestro videojuego.

Próximamente trabajaremos en este proyecto y daré una versión mas elaborada como seguimiento de cámara, colisiones, consumibles en el juego, enemigos y mucho mas para armar tu primer juego en 2D.


Las imagenes utilizadas en este proyecto son propiedad publica, y han sido desarrolladas por Kenney.

Gracias por leerme, puedes ubicar más de mi contenido en las redes...

No olvides comentar si hay alguna duda, si deseas dejar un feedback o solamente agradecer, esto me motiva a seguir haciendo este tipo de guias.

Sort:  

Congratulations @aesthezel! You have completed the following achievement on the Hive blockchain and have been rewarded with new badge(s) :

You distributed more than 10 upvotes.
Your next target is to reach 50 upvotes.

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

Check out the last post from @hivebuzz:

Feedback from the March 1st Hive Power Up Day