Programmare in C# – Unity e Raycast
In questo tutorial impareremo a utilizzare i Raycast in Unity3D.
Definizione di un Raycast
Innanzitutto, dobbiamo chiederci cos’è un Raycast. Per dirla con parole semplici, il Raycast potrebbe essere paragonato a un raggio di luce che va in linea retta su una data distanza.
Questo raggio ci consentirà di verificare se si viene a contatto con un altro oggetto, un tag o strati. Saremo in grado di filtrare molto finemente la collisione Raycast. In effetti, fa parte delle funzionalità relative alla fisica di Unity3D.
Con il Raycast, saremo in grado di gestire molte cose.
Vediamo alcuni esempi:
- Controllare una distanza tra il giocatore e un oggetto/terreno
- Creare un sistema di destinazione per le armi
- Sistema di visione alla “Metal Gear Solid“, per rilevare il giocatore
- Migliorare le collisioni. Non è necessario sapere come usarli, ma aiuta lo sviluppo dei giochi. I raycast possono essere utilizzati sia per giochi 3D che 2D.
Presentazione del tutorial
In questo tutorial, ci assicureremo di rilevare se il nostro giocatore è sul suolo o meno. Se è a terra, allora potrà saltare.
Ora, useremo i raycast in un progetto 3D, ma la procedura è esattamente la stessa in 2D.
L’unica cosa che cambia è il nome delle classi da utilizzare, infatti dobbiamo aggiungere 2D alla fine e gestire il Physic 2D.
Non vi mostreremo come realizzare un sistema di salto complesso, ma ne vedremo uno semplice, usando la fisica di RigidBody.
Per fare ciò, iniziamo a creare o aprire il nostro progetto Unity3D.
Creare la scena
Per questo tutorial avremo bisogno di molte cose: una scena, un suolo e un giocatore.
Per il pavimento, un Plane sarà sufficiente.
Creazione del giocatore
Creiamo una capsula che fungerà da giocatore e aggiungiamoci una componente RigidBody. Questa componente viene utilizzata per gestire la fisica dell’oggetto.
Per evitare di avere un risultato “strano” durante il nostro test, bisognerà selezionare Constraints, Freeze Rotation X, Y e Z.
Quindi dovreste avere una scena che assomiglia a questa:
Lo script
Ora che abbiamo tutti gli elementi necessari per il nostro esempio, è arrivato il momento di scrivere alcune righe di codice per far funzionare tutti questi elementi.
Riprendiamo l’obiettivo del tutorial: vogliamo far saltare il nostro giocatore, ma solo e soltanto se non sta già saltando.
Per cominciare, creeremo il sistema di salto creando uno scriptPlayerController. Per fare ciò, bisognerà semplicemente cliccare con il tasto destro su Crea>Script C# e inserire il nome del file. Una volta fatto ciò, bisognerà fare doppio clic sul file per aprirlo nell’editor.
(Piccola parentesi, per l’editor, vi consigliamo di installare Visual Studio, che è più piacevole per sviluppare rispetto a MonoDevelop.)
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float jumpPower;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetButtonDown("Jump"))
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
}
Quindi, secondo voi, qual è il senso di questo codice?
Bene, RequireComponent (typeof (Rigidbody)) è semplicemente un vincolo per forzare il giocatore ad avere sempre un RigidBody.
Questa riga non è obbligatoria, ma quando si sviluppa, può essere utile perché evita degli errori se si dimentica un componente su un oggetto.
[SerializeField] private float jumpPower; questa linea viene utilizzata per rispettare la programmazione orientata agli oggetti. SerializeField consente di visualizzare il valore jumpPower nell’editor anche se è privato. jumpPower determina la potenza del salto effettuato dal giocatore.
Avremmo potuto scrivere: public float jumpPower;
rb = GetComponent<Rigidbody>(); otteniamo la componente RigidBody del player.
Per quanto riguarda la parte Update, possiamo rilevare se il pulsante Jump viene premuto (Jump è configurato in Project Settings > Input). rb.AddForce si apre in base alla variabile jumpPower e il tipo di forza applicata è un impulso.
Implementare il Raycast
Caspita è fantastico, abbiamo un personaggio che salta !!! 🙂 Ma il problema è che può saltare all’infinito! Con il codice seguente, saremo in grado di rilevare il suolo e correggerlo.
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float jumpPower;
[SerializeField]
private float rayDistance;
[SerializeField]
private LayerMask layers;
private Rigidbody rb;
private bool grounded;
void Start()
{
rb = GetComponent();
}
void Update()
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, rayDistance, layers))
{
grounded = true;
}
else
{
grounded = false;
}
if (grounded && Input.GetButtonDown("Jump"))
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
}
rayDistance è la distanza massima di Raycast, la lunghezza del raggio.
layer è l’elenco dei layer correlati alla fisica, ad esempio, useremo il layer Default.
grounded è la variabile che determina se tocchiamo il terreno o meno.
Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, rayDistance, layers)) è il test di collisione.
Prima di determinare, in quale direzione verrà proiettato il Raycast, inizieremo a recuperare la posizione del giocatore. Quindi, memorizzeremo i dati nella variabile “hit” per successive elaborazioni, senza dimenticare di applicare la distanza ed elencare i layers.
Nell’editor, è possibile selezionare i layers utilizzati dal giocatore.
Ecco i valori che abbiamo inserito nell’editor:
Debug del Raycast
Dopo aver configurato il sistema Raycast, vedremo se questi sono proiettati correttamente. Aggiungeremo dunque questa riga nell’Update():
Debug.DrawRay (transform.position, transform.TransformDirection (Vector3.down) * rayDistance, Color.red);
È possibile notare che le impostazioni sono le stesse del Raycast.
Se iniziamo il gioco e saltiamo, e poi guardiamo il gioco nella scheda della Scena, possiamo vedere il nostro Raycast come una linea rossa:
Ecco il codice completo per il giocatore:
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float jumpPower;
[SerializeField]
private float rayDistance;
[SerializeField]
private LayerMask layers;
private Rigidbody rb;
private bool grounded;
void Start()
{
rb = GetComponent();
}
void Update()
{
RaycastHit hit;
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.down) * rayDistance, Color.red);
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, rayDistance, layers))
{
grounded = true;
}
else
{
grounded = false;
}
if (grounded && Input.GetButtonDown("Jump"))
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
}
Conclusione
Come detto in precedenza, le possibilità di utilizzo sono varie e illimitate.
Il codice sorgente del tutorial è qui sopra. Se avete bisogno di chiarimenti, non esitate a commentare di sotto all’articolo.