Ejercicio: First Person Shooter (haciéndolo desde cero)

Curso de Unity 3D

21.  
40.  

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.

Movimiento básico

1. Creamos un Plane y lo aplanamos para el suelo.

2. Añadimos un cubo que será nuestro player.

3. Al cubo le añadimos el componente CharacterController.

4. Al cubo le vinculamos el siguiente código que hará que se mueva:

public class PlayerController : MonoBehaviour{
  float mX, mZ, mouseX, mouseY, rotationX;
  CharacterController characterController;

  void Start(){
    characterController = GetComponent<CharacterController>();
  }

  void Update(){
    Movement();
  }

  void Movement(){
    mX = Input.GetAxis("Horizontal");
    mZ = Input.GetAxis("Vertical");
    Vector3 movement = transform.right * mX + transform.forward * mZ;
    characterController.Move(movement * Time.deltaTime);
  }
}

Definimos una variable para la velocidad del movimiento

characterController.Move(movement * speed* Time.deltaTime);

Rotación en función del ratón

Rotación básica

void Rotation(){
    mouseX = Input.GetAxis("Mouse X");
    mouseY = Input.GetAxis("Mouse Y");
    rotationX -= mouseY;
    camera.localRotation = Quaternion.Euler(rotationX, 0, 0);
    transform.Rotate(Vector2.up * mouseX);
}

Añadimos sensibilidad

mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.deltaTime;
mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.deltaTime;

Limitamos el rango de movimiento del ratón

rotationX = Mathf.Clamp(rotationX, -90f, 90f);

Hacemos desaparecer el cursor

Este paso será especialmente importante en pasos sucesivos.

Cursor.lockState = CursorLockMode.Locked;

El arma

Añadimos un prisma rectangular que será la pistola y una esfera que será la mira con el objetivo al que estamos apuntando.

Ejercicio: First Person Shooter (haciéndolo desde cero) 1

Completamos el código del player con el siguiente código:

void Update(){
    ...
    Raycast();
}

void Raycast(){
    // Esto tira un rayo desde la cámara
    Ray ray = new Ray(playerCamera.position, playerCamera.forward);
    Vector3 target;
    // Si el rayo colisiona con algo, alimentamos la variable targetHit
    if(Physics.Raycast(ray, out RaycastHit targetHit, Mathf.Infinity)){
      target = targetHit.point;
    }

    shotTarget.position = target;
}

Corregir el problema de que el punto de mira no se mueve cuando no colisiona contra nada

else{
      target = ray.origin + ray.direction * 1000;
}

Instanciar una bala

Creo un empty en el extremo de la pistola.

void Shot(){
    if (Input.GetButtonDown("Fire1")){
      GameObject bullet = Instantiate(bulletPrefab, shotOrigin.position, Quaternion.identity);
    }
}

Aplicando velocidad a la bala

bullet.transform.LookAt(shotTarget.transform.position);
Bullet.js
public class Bullet : MonoBehaviour{
  int speed = 7;

  void Update(){
    transform.position += transform.forward * speed * Time.deltaTime;
  }
}

Destruir la bala cuando colisione

Pondremos la propiedad isTrigger del Box Collider de la bala a true;

private void OnCollisionEnter(Collision collision){
    if(collision.gameObject.tag == "World" || collision.gameObject.tag == "Enemy") {
    	Destroy(gameObject);
    }
}

Destruir la bala al cabo de un tiempo (por si la bala no colisionó contra nada)

float timer;
void Update(){
	...

	timer += Time.deltaTime;

	if(timer >= 10){
		Destroy(gameObject);
	}
}

Salto

Añadimos gravedad

Vector3 fallSpeed;
float gravity = -9.81f;


void Jump()
{
    fallSpeed.y += gravity * Time.deltaTime;
    characterController.Move(fallSpeed * Time.deltaTime);
}

Evitamos que la gravedad se acumule mientras que el player está en el suelo

bool grounded;
public LayerMask groundMask;
float groundDistanceTest = 0.3f;

