First Person Controller en Unity

First Person Controller en Unity

En este post aprenderemos a crear un First Person Controller en Unity, desde cero.

Generalmente el movimiento en Unity se puede hacer de dos formas:

-Usando el RigidBody

-Usando el Character Controller

Cada uno tiene sus ventajas dependiendo de lo que queramos. Es decir, no existe un controlador de movimiento universal, ya que dependiendo del juego puede variar.

Character Controller

  • Controlar los pasos
  • Controlar las pendientes
  • No te sueles quedar enganchado en las paredes

Rigidbody

  • Gravedad
  • Arrastre incorporado
  • Interactúa con objetos físicos

En nuestro caso vamos a utilizar el Character Controller. Primero de todo vamos a generar un plano por donde avanzará nuestro player, y añadiremos un empty GameObject, con el Character Controller.

Para visibilizar nuestro player añadiremos un cilindro como hijo del empty, y le quitaremos el collider, ya que el Character Controller ya nos lo ofrece. Y al ser un personaje en primera persona, la cámara también será hijo del FirstPersonController, para que compartan la misma posición.

Para crear nuestro controlador vamos a necesitar dos scripts, uno para el movimiento de la cámara y otro para el movimiento del player.

Mouse Look.cs

A continuación, vamos a crear el primer script para controlar hacia donde miramos, añadiéndolo en la cámara. Vamos a usar el ratón para escoger la dirección. El mouse tiene dos ejes X e Y, si movemos a derecha e izquierda con el ratón estaremos modificando el eje X, y si movemos de arriba a abajo modificaremos el eje Y.

Cuando modifiquemos la X de nuestro ratón queremos que nuestro personaje rote en el eje Y

Y para el eje Y del ratón modificaremos la rotación de la cámara en X. Para entenderlo mejor, tenemos que verlo desde Unity:

También deberemos marcar unos límites en la rotación de la cámara.

Una vez creado el script, vamos a crear dos floats que nos vayan a indicar la posición de nuestro ratón, en Y y en X. Unity nos incluye en Edit/ProjectSettings/InputManager una serie de controles que nos sirven para detectar el Input de ciertos botones, mostrar ciertas posiciones del ratón… en este caso con el Input.GetAxis(“Mouse X”) y el Input.GetAxis(“Mouse Y”) nos devuelve el número de píxeles que se ha movido el ratón desde la última posición que tenía. Estos números los vamos a multiplicar por una sensibilidad 100 y por el tiempo de cada frame.

Ya tenemos iniciadas las 2 variables, estas tienen que modificar la rotación de nuestro personaje así que crearemos la variable playerBody de tipo Transform, cogemos el Transform de nuestro jugador y rotaremos en el eje Y (Vector3.up) y la multiplicaremos por el movimiento del ratón en X.

Nuestro personaje ya rota en la Y moviendo el mouse en el eje X, ahora solo queda hacia arriba o hacia abajo. Crearemos otra variable tipo float para registrar el giro de X de la cámara, haremos el cálculo poniéndole unos límites y añadiremos en nuestra cámara esta rotación, al tener la cámara como hijo, necesitamos usar el localRotation.

Antes de pasar al movimiento podemos añadir una línea en el Start para que el cursor siempre aparezca en el centro de la pantalla.

Ya tenemos todas las rotaciones de nuestra cámara y player. A continuación, vamos a crear el script para el movimiento de nuestro player.

Player Movement.cs

Para explicar el movimiento debemos conocer el GetAxis(“Horizontal”) y el GetAxis (“Vertical”) funcionan como el mouse X y el mouse Y, pero en este caso no nos detectan las posiciones del ratón, sino que detectan cuando estamos pulsando A, D y flecha izquierda y derecha para GetAxis(“Horizontal”), devolviéndonos un -1 para la izquierda y un +1 para la derecha. Y W y S y las flechitas del teclado de arriba y abajo para el GetAxis(“Vertical”), también devolviendo un -1 y un +1.

Una vez sabemos esto, vamos a crear dos variables para la X y la Z que es el movimiento del jugador.

Seguidamente les proporcionaremos la dirección, usando el transform.right, nos coge el vector (1,0,0) y se lo multiplicamos a nuestra x (positivo o negativo depende que tecla estemos pulsando, ya que devuelve -1 o 1) y le sumaremos transform.forward, que nos coge el vector (0,0,1), multiplicado por z.  Con esta línea ya tenemos la dirección. (Si nos movemos hacia la derecha en el eje X este Vector3 será (1, 0, 0), si nos movemos hacia delante, el eje Z será (0, 0, 1)).

Para que se mueva nuestro personaje deberemos declarar una nueva variable de tipo Character Controller, ya que tiene un método para moverse.  Este método pide un Vector3, justo lo que ya tenemos creado. Este Vector3 lo vamos a multiplicar por una velocidad y que se mueva con el tiempo.

