Di seguito una lista non ordinata di alcuni concetti con cui mi sono scontrato durante l’utilizzo di Unity 3D per lo sviluppo di videogiochi o simulazioni. Non vuole essere una lista esaustiva ne tanto meno una lista per esperti. Va considerata una lista per chi si approccia a Unity e riscontra dubbi, perplessità a problemi in alcuni aspetti dello sviluppo.

Gli argomenti trattati spaziano dall’editor alla fase di Game, dallo script al motore fisico passando dall’import dei modelli fino alla mappatura dei materiali.

Colliders e Centro di Massa

In GameObject con più di un collider triggerato, di cui uno di tipo Sphere, può succedere che il centro di massa del Rigidbody associato cambi valore continuamente. Questo genera spostamenti non voluti ed incontrollati del Rigidbody.
Il consiglio è di usare solo colliders di tipo Box quando possibile.

Motore fisico 2D e 3D

Il motore fisico 3D è chiamato Physics, il motore fisico 2D è invece chiamato Box2D.
I due sistemi sono atomici l’uno rispetto all’altro e non possono interagire tra di loro.
Possono invece coesistere.

Debug del motore fisico

E’ possibile eseguire il debug runtime del motore fisico, osservando quindi in Game i colliders, accedendo al debugger del motore tramite il menu Windows -> Analysis -> Physics Debug. Avere cura di abilitare poi la voce Force Overdraw per un debug più efficace.

StartCoroutine e StopCoroutine

Funzioni fondamentali, StartCoroutine() e StopCoroutine() richiedono come parametro il nome della funzione da eseguire, il modo più semplice ed efficace per eseguirle, per mantenere leggibilità e intellisense, è il seguente:

StartCoroutine(Method_Enumerator(param1, param2, param3…));
StopCoroutine(nameof(Method_Enumerator));

Conversione di parametri String in Float provenienti dall’editor

Per uno script MonoBehaviour il quale ha esposto un parametro String per l’editor che deve essere convertito in Float nello script, il metodo da utilizzare è quello di passare la Culture di tipo Invariant al metodo Convert in quanto preserva il valore con il punto (definendo la parte decimale) ma sopratutto consente uniformità tra le misure usate in Unity.

Nell’esempio sottostante editorValue viene specificato come “0.1” (notare il punto e non la virgola) nella finestra dell’editor, ma:

float convertedValue1 = Convert.ToSingle(editorValue) ritorna: 0.0f
float convertedValue2 = Convert.ToSingle(editorValue, System.Globalization.CultureInfo.InvariantCulture) ritorna: 0.1f

Import di modelli da software di modellazione 3D (Maya, 3ds Max, Blender…)

Durante la fase di export verificare che gli assi siano congrui con quelli di Unity:

  • X rosso verso destra
  • Y verde verso l’alto
  • Z blu verso l’orizzonte

Verificare inoltre le unità di misura. Spesso non coincidono in quanto in Unity 1 corrisponde ad un metro mentre, ad esempio, in Maya 1 corrisponde ad un centimetro. Una volta importato il modello in Unity, selezionarlo e provare a disabilitare la seconda casella che riguarda la conversione automatica delle unità di misura.

Il consiglio è di untilizzare come file di interscambio il formato .FBX che include sia la definizione dei materiali a livello di facce della mesh che le animazioni. Esporta inoltre luci e camera (che in realtà potrebbero essere di troppo).

Abilitare l’autocomplete (intellisense) per Visual Studio

Può capitare che l’editor Visual Studio non riconosca l’auto-completamento (o intellisense) degli oggetti principali.
La soluzione qui.

Update vs FixedUpdate

Update() e FixedUpdate() sono richiamate all’interno del flusso di esecuzione. E’ bene sapere che Update() deve essere utilizzato quando si interroga il sistema di Input (in quanto viene eseguito in modo atomico e sequenziale), mentre FixedUpdate() quando si eseguono operazioni che coinvolgono movimenti e interazioni con il motore fisico (velocità, collisioni, posizioni, etc).
Qui l’ordine di esecuzione ufficiale.

Time.DeltaTime vs Time.FixedDeltaTime

Spesso si trova indicato DeltaTime oppure FixedDeltaTime, il primo usato in Update() e il secondo in FixedUpdate(), in realtà il consiglio è di usare sempre Time.DeltaTime in quanto la variabile assume il valore corretto in base alla funzione in cui si trova. Qui viene indicato chiaramente nella guida di Unity.

Qui un video molto esplicativo sull’uso generico di DeltaTime : https://www.youtube.com/watch?v=vZyvdm4I0uc

Uso efficiente del metodo GetComponent

Il metodo GetComponent è uno dei più onerosi in termini di prestazioni e va usato solo nelle funzioni di Awake o Start. Qualora comunque si voglia usarlo in altri contesti è bene utilizzare la sua versione GetComponent<T>() invece delle due GetComponent(string) o GetComponent(tyepof(T)).

Confronto di GameObjects a null

Il confronto a null di un GameObject può essere eseguito sia con gameObject = null oppure con System.Obejct.ReferenceEquals(gameObject, null). La seconda soluzione sembra essere quella più performante, anche se veramente di poco. Il consiglio è di usare quella più comoda.

Rimuovere le callback vuote

Le funzioni di calback più usato nei GameObject sono Awake(), Start(), Update() e FixedUpdate(). Se nel GameObejct corrente non è necessario implementarle, il consiglio è quello di rimuoverle al fine di non farle eseguire. Seppur vuote il tempo di esecuzione può comunque fare la differenza.

Duplicare elementi (CTRL+D)

Per duplicare qualsiasi elemento (ad esempio una materiale, una cartella di un materiale, un prefab, etc) è consigliato usare la funzione Duplica accessibile con CTRL+D e non il copia incolla CTRL+C / CTRL-V, in quanto si potrebbe incorrere in duplicazione di GUID associati agli alementi da duplicare.

Snap di elementi per renderli modulari (tasto V)

E’ possibile decidere il vertice di cui fare lo snap sulla griglia premendo, e tenendo premuto, il tasto V e muovendo poi l’elemento sulla griglia.

Confronto della proprietà .tag

Se si rende necessario il confronto della proprietà .tag di un GameObject (situazione abbastanza usuale in realtà) è bene utilizzare il metodo .CompareTag(“mio tag”) e non .tag = “mio tag” in quando la prima funziona non allocca memoria, mentre la seconda si.

Flickering di mesh complanari e Clipping Planes

Può capitare di notare un effetto di flickering di due mesh che collidono tra loro. Questo disturbo è dato dal conflitto di arrotondamento dei floating point. Per risolvere questo fastidioso problema basta aggiustare il valore del Near Clipping Plane (solitamente impostato a 0.01) della Camera corrente. Tale valore dipende da motli fattori quindi il consiglio è di provare diversi valori, anche a runtime, prima di eliminare il disturbo.

BONUS: Pacchetti consigliati

Accedendo al menu Windows -> Package Manager è possibile installare pacchetti aggiuntivi di Unity. Avere cura di cercare anche tra le Prerelease e le Preview. Di seguito alcuni pacchetti consigliati:

  • ProGrids – gestione degli snap sulla griglia dell’editor
  • ProBuilder – gestione della modellazione nell’editor
  • Cinemachine – gestione della camera in modo cinematografico

[…in aggiornamento]