Questo è il primo di due tutorial dedicati alla rotazione di un oggetto in modo da fargliene puntare un altro in Unity; in particolare, vedremo come fare in modo che il modello 3D di una telecamera di videosorveglianza si orienti automaticamente verso il Player, seguendo i suoi movimenti all'interno della scena.



Trascrizione del video

Salve a tutti!

Questo è il primo di due tutorial dedicati alla rotazione di un oggetto in modo da fargliene puntare un altro in Unity; in particolare, vedremo come fare in modo che il modello 3D di una telecamera di videosorveglianza si orienti automaticamente verso il Player, seguendo i suoi movimenti all'interno della scena.

Questo tutorial è stato realizzato utilizzando Unity 2022 ed è diviso in due parti.

Nella prima parte, analizzeremo il problema e lo affronteremo utilizzando il metodo Rotate per ottenere una rotazione istantanea della telecamera.

Nella seconda parte, invece, utilizzeremo i quaternioni e il metodo Slerp per realizzare rotazioni più fluide e graduali.

L'asset utilizzato per questi due tutorial è "Surveillance Camera 1"; tuttavia non è necessario scaricarlo per seguire i video: serve solo per l'esempio concreto, per cui potete tranquillamente guardare i tutorial e imparare senza scaricare questo particolare modello 3D!

Analizziamo il problema da risolvere, prima di passare all'implementazione.

La telecamera può ruotare solo intorno al suo asse verticale locale, per cui possiamo ridurre il problema al piano 2D; per rendere più comprensibile questo aspetto, sto inquadrando la scena dal punto di vista TOP in modalità Ortogonale.

Sia il modello 3D della telecamera di videosorveglianza che il Player hanno, come tutti i game objects, le coordinate Position XYZ che ne identificano la posizione nella scena.

La coordinata position.y non ci interessa, perché la telecamera può ruotare solo intorno a quell'asse LOCALE, per cui considereremo solo le coordinate di posizione x e z, come se i due oggetti si trovassero sullo stesso piano, con lo stesso valore per le loro coordinate y.

Nel nostro caso, inoltre, la telecamera di videosorveglianza può essere considerata come l'origine del sistema di riferimento (quello che, in un piano cartesiano, sarebbe l'origine, nel punto 0,0).

Non solo: possiamo anche considerare la direzione inquadrata dalla telecamera, che in questo caso corrisponde all'asse LOCALE y negativo, come uno degli assi cartesiani.

Possiamo poi identificare la direzione che collega la telecamera virtuale e la posizione del Player nella scena: si tratta, semplicemente, di un vettore, che anche in questo caso considereremo solo su due dimensioni (ossia X e Z GLOBALI).

Va da sé, quindi, che la rotazione che vogliamo far fare alla telecamera è data dall'angolo che separata l'orientamento della telecamera (il suo asse Y locale negativo) e il vettore ideale che collega la telecamera al Player: trovando quest'angolo, avremo la rotazione da far fare al modello 3D intorno al suo asse verticale locale.

Siamo molto fortunati: esiste una funzione matematica, chiamata arcotangente a due argomenti e implementata dal metodo Atan2 di Mathf, che calcola proprio quest'angolo prendendo, come parametro, il vettore direzione, dato dalla differenza tra le coordinate dei due punti.

In particolare, Atan2 considera l'angolo tra l'asse X del piano cartesiano e il vettore direzione tra l'origine e il target. Nel nostro caso, l'origine è data dalle coordinate X e Z del modello 3D della telecamera di videosorveglianza, per cui le coordinate (x,y) del target saranno date dalle differenze delle coordinate tra la telecamera di videosorveglianza e il player, mentre l'asse X coincide con l'asse Y locale negativo del modello della telecamera.

