Suggerimenti per l'ottimizzazione per Unity

Unity è un motore di gioco popolare non solo tra gli sviluppatori indipendenti ma anche tra le grandi aziende.

È dotato di un'interfaccia intuitiva, una potente pipeline di rendering, un sistema di componenti facile da usare e, infine, supporta una vasta gamma di piattaforme.

Ma con un'interfaccia facile da usare, è ancora più semplice complicare eccessivamente il gioco (ad esempio posizionando molti oggetti non necessari, ecc.), quindi è importante avere ottimizzazione in mente durante tutto il corso dello sviluppo.

Ecco alcuni suggerimenti importanti per le 3 categorie principali (Rendering, Scripting, e Audio) che ti aiuteranno a migliorare le prestazioni del tuo gioco:

Rendering

Suggerimento 1: mantieni gli oggetti con il componente Renderer non scalati

Gli oggetti non in scala sono quelli che hanno una scala pari a (1, 1, 1). In tal caso, Unity non deve eseguire calcoli aggiuntivi per ridimensionare l'oggetto in ciascun fotogramma.

Esempio: Supponiamo che tu abbia un modello di casa troppo grande o troppo piccolo per il tuo livello. La cosa naturale da fare è ridimensionarlo in questo modo:

Ridimensionamento dell'edificio

Nella maggior parte dei casi va bene ridimensionare l'oggetto nella vista Scena, ma se prevedi di avere molte istanze duplicate di quell'oggetto, è preferibile modificare la scala nelle Impostazioni di importazione.

