Creare un Proiettile in Unity
Di solito, nei videogiochi, per implementare un proiettile si preferisce utilizzare il raycasting anziché la fisica tradizionale. In particolare, Unity aggiorna il movimento fisico ad ogni intervallo, detto “physics ticks”1. Se la velocità del proiettile è superiore alla frequenza di aggiornamento di questi intervalli, potrebbe verificarsi una situazione in cui una collisione tra il proiettile e un oggetto non viene intercettata. Per questo motivo, nelle prossime righe capiremo meglio come avere migliore precisione e maggior controllo di ciò che accade al proiettile.
Il raycasting è una tecnica utilizzata per proiettare raggi nella scena da una sorgente verso una particolare direzione, al fine di individuare gli oggetti intercettati lungo il loro percorso.
Vediamo nel dettaglio come tutto questo possa tornarci utile per il nostro sistema di sparo:
- Creazione della classe Proiettile.
public class Projectile : MonoBehaviour {
public float speed = 10f;
public LayerMask layerToHit;
public float damageRadius = 0.5f;
public int damage = 10;
public GameObject hitEffectPrefab; // Prefab dell'effetto visivo di collisione
public AudioSource audioSource;
}
Dichiarazioni delle variabili
- Il Proiettile viene sparato dall’arma verso il punto mirato. Questo proietta a sua volta un raggio di breve distanza davanti a sé per intercettare eventuali collisioni con superfici e oggetti. Durante il calcolo della traiettoria del colpo, è molto importante moltiplicare la velocità di movimento del proiettile per Time.deltaTime, una variabile statica di Unity che rappresenta la frazione di tempo impiegata per completare l’ultimo frame di gioco. Così si ha la garanzia di avere un movimento costante e fludio dell’oggetto frame dopo frame.
private void Update()
{
// Calcolo frame dopo frame la posizione del proiettile nella scena
Vector3 movement = transform.forward * speed * Time.deltaTime;
transform.position += movement;
// Eseguo un raycast dalla posizione del proiettile verso la direzione in cui sta puntando
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, movement.magnitude, layerToHit))
{
//Se il raggio colpisce qualcosa, gestiamo la collisione
HandleCollision(hit);
}
}
Istruzioni eseguite per ogni frame
- È essenziale gestire i diversi scenari in cui il raggio interseca un oggetto di gioco. Quando il raggio si scontra con un oggetto lungo il suo percorso, si registra il punto di impatto del proiettile con l’oggetto colpito nella variabile hit. Successivamente, vengono applicati gli effetti dell’impatto, che possono comprendere aspetti logici (come la riduzione della vita del nemico), visivi (quali la traccia del proiettile, il foro e l’esplosione dell’impatto) e sonori (come il suono dello sparo).
private void HandleCollision(RaycastHit hit)
{
// Se l'oggetto colpito possiede il componente Health, allora lo uso
// per aggiornare il valore della vita del nemico Health healthComponent;
if (hit.transform.TryGetComponent<Health>(out Health healthComponent))
healthComponent.TakeDamage(damage);
// Istanzia l'effetto di impatto nel punto di collisione
if (hitEffectPrefab != null)
Instantiate(hitEffectPrefab, hit.point, Quaternion.LookRotation(hit.normal));
//Aggiungi l'effetto sonoro
if (audioSource != null)
audioSource.Play();
// Distruggi il proiettile dopo la collisione
Destroy(gameObject);
}
Metodo che gestisce la collisione e applica gli effetti visivi e sonori
Link utili:
L’unità di tempo in cui il motore fisico aggiorna lo stato della simulazione fisica. ↩︎