Il Canvas o UI Canvas è la base di tutte le interfacce utente: ogni componente della UI deve obbligatoriamente trovarsi all'interno di esso, o non verrà renderizzato. Il Canvas è un GameObject che ha il componente Canvas, e di cui tutti gli elementi della UI devono essere figli. Se creiamo un qualunque nuovo elemento UI come un Button o un'Image e non è presente già un Canvas in scena, questi sarà creato automaticamente e l'elemento UI aggiunto ad esso come figlio.
Ecco come si presenta il componente nell'Inspector:
Il Canvas viene rappresentato in scena con un rettangolo bianco, con l'aspect ratio che la Game View ha attualmente, e come un oggetto enorme (spesso almeno 10 volte l'intera scena 3D!).
Per manipolarlo (e per manipolare gli elementi 2D della UI useremo spesso il Rect Tool, che è il nuovo manipolatore aggiunto in Unity 4.6:
Questi ci permette di agire su Width/Height invece che su Scale, spostare l'oggetto solo su X ed Y senza scomodare la Z (spesso inutile), ruotare solo sull'asse Z, arrotondare i movimenti al pixel, ed altre cose utili.
Ecco come appare un Canvas 16:9 nella Scene View se selezionato con il Rect Tool:
Nota: non è possibile spostare né ridimensionare il Canvas, il cui aspect ratio viene definita come detto dalla Camera principale, che lui andrà a coprire completamente.
Stili di rendering
La nuova UI può essere renderizzata in tre modi, scegliendo l'apposita opzione nel componente Canvas. Vediamole in dettaglio.
Screen Space - Overlay
Con questo metodo di rendering, la UI viene disegnata sopra qualunque elemento della scena. e non dipende da nessuna Camera. Difatti, la UI viene renderizzata anche se in scena non è attiva nessuna Camera.
Ecco un esempio:
La UI viene disegnata al di sopra di qualunque oggetto 3D. È la soluzione più comune, e per molti versi anche la più facile da gestire perché la UI non viene mai occultata.
Questo è il risultato di una scena preparata in questo modo:
Come si può notare, in scena non è visibile alcuna UI, e la Camera Preview nell'angolo in basso non la visualizza perché, come detto, la UI non è strettamente legata a nessuna Camera specifica.
Per vedere la UI in scena dobbiamo fare zoom out (di molto), e la troveremo in una situazione simile:
In questa immagine ho selezionato la camera per dare un'idea della differenza di dimensioni: l'intera scena 3D con i due robottini è un piccolo punto in corrispondenza del pivot della Camera. Ma è assolutamente normale (non cercate di ridurre le dimensioni della UI!): Unity tratta i pixel della UI come se fossero unità, quindi una UI di 800x600 sarà lunga 800 volte il cubo di base!
In Screen Space - Overlay, il Canvas si ridimensiona automaticamente in base all'aspect ratio dello schermo.
Difatti, se selezioniamo il Canvas, vedremo che i suoi valori nel RectTransform sono completamente bloccati:
L'Inspector mostra un warning: “Some values driven by Canvas” (“Alcuni valori sono controllati dal Canvas”).
Screen Space - Camera
Selezionando questo metodo di disegno, la UI viene sempre disegnata secondo le dimensioni dello schermo, ma verrà legata ad una specifica Camera che si fa quindi “carico” di renderizzarla.
Ad esempio, selezionando questo metodo di disegno con la scena precedente, avremo un risultato simile:
Perché avviene ciò? La UI viene disegnata su un piano che si piazza di fronte alla camera, intersecando il suo frustum, ad una distanza che possiamo stabilire noi. Ecco cosa sta succedendo nella Scene View:
Nella nostra scena però una distanza di 2 unità fa sì che la UI intersechi in parte la scena 3D, risultando nel brutto effetto di compenetrazione di cui sopra. Basterà in questo caso ridurre la distanza ad 1 o meno, per evitare l'inconveniente (se la UI scompare, fate attenzione al valore su cui è settato il Near Clip Plane della Camera!).
Questo metodo di rendering è utile se vogliamo, ad esempio, far passare dei piccoli asteroidi davanti alla UI in una scena nello spazio. Dovremo però fare attenzione che questi non intersechino mai la UI, e questo normalmente richiede un lavoro extra di design e di debug.
World Space
In ultimo, il metodo di rendering World Space tratta la UI come se fosse un normale piano nello spazio. Questo metodo vi permette di ridimensionarla a piacimento, di ruotarla su tutti gli assi, e di gestirne la deformazione prospettica mediante il valore di Field of View della Camera (solo se state usando una Camera prospettica però!).
Si possono creare effetti del genere:
… con l'unico difetto che, essendo ruotata, a volte la UI soffre di un effetto di seghettatura se magari stiamo usando una Camera che non supporta l'anti-aliasing.
Ecco com'è piazzata la UI in scena:
Come si può vedere, è a tutti gli effetti un oggetto 3D che si trova dietro i personaggi, che possiamo manipolare con Scale, Rotate e Position in modo da dargli esattamente la forma che vogliamo.
Purtroppo come per Screen Space - Camera però drovemo preoccuparci che quel robot non arretri, intersecando la UI!
Il metodo World Space potrebbe però risultare comodo se vogliamo disegnare parti di UI altamente integrate con il mondo 3D, come ad esempio del testo su uno schermo presente nella scena.
Ordine di disegno
È importante tenere da conto che l'ordine di disegno degli elementi della UI - se questa non è impostata come World Space - viene definito non dalla loro posizione nello spazio 3D ma dall'ordine in cui si trovano nel pannello Hierarchy.
Per visualizzare l'ordine corretto, bisogna assicurarsi che l'ordinamento nel pannello Hierarchy sia secondo il Transform, e non alfabetico.
In poche parole, se il simbolo nel pannello Hierarchy è come il primo qui in basso...
… cliccate e scegliete Transform Sort.
In questo modo, gli elementi verranno disegnati secondo l'ordine nella Hierarchy: elementi elencati per primi verranno disegnati per primi, e quindi quelli elencati dopo gli verranno disegnati sopra, risultando “davanti”.
Ad esempio nella UI di cui sopra:
Il primo Panel rappresenta il pannello lilla che contiene tutto. Title è la fascetta con la scritta “Menu Principale”, mentre i Button sono i differenti pulsanti.
Come si può vedere, Title e i Button vengono disegnati davanti al pannello perché sono successivi ad esso nella Hierarchy.