jairogarcíarincón
Para crear los disparos, vamos a utilizar un Game Object vacío al que aplicaremos unos efectos visuales, de modo que si queremos cambiar de arma solo tenemos que cambiar esos efectos visuales y podemos seguir usando el mismo contenedor:
- Desactiva la Nave desde su Inspector window para que no nos moleste.
- Crea un Empty Game Object y llámalo Disparos.
- Resetea su posición.
- Dentro de él, crea un 3D Object > Quad y llámalo VFX.
- Rota el objeto VFX 90º en el eje X.
- Crea un nuevo Material dentro de Materials y llámalo FX Naranja.
- Selecciona FX Naranja y desde su Inspector window, haz clic en el círculo a la izquierda de Albedo
- En el desplegable, selecciona la textura fx_lazer_orange_dff.
- Arrastra el Material FX Naranja al Quad VFX.
- Selecciona VFX y cambia el Shader a Legacy shaders > Particles > Additive para eliminar el negro de la textura.
- El resultado debería ser similar a este:
Los disparos se moverán mediante física y además incluirán un Box Collider, con lo que debemos:
- Añadir a nuestro objeto contenedor Disparos un Rigidbody y desactiva la propiedad Use Gravity.
- Eliminar el Mesh Collider de nuestro Quad VFX para que no haya dos.
- Añadir a nuestro objeto contenedor Disparos un Capsule Collider y hacer clic en Edit Collider para ajustarlo a nuestro laser: Direction a Z-Axis, Radius a 0.03 y Height a 0.5.
- Añadir la propiedad Is Trigger a la Capsule Collider
Para poder mover los disparos, debemos asociar a Disparos un nuevo C# script llamado DisparosController con el siguiente código:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DisparosController : MonoBehaviour {
//Declarlo la variable de tipo RigidBody que luego asociaremos a nuestro objeto
private Rigidbody rb;
//Declaro la variable pública velocidad para poder modificarla desde la Inspector window
[Range(10,30)]
public float velocidad = 20;
void Start () {
//Capturo el rigidbody del jugador al iniciar el juego
rb = GetComponent<Rigidbody>();
//Aplico movimiento en dirección z positiva (con su velocidad)
rb.velocity = transform.forward * velocidad;
}
}
Para finalizar, vamos a arrastrar el objeto Disparos dentro de la carpeta Assets > Prefabs.
De este modo, hemos creado un Prefab para los Disparos, ya que solo querremos una instancia de nuestro disparo en la escena simultáneamente.
Si ahora borras el objeto Disparos de la Hierarchy window, guardas la escena, ejecutas el juego y arrastras instancias del Prefab a la Hierarchy window, verás como se mueven hacia arriba y desaparecen.
Activa de nuevo la Nave para verla en la escena.
Crea un Empty Object llamado Disparador, resetea su posición y arrástralo dentro de la Nave para que se mueva con ella.
Modifica la Transform de Disparador para que este delante de la nave (Z = 1).
Edita el script JugadorController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NaveController : MonoBehaviour {
//Declarlo la variable de tipo RigidBody que luego asociaremos a nuestro objeto
private Rigidbody rb;
//Declaro la variable pública velocidad para poder modificarla desde la Inspector window
[Range(5,15)]
public float velocidad = 10;
//Límites del juego
float xMin = -5.8f;
float xMax = 5.8f;
float zMin = -3.7f;
float zMax = 13.5f;
//Declaro la variable pública giro para poder modificarla desde la Inspector window
[Range(-1,-10)]
public float giro = -4;
//Declaro la variable de tipo GameObject que luego asociaremos a nuestro prefab Disparos
public GameObject disparo;
//Declaro la variable de tipo Transform para la posición del disparador
public Transform disparador;
//Declaro la variable de tipo float velocidadDisparo para la velocidad con la que puedo generar disparos
[Range(0,1)]
public float velocidadDisparo = 0.25f; //4 por segundo
//Tiempo que tiene que transcurrir hasta el próximo disparo
private float proximoDisparo;
void Start () {
//Capturo el rigidbody del jugador al iniciar el juego
rb = GetComponent<Rigidbody>();
}
//Esto lo ejecuta antes de actualizar el último frame
void Update () {
if (Input.GetButton("Fire1") && Time.time > proximoDisparo){
//Incremento el valor de proximo disparo
proximoDisparo = Time.time + velocidadDisparo;
//Instancio un nuevo disparo en esa posición y con esa rotación
Instantiate(disparo, disparador.position, disparador.rotation);
}
}
// Porque voy a utilizar la física para moverlo
void FixedUpdate () {
//Capturo el movimiento en horizontal y vertical de nuestro teclado
float movimientoH = Input.GetAxis("Horizontal");
float movimientoV = Input.GetAxis("Vertical");
//Genero el vector de movimiento asociado, teniendo en cuenta la velocidad
Vector3 movimiento = new Vector3(movimientoH * velocidad, 0.0f, movimientoV * velocidad);
//Aplico ese movimiento al RigidBody de la nave
rb.AddForce(movimiento);
//Restrinjo la posición de la nave a los límites del juego
rb.position = new Vector3
(
Mathf.Clamp (rb.position.x, xMin, xMax),
0.0f,
Mathf.Clamp (rb.position.z, zMin, zMax)
);
//Rotación de la nave en Z en función de la velocidad en X
rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * giro);
}
}
Para finalizar, arrastra el prefab Disparos a la variable Disparo y el objeto Disparador a la variable Disparador.
En esta situación, deberías poder disparar (con el botón izquierdo del ratón, aunque lo puedes modificar en Edit > >Preferences > Input), si bien observarás que se generan un montón de disparos en la Hierarchy window, algo que solucionaremos a continuación.
Una vez que el disparo ha salido del campo de juego, es ineficiente seguir manteniéndolo en el juego, y de hecho podríamos llegar a consumir los recursos del sistema.
Por este motivo, debemos buscar la manera de eliminar los disparos cuando lleguen a una posición determinada o, dicho de otro modo, debemos establecer unos límites de vida del disparo.
Dado que nos encontraremos con el mismo problema cuando creemos enemigos, etc., la mejor forma de conseguirlo será creando una "caja" de modo que todo lo que se salga de ella será destruido.
- Crea un nuevo 3D object > Cube y llámalo Limites.
- Resetea su posición y activa la propiedad Is Trigger del Box Collider.
- Ajusta Position XYZ a 0, 0, 5 y Scale XYZ a 15, 1, 20.
- Elimina los componentes Mesh Renderer y Mesh Filter, para quedarnos solo el Box Collider.
El resultado deber ser similar a este:
Crea un nuevo C# script llamado DestruirPorLimites dentro de Assets > Scripts con el siguiente código y añádelo al objeto Limites:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestruirPorLimites : MonoBehaviour {
//Al salir de la colisión
void OnTriggerExit(Collider other){
//Destruyo el objeto
Destroy(other.gameObject);
}
}
De este modo podremos comprobar que al disparar, cuando los disparos llegan al límite se auto-destruyen. en el siguiente apartado crearemos enemigos y de nuevo utilizaremos este script para destruirlos cuando se salgan de los límites.
Publicado el 30 de Enero de 2025
unityspace shooter