Saltar y gravedad

En este post aprenderemos cómo hacer que el personaje salte y tenga gravedad.

Empezaremos por crear una variable pública de tipo float llamada jumpSpeed a la que asignaremos un valor igual a 20 que nos servirá para ajustar la altura del salto (public float jumpSpeed = 20;) y una variable pública de tipo float llamada gravity a la que asignaremos un valor igual a 9,8 (el valor de la gravedad terrestre) que indicará la gravedad que afecta a nuestro personaje, recordad poner la f para valores decimales (public float gravity = 9.8f;).

A continuación crearemos una sentencia if que aplique la gravedad a nuestro personaje cuando no esté tocando el suelo. Para ello comprobaremos el valor de la variable tipo bool isGrounded dentro de la clase CharacterController, que será true si el personaje está tocando el suelo. Como queremos aplicar la gravedad si no está en el suelo la sentencia if quedaría if (!controller.isGrounded) . El signo de exclamación ‘!’ indica negación. A la hora de aplicar la gravedad básicamente tendremos que restar a nuestro movimiento en el eje Y el valor de la variable gravity, de modo que quedaría currentMovement -= new Vector3 (0, gravity * Time.deltaTime, 0); . Cuando restamos o sumamos vectores entre sí los valores de cada componente afectan únicamente a su equivalente dentro de cada vector, es decir, eje X con eje X, Y con Y y Z con Z. Si realizamos una prueba con nuestro personaje levantándolo del suelo, veremos que la caída será muy lenta. Esto se debe a que en nuestro código el vector currentMovement se está igualando a 0 en el eje Y en cada frame. Para solucionar esto asignaremos al vector currentMovement el valor del eje Y que tenía en el frame anterior, para ello escribiremos el código currentMovement = new Vector3 (0, currentMovement.y, Input.GetAxis ("Vertical") * moveSpeed);.

code1gravity

Otra opción sería eliminar esta línea de código y modificar solamente la variable del eje Z de nuestro vector currentMovement que es la que afecta a nuestro movimiento (currentMovement.z = Input.GetAxis ("Vertical") * moveSpeed;). Además, para evitar una rotación infinita deberíamos igualar la variable del eje X a 0 (currentMovement.x = 0;).

code2gravity

Tenemos que tener en cuenta que con este código el valor del eje Y del vector currentMovement se decrementará cada vez que el personaje no esté tocando el suelo. Para evitar que este decremento se almacene e influya en la siguiente vez que el personaje no esté en el suelo, tenemos que igualar a 0 cada vez que entre en contacto con el suelo. Para ello recurriremos a la sentecia if-else de manera que si el objeto no está en contacto con el suelo le aplique la gravedad, pero si está en contacto con el suelo restablezca el valor del eje Y del vector currentMovement a 0. Para ello escribiremos a continuación del else lo siguiente: currentMovement.y = 0;.

ifelse

Para añadir la opción de salto realizaremos una sentencia if que compruebe que el personaje está en el suelo y que el usuario pulsa la tecla de salto, para ello el código sería if (controller.isGrounded && Input.GetButtonDown ("Jump")). A continuación escribiríamos el código currentMovement.y = jumpSpeed; que añadirá a la componente Y del vector currentMovement el valor de la variable jumpSpeed que provocará que nuestro personaje salte. Comprobaremos que a veces al darle a la barra espaciadora nuestro personaje no saltará. Esto se debe a que el juego toma los datos al inicio de cada frame y puede cuadrar que no recoja la información al presionar la tecla de salto. Esto lo corregiremos con unas pocas líneas de código posteriormente. Nuestro código final quedaría así:

using UnityEngine;
using System.Collections;

public class PlayerScript : MonoBehaviour {

public float moveSpeed = 5;
public float rotateSpeed = 180;
public float jumpSpeed = 20;
public float gravity = 9.8f;
CharacterController controller;
Vector3 currentMovement;

void Start () {

controller = GetComponent<CharacterController> ();
}

void Update () {

transform.Rotate (0, Input.GetAxis ("Horizontal") * rotateSpeed * Time.deltaTime, 0);

currentMovement = new Vector3 (0, currentMovement.y, Input.GetAxis ("Vertical") * moveSpeed);
currentMovement = transform.rotation * currentMovement;

if (!controller.isGrounded)
currentMovement -= new Vector3 (0, gravity * Time.deltaTime, 0);
else
currentMovement.y = 0;

if (controller.isGrounded && Input.GetButtonDown ("Jump"))
currentMovement.y = jumpSpeed;

controller.Move (currentMovement * Time.deltaTime);
}
}

Por último, crearemos un nivel de prueba para probar la funcionalidad del salto mediante el uso de varios cubos a distinta altura sobre los que saltar. Ajustaremos la gravedad y la variable jumpSpeed para configurar nuestro salto y la velocidad de caída. Y para organizar las cosas en Hierarchy crearemos un objeto vacío (Create->Create Empty) al que llamaremos Level y arrastraremos dentro de él los cubos, el suelo y la luz.

leveltestjump

Deja un comentario