La prima cosa che devi fare è ridimensionare il modello finché non si adatta alle tue esigenze (es. l'edificio sopra è stato scalato da (1, 1, 1) a (0.49482, 0.49482, 0.49482)), quindi selezionare il modello nel Progetto e nelle Impostazioni di importazione annota il fattore di scala (di solito è 1 o 0,1).

Imposta il nuovo valore, che dovrebbe essere uguale al fattore di scala predefinito moltiplicato per la nuova scala (nel mio caso è 1 x 0,49482 = 0,49482), quindi premi Applica. Ora torna al modello nella vista scena e imposta nuovamente la scala su (1, 1, 1).

Impostazioni del fattore di scala Unity 3D

L'oggetto è ora ridimensionato nel modo desiderato preservando la scala predefinita (1, 1, 1).

Questo suggerimento è particolarmente importante per gli oggetti animati che utilizzano SkinnedMeshRenderer poiché questo componente è più costoso da renderizzare e avere una scala di (1, 1, 1) semplifica il processo di rendering.

Suggerimento 2: usa meno luci possibile

Sono disponibili 3 tipi di luci in Unity (luce direzionale, luce puntiforme e riflettore). In termini di prestazioni, la luce direzionale è la più economica per il rendering, poi il punto e infine il riflettore.

In generale, non vuoi avere più di una luce direzionale per scena, e per le luci spot e puntiformi cerca di averne il meno possibile (o nessuna).

In termini di ombre in tempo reale, mentre migliora l'aspetto visivo del gioco, ha un sovraccarico ad alte prestazioni, quindi in genere è meglio disabilitarle o inserirle in lightmaps e light sonde.

Suggerimento 3: utilizzare gli shader trasparenti con cautela

Utilizza gli shader trasparenti o di particelle solo su superfici che devono essere trasparenti (ad es. Recinzioni, particelle di fumo, ecc.)

Gli oggetti con trasparenza richiedono un passaggio di rendering aggiuntivo che potrebbe ridurre le prestazioni, soprattutto su piattaforme con risorse limitate, come Mobile o Web.

Scrittura

Suggerimento 1: memorizzare sempre nella cache i riferimenti ai componenti

Dovresti sempre memorizzare nella cache i riferimenti ai componenti se prevedi di accedervi a ogni aggiornamento.

Ad esempio, controlla lo script seguente:

Cattivo

using UnityEngine;

public class Script1 : MonoBehaviour
{
    float someValue = 0;

    // Update is called once per frame
    void Update()
    {
        someValue = GetComponent<Script2>().someValue2;
    }
}

Qui abbiamo Script1 che ottiene la variabile "someValue2" da Script2 e la assegna a una variabile locale.

Ora, chiamando solo un GetComponent ogni frame non avrà alcun impatto sulle prestazioni, tuttavia, dovresti adottare l'abitudine di memorizzare nella cache i componenti che verranno utilizzati frequentemente.

Esistono due modi per memorizzare nella cache un componente in uno script: creare una variabile pubblica e assegnarla nella vista Inspector oppure creare una variabile privata e assegnarla da Start o Awake. Controlla l'esempio qui sotto:

Bene

using UnityEngine;

public class Script1 : MonoBehaviour
{

    float someValue = 0;

    Script2 script2Cached;

    // Use this for initialization
    void Start()
    {
        script2Cached = GetComponent<Script2>();
    }

    // Update is called once per frame
    void Update()
    {
        someValue = script2Cached.someValue2;
    }
}

Molto meglio, ora è possibile accedere a Script2 a ogni aggiornamento senza sovraccarico delle prestazioni.

Fai lo stesso per i componenti integrati, come BoxCollider, Rigidbody, ecc. (eccetto Transform e GameObject, questi sono già memorizzati nella cache per impostazione predefinita, quindi puoi accedervi immediatamente).

Suggerimento 2: utilizzare SendMessage con cautela

SendMessage ti consente di chiamare una funzione specifica (se esiste) su ogni MonoBehaviour che è attached a un oggetto di gioco.

Ad esempio, quando spari con un'arma nel gioco puoi infliggere rapidamente danni quando il proiettile colpisce il nemico, senza la necessità di utilizzare GetComponent e altre cose extra.

Tuttavia, questo metodo non dovrebbe essere chiamato troppo frequentemente poiché richiede un'elevata intensità di calcolo.

Suggerimento 3: utilizza GameObject.Find e GameObject.FindWithTag con cautela

GameObject.Find, GameObject.FindWithTag e GameObject.FindGameObjectsWithTag ti consentono di cercare rapidamente gli oggetti nella scena. Questi metodi sono molto più lenti di GetComponent e devono essere utilizzati solo durante l'inizializzazione.

Suggerimento 4: evitare di utilizzare OnGUI

Storicamente OnGUI era l'unico modo per creare menu in Unity. Ma da allora è stata aggiunta un'alternativa chiamata UI Canvas che è molto migliore in termini di prestazioni e offre molte più funzionalità.

Tuttavia, OnGUI rimane ancora un modo praticabile per creare UI in Unity e se hai assolutamente bisogno di usarlo, tieni presente che OnGUI viene chiamato almeno due volte per frame (il doppio di Update e LateUpdate), quindi non farlo usalo per qualsiasi calcolo oltre all'interfaccia utente.

Una cosa che puoi fare è avere uno script separato che contenga solo OnGUI e abilitarlo/disabilitarlo quando necessario.

Per esempio:

UIScript.cs

using UnityEngine;

public class UIScript : MonoBehaviour {

    void OnGUI()
    {
        if(GUI.Button(new Rect(5, 5, 125, 25), "Button 1"))
        {
            //Button 1 was pressed, Do Something
        }
        if (GUI.Button(new Rect(140, 5, 125, 25), "Button 2"))
        {
            //Button 2 was pressed, Do Something
        }
    }
}

Script1.cs

using UnityEngine;

public class Script1 : MonoBehaviour
{

    UIScript uiScript;

    // Use this for initialization
    void Start()
    {
        uiScript = GetComponent<UIScript>();
        uiScript.enabled = false;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Tab))
        {
            //toggle UIScript when Tab is pressed
            uiScript.enabled = !uiScript.enabled;
        }
    }
}

Sia UIScript che Script1 sono collegati allo stesso GameObject. Script1 controlla quando mostrare il menu.

Quando il giocatore preme Tab, l'UIScript viene abilitato, mostrando i pulsanti. Premendo nuovamente Tab lo si disattiva, nascondendo i pulsanti.

Mentre UIScript è disattivato, il metodo OnGUI non viene chiamato, il che a sua volta migliora le prestazioni.

Suggerimento 5: utilizza Profiler

Profiler è uno degli strumenti più importanti quando si tratta di identificare colli di bottiglia e cali di fps, rendendo più semplice trovare la causa esatta delle scarse prestazioni.

Audio

Le clip audio possono essere ottimizzate assicurandosi che le impostazioni di importazione siano corrette.

Le impostazioni ottimali di importazione dell'audio dipenderanno dalla lunghezza dell'audio, dalla frequenza di riproduzione e dalla piattaforma di destinazione.

Articoli suggeriti
Il generatore di cartelloni pubblicitari per l'Unità
Miglioramento delle prestazioni di un gioco per dispositivi mobili in Unity
Impostazioni di importazione di clip audio Unity per le migliori prestazioni
Come utilizzare l'aggiornamento in Unity
Unity ottimizza il tuo gioco utilizzando Profiler
Suggerimenti Twitter per l'unità
I concetti fondamentali del game design