Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Transform: rotazione, orientamento e scalatura

Modificare le dimensioni e l'orientamento nello spazio degli oggetti
Modificare le dimensioni e l'orientamento nello spazio degli oggetti
Link copiato negli appunti

Continuamo a lavorare con il componente Transform, come nella lezione precedente, questa volta analizzando rotazioni e scalature.

Ruotare gli oggetti

La rotazione viene conservata in Unity in diversi modi: ci sono le proprietà eulerAngles e localEulerAngles, che sono Vector3 e rappresentano l'angolo di rotazione nei tre diversi assi X, Y e Z in gradi (quindi da 0 a 360).

Ruotare un oggetto impostando i suoi angoli di Eulero però presenta un problema che si chiama gymbal lock (ecco anche un video esplicativo), molto conosciuto agli animatori 3D. In breve, gli angoli di rotazione che vediamo nell'Inspector hanno un ordine di applicazione, quindi sommare rotazioni su diversi assi non produce i risultati sperati perché la rotazione su un asse dipende anche dalla rotazione degli altri 2.

Per risolvere questo problema, in Unity vengono usati i quaternioni, che sono una struttura matematica che incorpora numeri complessi, e che può a volte essere confusa con un Vector4 perché ha quattro componenti (x, y, z e w).

I quaternioni sono conservati nella proprietà transform.rotation, però sui quaternioni non si dovrebbe mai andare ad agire in maniera diretta (cioè modificando le componenti a mano) ma sempre con le funzioni che fornisce Unity, come Rotate, RotateAround, ecc.

È possibile invece modificare a mano gli angoli di Eulero (questo sì che si può fare), ad esempio per resettare una rotazione:

transform.localEulerAngles = new Vector3(0f, 0f, 0f);

Questa operazione modifica anche i quaternioni della proprietà rotation.

Orientamenti

Altra utile possibilità è di orientare un oggetto in modo che guardi verso un altro. In Unity, il componente Transform contiene 3 vettori che indicano l'orientamento attuale nelle tre direzioni principali: up, forward e right. Questi vettori (versori) non rappresentano posizioni né spostamenti, ma orientamenti, e come tali hanno lunghezza 1. Possono essere usati per diversi scopi.

Ad esempio, si può spostare un oggetto in avanti (il suo "avanti") di 3 unità. Per farlo precedentemente avevamo usato Translate nello spazio locale, ma potremmo farlo anche usando l'orientamento:

transform.Translate(new Vector3(2f, 0f, 0f), Space.Self);
transform.Translate(transform.forward * 2f, Space.World);

Queste due righe si equivalgono: nella prima, diciamo all'oggetto di spostarsi di due unità in avanti rispetto al suo sistema di coordinate (Space.Self).

Nella seconda, utilizziamo transform.forward per avere un vettore lungo due unità, che punti nella direzione "avanti" dell'oggetto. In questo modo lo spazio di coordinate può essere Space.World.

Usando gli orientamenti, possiamo copiare la rotazione da un oggetto all'altro. Inoltre, possiamo invertire gli orientamenti, in modo da ottenere le direzioni giù, dietro e sinistra (che non sono disponibili come proprietà):

cube1.transform.forward = -cube2.transform.forward;

Così facendo, cube1 copierà esattamente la rotazione di cube2, ma sarà orientato al contrario, come se cube2 si fosse girato di spalle. Allo stesso modo, usare -transform.up restituisce una direzione "verso il basso" dell'oggetto, e -transform.right verso sinistra.

Da notare che gli orientamenti che abbiamo visto sono relativi agli oggetti, ovvero locali. Anche se sono facili da immaginare, troviamo gli orientamenti globali in:

  • Vector3.up: (0, 1, 0);
  • Vector3.right: (1, 0, 0);
  • Vector3.forward: (0, 0, 1).

Per fare un modo che un oggetto guardi verso un altro senza calcolare la direzione, possiamo usare una funzione LookAt del Transform. Questa accetta come parametri la posizione verso cui guardare (che sarà in pratica il nuovo forward dell'oggetto da orientare), ed un vettore che indichi poi come orientare l'oggetto verso l'alto (che sarà il suo nuovo up):

transform.LookAt(Vector3.zero, -Vector3.up);

In questo esempio, l'oggetto sarà orientato per guardare verso l'origine degli assi (Vector3.zero), ma sarà anche girato a testa in giù, perché come "su" gli abbiamo dato la direzione globale "verso in basso" (-Vector3.up).

Scalature

Il fattore di scala degli oggetti si può modificare in maniera molto simile alla posizione: i valori di scala sono custoditi in un Vector3, nelle sue 3 componenti, ed esiste in versione locale e globale. Lavorare con quella globale (transform.lossyScale) non ha senso però, quindi ci ritroveremo in Unity a lavorare sempre sulla transform.localScale. Ad esempio:

transform.localScale = new Vector3(2f, 2f, 2f);

Così facendo, l'oggetto diventa il doppio della sua normale scalatura. Da notare che la scala non equivale alle dimensioni, ovvero se due oggetti hanno scala (2, 2, 2) non è detto che siano grandi lo stesso (questo dipende anche dalle dimensioni in cui sono stati modellati nel software di 3D).

La scala globale, contenuta in transform.lossyScale, è di sola lettura. È quasi inutile operare con essa, perché ovviamente dipende dalla combinazione della scala locale con la scala del parent (e di eventuali altri parent) uniti alla loro rotazione (perché a volte gli oggetti sono scalati in maniera non uniforme.

È utile anche dire che le scalature non uniformi sono in generale molto sconsigliate, perché in caso di oggetti innestati possono portare a deformazione degli oggetti figli, proprio a causa del fatto che tutti i transform devono essere combinati fra loro per ottenere la posizione finale dei vertici.

Ti consigliamo anche