void Jump(){
    grounded = Physics.CheckSphere(groundTester.position, groundDistanceTest, groundMask);
    if (grounded && fallSpeed.y < 0) fallSpeed.y = -2f;

Debemos vincular a una layer llamada Ground, el suelo y los objetos que haya en él.

Ejercicio: First Person Shooter (haciéndolo desde cero) 2

También debemos indicar el valor de la propiedad ground (de tipo LayerMask en el player).

Ejercicio: First Person Shooter (haciéndolo desde cero) 3

Saltar

void Jump(){
	grounded = Physics.CheckSphere(groundTester.position, groundDistanceTest, groundMask);
	if (Input.GetKeyDown(KeyCode.Space) && grounded){
		fallSpeed.y = Mathf.Sqrt(5 * -2f * gravity);
	}

Gestión de la vida

Añadimos una bala a la escena y le deshabilitamos el código. Reducimos la variable de vida cuando el player colisione contra ella.

private void OnTriggerEnter(Collider other){
	if(other.gameObject.tag == "Bullet"){
		Destroy(other);
		life--;
		print(life);
    }
}

Vamos a implementar la barra de vida siguiendo las instrucciones del videojuego de plataformas.

Morir

if(health <= 0)
{
        print("Morir");
}

Añadir modelo 3D

Sin animación

Para descargar nuestro personaje, iremos a Mixamo. Tener en cuenta que:

  • Los personajes rojos son y chicas y los azules, chicos.

De Mixamo debemos descargar:l modelo sin animaciones. Cojeremos los formatos .dae y .fbx. Realmente, el fichero dae no es necesario, pero dentro de su empaquetado vendrá una carpeta con texturas.

En Unity:

1. Seleccionaremos en el panel de proyecto el fichero del modelo → panel inspector → Rig → Animation Type: Humanoid.

Añadimos el modelo a la escena.

Arrastramos los GameObject hijos de Player al Modelo añadido a la escena.

Arrastramos los componentes de Player al Modelo añadido a la escena.

Debemos hacer algunos ajustes para que todo esté correcto:

  • Ajustamos el tamaño de la capsula del Character Controller para que se ajuste al tamaño del modelo. Para ello cambiaremos el valor de sus propiedades X, Y, etc..
  • Ajustamos la posición de la MainCamera a la posición de la cabeza del personaje.

Animaciones

Vamos a mixamo y descargamos una animación de un personaje andando(walking) y en reposo (idle). En el momento de la descarga, marcaremos la check de inplace. Para las animaciones, descargaremos sólo los ficheros fbx for Unity.

1. Seleccionaremos en el panel de proyecto el fichero del modelo y de la animación → panel inspector → Rig

  • Animation Type: Humanoid.
  • Avatar Definition: Copy From Other Avatar → Source: arrastraremos ‘The Boss Avatar’.
Ejercicio: First Person Shooter (haciéndolo desde cero) 4

3. Seleccionaremos en el panel de proyecto el fichero del modelo y de la animación → panel inspector → Animation → Marcamos las checks de Back Into Pose para Root Transform Rotation, Root Transform Position (Y), Root Transform Position (XZ). Desmarcamos la check de mirror.

3. Creamos una carpeta Animations para las animaciones en 3D.

4. Desplegamos el fichero de Mixamo. Seleccionamos el objeto de la animación. Lo duplicamos (ctrl + d). Arrastramos el duplicado a la carpeta recién creada.

Ejercicio: First Person Shooter (haciéndolo desde cero) 5

5. Vamos al panel Animator. Botón derecho → Create StateFrom New Blend Tree

6. En el panel Animator añadimos dos nuevos parámetros de tipo Float: x e y.

7. Hacemos doble click sobre el estado recién creado. Pulsamos sobre el Blend Tree. En el panel inspector:

  • Blend Type: 2D Freeform Directional.
  • Parameters: x, y

  • Añadimos tres campos Motion. Para ello, vamos a la propiedad Motion y le damos a la cruceta → Add Motion Field. Arrastramos las animaciones correspondientes y lo dejamos configurado de la siguiente manera:
Ejercicio: First Person Shooter (haciéndolo desde cero) 6

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.