La funzione prende i due parametri in ordine inverso: nel piano cartesiano, infatti, abbiamo atan2(y,x); nel nostro caso, considerando il sistema di riferimento di Unity (dove l'asse x è quello laterale, quello z è quello frontale e quello y è quello verticale, che qui non consideriamo), scriveremo atan2(x, z).

La documentazione online di Unity ci dice che Mathf.Atan2 prende le coordinate y e x (che nel nostro caso saranno x e z) e restituisce, sotto forma di valore float, l'angolo IN RADIANTI la cui tangente è y/x.

La funzione Rotate di Unity vuole un angolo di rotazione IN GRADI, per cui dovremo tenere conto di questa differenza di unità di misura (e della conversione necessaria) quando scriveremo il codice.

Ora che abbiamo analizzato il problema e la sua soluzione, passiamo alla prima implementazione: quella della rotazione istantanea, con Rotate.

Per prima cosa, creo un nuovo script C# chiamato LookAtObject da associare alla telecamera di sorveglianza vera e propria; dico "telecamera di sorveglianza vera e propria" perché quest'asset è composto, in realtà, da tre elementi: la base da poggiare alla parte, un elemento perno e la telecamera.

Ci interessa che la telecamera ruoti intorno al SUO asse verticale, ovvero intorno al suo asse verticale LOCALE.

Nell'universo virtuale di Unity, l'asse verticale GLOBALE è l'asse y, ma ciascun oggetto può avere un suo sistema di riferimento LOCALE; nel caso del modello 3D della telecamera di videosorveglianza, questo è l'asse Z LOCALE, come possiamo constatare passando alla modalità di visualizzazione LOCAL nell'editor di Unity.

Questa distinzione introduce una piccola complessità nel nostro progetto: dovremo calcolare l'angolo di rotazione sul piano globale della scena, utilizzando quindi le coordinate X e Z degli oggetti, dopodiché dovremo effettuare la rotazione

Per prima cosa, creiamo un riferimento all'oggetto da seguire, creando una variabile di tipo Transform chiamata objectA, alla quale associamo il Player nell'Inspector.

[SerializeField] private Transform objectA;

Fatto questo, possiamo spostarci direttamente in Update per implementare la soluzione discussa poco fa.

Ci servono appena tre linee di codice: nella prima, calcoleremo l'angolo che separa l'orientamento attuale della telecamera da quello che dovrebbe avere (per puntare l'oggetto); nella seconda, calcoleremo l'entità della rotazione da effettuare, intorno all'asse Z locale della telecamera, per arrivare all'orientamento volume; nella terza, effettueremo la rotazione vera e propria con il metodo Rotate, al quale dovremo dare due parametri: il vettore verticale locale e l'entità della rotazione da effettuare intorno a quel vettore.

Iniziamo con il calcolo dell'angolo compreso tra l'orientamento della telecamera e quello che dovrebbe avere, utilizzando la funzione Atan2 di Mathf, la quale restituisce un valore in radianti che trasformeremo in gradi.

Abbiamo visto che, nel piano 2D, Atan2 prende due parametri: la differenza tra le coordinate Y e la differenza tra le coordinate X dei due punti (target e osservatore, in quest'ordine).

Nel nostro scenario, con il sistema di coordinate globali di Unity (per cui X e Z sono sul piano 2D, mentre Y GLOBALE identifica l'asse verticale della scena), dovremo scrivere:

float theta = Mathf.Atan2((objectA.transform.position.x - transform.position.x), (objectA.transform.position.z - transform.position.z))

ma non abbiamo finito: nella stessa istruzione, aggiungiamo alla fine

* Mathf.Rad2Deg;

per convertire il risultato in gradi.

Fatto ciò, possiamo passare alla seconda istruzione: il calcolo della rotazione da effettuare, in gradi, che può essere effettuata facilmente con:

float deltaAngle = Mathf.DeltaAngle(transform.eulerAngles.z, theta);

dove transform.eulerAngles.z rappresenta l'orientamento attuale della telecamera di videosorveglianza, mentre theta rappresenta l'orientamento, calcolato al punto precedente, che essa deve assumere.

La terza e ultima istruzione ci consente di ruotare la telecamera di videosorveglianza:

transform.Rotate(Vector3.forward, deltaAngle);

Da notare che ho utilizzato Vector3.forward, che identifica l'asse Z LOCALE dell'oggetto, come vettore intorno al quale effettuare la rotazione; ciò è dovuto al fatto che, nel caso specifico di questo modello 3D, l'asse Z LOCALE non è quello che indica il davanti e il dietro, ma l'asse verticale LOCALE dell'oggetto.

Salviamo lo script, passiamo all'editor di Unity e premiamo Player per valutare il risultato finale.

Attenzione, nota importante: se vede che la telecamera di videosorveglianza non è orientata verso il bersaglio, assicuratevi che le trasformazioni iniziali di rotazione XYZ della telecamera siano impostate a 0 nell'Inspector e riprovate.

Ricapitolando: in questa prima parte abbiamo esaminato il problema da risolvere e abbiamo visto come considerare i due oggetti sullo stesso piano, come calcolare il vettore di direzione e, soprattutto, come applicarlo al caso specifico della telecamera di videosorveglianza (tenendo conto del suo sistema di riferimento locale). Abbiamo quindi applicato una rotazione istantanea all'oggetto, così da fargli puntare il Player ad ogni frame del gioco, utilizzando la funzione Rotate.

Nella seconda parte vedremo come calcolare i quaternioni di rotazione e utilizzare la funzione Slerp, così da far ruotare l'oggetto più lentamente.

Cerca nei Tutorial

Cerca inserendo una frase o più parole chiave, separate da virgole.

Modelli 3D, tutorial e risorse di computer grafica di Francesco Milanese. Le licenze d’uso dei modelli 3D sono acquistabili tramite gli store esterni indicati nelle rispettive pagine, secondo le condizioni di licenza applicabili. Francesco Milanese — Partita IVA: 06321250877. Contatti: info@francescomilanese.com


INFORMATIVA ESTESA SULL'UTILIZZO DEI COOKIES