En este punto nuestro personaje ya se moverá correctamente y con completa libertad, pero falta añadir la gravedad. Vamos al script del player y añadiremos dos nuevas variables:

Vamos a escribir en el Update que la velocidad en Y, es decir la dirección de Y en este nuevo Vector3, es igual a esta velocidad multiplicada por la gravedad por el tiempo. Y se lo añadiremos al Character Controller como hemos hecho antes, afectando solo en el eje Y del player, pero multiplicando otra vez por el tiempo, ya que la gravedad se multiplica por tiempo al cuadrado.

Si nos fijamos en la variable de velocidad en Y, vemos que cada segundo se reduce en 9,81 y si nos cayésemos de cualquier sitio lo haríamos a muchísima velocidad, ya que no para nunca. Para corregir este problema, necesitaremos comprobar el suelo. Para comprobar que estamos tocando el suelo crearemos un objeto empty en los pies del jugador.

En este punto generamos una pequeña esfera que nos detectara si el objeto con el cual colisionó tiene una LayerMask determinada. Vamos a verlo a continuación, crearemos 4 variables.

En el Update, escribiremos la línea para que la booleana sea cierta cuando nuestra esfera colisione con la capa seleccionada. Si la esfera collisiona con la Capa “floorMask” y la velocidad en Y es negativa le pondremos el valor de Y será -2.

Para crear y añadir la capa debemos dirigirnos al inspector de Unity en Layer/Default/Add Layer, añadimos la nueva capa y se la seleccionamos a todos los objetos de nuestra escena.

Salto

Ahora ya solo nos quedaría añadir el salto a nuestro movimiento.

Para implementar el salto vamos a usar otro de los Inputs que nos proporciona Unity. Y le decimos que nos haga el salto si pulsamos la tecla de saltar y si está en el suelo. Usaremos una fórmula física para saltar la distancia que queramos: raíz cuadrada de la altura (3) que queremos saltar *-2 *gravedad.

Ya tenemos nuestro First Person Controller completo, quedaría algo así:

Mouse Look

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseLook : MonoBehaviour
{
    public float Sensibilidad = 100;
    public Transform playerBody;
    public float xRotacion;
    private void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
    }
    void Update()
    {
        float mouseX = Input.GetAxis("Mouse X")*Sensibilidad*Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y")*Sensibilidad*Time.deltaTime;

        xRotacion -= mouseY;
        xRotacion = Mathf.Clamp(xRotacion, -90, 90);

        transform.localRotation = Quaternion.Euler(xRotacion, 0, 0);
        
        playerBody.Rotate(Vector3.up * mouseX);
        print(xRotacion);
        
    }
}

Player Movement

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public CharacterController cc;
    public float Velocidad=12;

    public float Gravedad = -9.81f;
    public Vector3 velocity;

    public Transform groundCheck;
    public float groundDistance = 0.4f;
    public LayerMask floorMask;
    bool isGrounded;
    void Update()
    {
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, floorMask);
        
        if (isGrounded && velocity.y<0)
        {
            velocity.y = -2f;
        }

        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            velocity.y = Mathf.Sqrt(3 * -2 * Gravedad);
        }

        float x = Input.GetAxis("Horizontal");
        float z= Input.GetAxis("Vertical");

        Vector3 move = transform.right * x+transform.forward*z;
        cc.Move(move*Velocidad*Time.deltaTime);
        

        velocity.y += Gravedad * Time.deltaTime;
        cc.Move(velocity * Time.deltaTime);

    }
}

Si os ha sido de utilidad el First Person Controller, podéis echar un vistazo al Third Person Controller pulsando aquí.

10Comentarios

  • Siuk
    11/12/2022

    Hola, sabe que funciono todo menos el salto, no para de saltar

  • Robert
    24/01/2022

    Hola no se nada de programar aun así con el código no me deja hacer nada puedes mandar un link para descargar el proyecto solo con el controlador en primera persona?

  • Franco
    26/10/2021

    Hola como puedo hacer para que la cámara gire hacia los costado también, ya que solo se mueve en dirección arriba y abajo

    • Malilla
      09/12/2022

      Hola no me salen el Transform ni el input.get axis nose marcan de color y por ende no funciona al ejecutar el juego como agregó eso ???

  • Gabriel
    25/06/2021

    Hola , no se nada de unity. quiero aprender pero siempre me quedo atorado en esta parte y no puedo seguir. Aprendí un par de cosas siguiendo tus pasos pero solo pude hacer que la cámara se nueva hacia arriba y abajo. Pero no pude hacer que caminara.
    No entiendo la parte de Layer/Default/Add Layer, y al GroundCheck no se si hay que agregarle algo.

Escribe un comentario