Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo si basa sulle raccomandazioni sulle prestazioni per la realtà mista, ma è incentrato sui miglioramenti specifici di Unity.
Di recente è stata rilasciata un'applicazione denominata Quality Fundamentals che copre problemi comuni di prestazioni, progettazione e ambiente e soluzioni per le app HoloLens 2. Questa app è un'ottima demo visiva per il contenuto che segue.
Usare le impostazioni del progetto Unity consigliate
Il primo passaggio più importante quando si ottimizzano le prestazioni delle app di realtà mista in Unity è assicurarsi di usare le impostazioni di ambiente consigliate per Unity. Questo articolo contiene contenuto con alcune delle configurazioni di scena più importanti per la creazione di app Realtà mista performanti. La sezione seguente evidenzia alcune di queste impostazioni consigliate.
Come profilare con Unity
Unity fornisce il profiler unity predefinito, che è un'ottima risorsa per raccogliere informazioni dettagliate sulle prestazioni preziose per la specifica app. Anche se è possibile eseguire il profiler nell'editor, queste metriche non rappresentano il vero ambiente di runtime, quindi i risultati devono essere usati con cautela. Profilare in remoto l'applicazione durante l'esecuzione sul dispositivo per ottenere informazioni dettagliate più accurate e interattive.
Unity offre un'ottima documentazione per:
- Come connettere il profiler Unity alle applicazioni UWP in remoto
- Come diagnosticare in modo efficace i problemi di prestazioni con Unity Profiler
Profilatura GPU
Profiler Unity
Con Unity Profiler connesso e dopo aver aggiunto il profiler GPU (vedere Aggiungere profiler nell'angolo in alto a destra), è possibile vedere quanto tempo viene impiegato rispettivamente per la CPU & GPU al centro del profiler. Ciò consente allo sviluppatore di ottenere una rapida approssimazione se l'applicazione è limitata da CPU o GPU.
Nota
Per usare la profilatura GPU, è necessario disabilitare i processi grafici nelle impostazioni di Unity Player. Per altri dettagli, vedere il modulo GPU Usage Profiler di Unity.
Debugger di frame Unity
Frame Debugger di Unity è anche uno strumento potente e intuitivo da usare. Offre una buona panoramica di ciò che la GPU sta facendo ogni fotogramma. Gli aspetti da cercare sono altre destinazioni di rendering e comandi blit da copiare tra di loro perché sono costosi in HoloLens. Idealmente, non è consigliabile usare destinazioni di rendering fuori schermo in HoloLens. Questi vengono aggiunti quando si abilitano funzionalità di rendering costose (ad esempio MSAA, HDR o effetti a schermo intero come bloom) che devono essere evitate.
Sovrapposizione della frequenza dei fotogrammi di HoloLens
La pagina Prestazioni del sistema del portale dispositivi contiene un buon riepilogo delle prestazioni della CPU e della GPU del dispositivo. È possibile abilitare Il contatore della frequenza dei fotogrammi nel visore auricolare e Il grafico della frequenza dei fotogrammi nel visore auricolare. Queste opzioni abilitano rispettivamente un contatore FPS e un grafo che offrono feedback immediato in qualsiasi applicazione in esecuzione nel dispositivo.
PIX
È possibile usare PIX anche per profilare le applicazioni Unity. Sono inoltre disponibili istruzioni dettagliate su come usare e installare PIX per HoloLens 2. In una compilazione di sviluppo, gli stessi ambiti visualizzati nel debugger frame di Unity verranno visualizzati anche in PIX e possono essere controllati e profilati in modo più dettagliato.
Nota
Unity consente di modificare facilmente la risoluzione della destinazione di rendering dell'applicazione in fase di esecuzione tramite la proprietà XRSettings.renderViewportScale . L'immagine finale presentata sul dispositivo ha una risoluzione fissa. La piattaforma esegue un esempio dell'output con risoluzione inferiore per creare un'immagine a risoluzione superiore per il rendering nei display.
UnityEngine.XR.XRSettings.renderViewportScale = 0.7f;
Consigli sulle prestazioni della CPU
Il contenuto seguente illustra procedure di prestazioni più approfondite, destinate in particolare allo sviluppo di Unity & C#.
Riferimenti alla cache
È consigliabile memorizzare nella cache i riferimenti a tutti i componenti pertinenti e a GameObject durante l'inizializzazione perché le chiamate di funzione ripetute, ad esempio GetComponent<T>() e Camera.main , sono più costose rispetto al costo della memoria per archiviare un puntatore. . Camera.main usa semplicemente FindGameObjectsWithTag() sotto, che cerca nel grafico della scena un oggetto fotocamera con il tag "MainCamera".
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
private Camera cam;
private CustomComponent comp;
void Start()
{
cam = Camera.main;
comp = GetComponent<CustomComponent>();
}
void Update()
{
// Good
this.transform.position = cam.transform.position + cam.transform.forward * 10.0f;
// Bad
this.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 10.0f;
// Good
comp.DoSomethingAwesome();
// Bad
GetComponent<CustomComponent>().DoSomethingAwesome();
}
}
Nota
Evitare GetComponent(string)
Quando si usa GetComponent(), sono presenti alcuni overload diversi. È importante usare sempre le implementazioni basate su tipi e mai l'overload di ricerca basato su stringa. La ricerca in base alla stringa nella scena è più costosa rispetto alla ricerca in base al tipo.
(Buono) Component GetComponent(Type type)
(Buono) T GetComponent<T>()
(Non valido) Component GetComponent(string)>
Evitare operazioni costose
Evitare l'uso di LINQ
Anche se LINQ può essere pulito e facile da leggere e scrivere, in genere richiede più calcolo e memoria rispetto a se l'algoritmo è stato scritto manualmente.
// Example Code using System.Linq; List<int> data = new List<int>(); data.Any(x => x > 10); var result = from x in data where x > 10 select x;API Unity comuni
Alcune API Unity, anche se utili, possono essere costose da eseguire. La maggior parte di questi comporta la ricerca di un elenco corrispondente di GameObjects nell'intero grafico della scena. Queste operazioni possono essere in genere evitate memorizzando nella cache i riferimenti o implementando un componente di gestione per GameObjects per tenere traccia dei riferimenti in fase di esecuzione.
GameObject.SendMessage() GameObject.BroadcastMessage() UnityEngine.Object.Find() UnityEngine.Object.FindWithTag() UnityEngine.Object.FindObjectOfType() UnityEngine.Object.FindObjectsOfType() UnityEngine.Object.FindGameObjectsWithTag() UnityEngine.Object.FindGameObjectsWithTag()
Nota
SendMessage() e BroadcastMessage() devono essere eliminati a tutti i costi. Queste funzioni possono essere nell'ordine di 1000 volte più lente rispetto alle chiamate di funzione diretta.
Attenzione alla boxe
Il boxing è un concetto fondamentale del linguaggio e del runtime C#. Si tratta del processo di wrapping di variabili tipiizzate da valore, ad
charesempio ,int,boole così via, in variabili tipizzate di riferimento. Quando una variabile tipizzata da valore è "boxed", viene sottoposta a wrapping in unSystem.Objectoggetto , archiviato nell'heap gestito. La memoria viene allocata e, infine, quando eliminata deve essere elaborata dal Garbage Collector. Queste allocazioni e deallocazione comportano un costo di prestazioni e in molti scenari non sono necessarie o possono essere facilmente sostituite da un'alternativa meno costosa.Per evitare la conversione boxing, assicurarsi che le variabili, i campi e le proprietà in cui vengono archiviati tipi numerici e struct (incluso
Nullable<T>) siano tipizzati come tipi specifici, adintesempio ,float?oMyStruct, anziché utilizzare l'oggetto . Se questi oggetti vengono inseriti in un elenco, assicurarsi di usare un elenco fortemente tipizzato, adList<int>esempio anzichéList<object>oArrayList.Esempio di boxing in C#
// boolean value type is boxed into object boxedMyVar on the heap bool myVar = true; object boxedMyVar = myVar;
Percorsi di codice ripetuti
Tutte le funzioni di callback di Unity ripetute (ad esempio Update) eseguite più volte al secondo e/o frame devono essere scritte con attenzione. Qualsiasi operazione costosa in questo caso ha un impatto enorme e coerente sulle prestazioni.
Funzioni di callback vuote
Anche se il codice seguente può sembrare innocente nell'applicazione, soprattutto perché ogni script Unity viene inizializzato automaticamente con un metodo Update, questi callback vuoti possono diventare costosi. Unity opera avanti e indietro tra un limite di codice non gestito e gestito, tra il codice UnityEngine e il codice dell'applicazione. Il cambio di contesto su questo bridge è piuttosto costoso, anche se non c'è nulla da eseguire. Ciò diventa particolarmente problematico se l'app include 100 gameobject con componenti con callback Unity ripetuti vuoti.
void Update() { }
Nota
Update() è la manifestazione più comune di questo problema di prestazioni, ma altri callback di Unity ripetuti, ad esempio i seguenti possono essere ugualmente negativi, se non peggiori: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), e così via.
Operazioni per favorire l'esecuzione una volta per fotogramma
Le API Unity seguenti sono operazioni comuni per molte app holographic. Anche se non sempre possibile, i risultati di queste funzioni possono essere comunemente calcolati una volta e i risultati riutilizzati nell'applicazione per un determinato frame.
a) È consigliabile avere una classe o un servizio Singleton dedicato per gestire lo sguardo fisso di Raycast nella scena e quindi riutilizzare questo risultato in tutti gli altri componenti della scena, invece di eseguire operazioni Raycast ripetute e identiche da ogni componente. Alcune applicazioni possono richiedere raycast di origini diverse o su diversi LayerMasks.
UnityEngine.Physics.Raycast() UnityEngine.Physics.RaycastAll()b) Evitare le operazioni GetComponent() nei callback di Unity ripetuti come Update() memorizzando nella cache i riferimenti in Start() o Awake()
UnityEngine.Object.GetComponent()c) È consigliabile creare un'istanza di tutti gli oggetti, se possibile, durante l'inizializzazione e usare il pool di oggetti per riciclare e riutilizzare GameObject durante il runtime dell'applicazione
UnityEngine.Object.Instantiate()Evitare interfacce e costrutti virtuali
Richiamare chiamate di funzione tramite interfacce o oggetti diretti o chiamare funzioni virtuali può spesso essere molto più costoso rispetto all'uso di costrutti diretti o chiamate di funzione diretta. Se la funzione virtuale o l'interfaccia non è necessaria, è necessario rimuoverla. Tuttavia, il successo delle prestazioni per questi approcci vale la pena di essere compromesso se l'uso di questi approcci semplifica la collaborazione allo sviluppo, la leggibilità del codice e la gestibilità del codice.
In genere, è consigliabile non contrassegnare campi e funzioni come virtuali a meno che non vi sia una chiara aspettativa che questo membro debba essere sovrascritto. È consigliabile prestare particolare attenzione ai percorsi di codice ad alta frequenza chiamati più volte per fotogramma o anche una volta per fotogramma, ad esempio un
UpdateUI()metodo.Evitare di passare struct in base al valore
A differenza delle classi, gli struct sono tipi valore e quando vengono passati direttamente a una funzione, il relativo contenuto viene copiato in un'istanza appena creata. Questa copia aggiunge il costo della CPU, oltre a una maggiore quantità di memoria nello stack. Per gli struct di piccole dimensioni, l'effetto è minimo e quindi accettabile. Tuttavia, per le funzioni richiamate ripetutamente ogni frame e funzioni che accettano struct di grandi dimensioni, se possibile modificare la definizione della funzione da passare per riferimento. Altre informazioni sono disponibili qui
Varie
Fisica
a) In genere, il modo più semplice per migliorare la fisica consiste nel limitare la quantità di tempo dedicato alla fisica o il numero di iterazioni al secondo. In questo modo si riduce l'accuratezza della simulazione. Vedere TimeManager in Unity
b) I tipi di collisori in Unity hanno caratteristiche di prestazioni molto diverse. L'ordine seguente elenca i collisori più performanti per i collisori meno performanti da sinistra a destra. È importante evitare collisori mesh, che sono sostanzialmente più costosi rispetto ai collisori primitivi.
Mesh Sphere < Capsule < Box <<< Mesh (Convex) < (non Convex)
Animazioni
Disabilitare le animazioni inattive disabilitando il componente Animator (la disabilitazione dell'oggetto gioco non avrà lo stesso effetto). Evitare modelli di progettazione in cui un animatore si trova in un ciclo impostando un valore sulla stessa cosa. Questa tecnica comporta un sovraccarico notevole, senza alcun effetto sull'applicazione. Scopri di più qui.
Algoritmi complessi
Se l'applicazione usa algoritmi complessi, ad esempio cinematica inversa, ricerca di percorsi e così via, cercare un approccio più semplice o modificare le impostazioni pertinenti per le prestazioni
Consigli sulle prestazioni da CPU a GPU
In genere, le prestazioni da CPU a GPU si riduce alle chiamate di estrazione inviate alla scheda grafica. Per migliorare le prestazioni, le chiamate di disegno devono essere strategicamente ridotte o b) ristrutturate per ottenere risultati ottimali. Poiché le chiamate di disegno sono a elevato utilizzo di risorse, ridurle ridurrà il lavoro complessivo richiesto. Inoltre, le modifiche dello stato tra le chiamate di disegno richiedono costosi passaggi di convalida e conversione nel driver di grafica e, di conseguenza, la ristrutturazione delle chiamate di disegno dell'applicazione per limitare le modifiche dello stato (ad esempio materiali diversi e così via) può migliorare le prestazioni.
Unity ha un ottimo articolo che offre una panoramica e approfondisce le chiamate di disegno in batch per la piattaforma.
Rendering con istanza a passaggio singolo
Single Pass Instanced Rendering in Unity consente di ridurre le chiamate di disegno per ogni occhio a una chiamata di disegno con istanza. A causa della coerenza della cache tra due chiamate di disegno, c'è anche un miglioramento delle prestazioni della GPU.
Per abilitare questa funzionalità nel progetto Unity
- Aprire Impostazioni OpenXR (passare a Modifica>impostazioni> progettoXR Plugin Management>OpenXR).
- Selezionare Single Pass Instanced dal menu a discesa Modalità rendering .
Per informazioni dettagliate su questo approccio di rendering, leggere gli articoli seguenti di Unity.
- Come ottimizzare le prestazioni di realtà aumentata e realtà virtuale con rendering stereo avanzato
- Creazione di istanze a passaggio singolo
Nota
Un problema comune con il rendering con istanza a passaggio singolo si verifica se gli sviluppatori hanno già shader personalizzati esistenti non scritti per la creazione di istanze. Dopo aver abilitato questa funzionalità, gli sviluppatori possono notare alcuni GameObject di cui viene eseguito il rendering solo con un occhio. Ciò è dovuto al fatto che gli shader personalizzati associati non hanno le proprietà appropriate per l'istanza.
Invio in batch statico
Unity è in grado di inviare in batch molti oggetti statici per ridurre le chiamate di disegno alla GPU. L'invio in batch statico funziona per la maggior parte degli oggetti Renderer in Unity che 1) condividono lo stesso materiale e 2) sono contrassegnati come statici (selezionare un oggetto in Unity e selezionare la casella di controllo in alto a destra del controllo). Gli oggetti GameObject contrassegnati come statici non possono essere spostati nel runtime dell'applicazione. Pertanto, l'invio in batch statico può essere difficile da applicare in HoloLens, dove praticamente ogni oggetto deve essere posizionato, spostato, ridimensionato e così via. Per le cuffie immersive, l'invio in batch statico può ridurre notevolmente le chiamate di disegno e migliorare così le prestazioni.
Per altri dettagli, vedere Batch staticoin Draw Call Batching in Unity .
Invio in batch dinamico
Poiché è problematico contrassegnare gli oggetti come statici per lo sviluppo holoLens, il batch dinamico può essere un ottimo strumento per compensare questa funzionalità mancante. Può essere utile anche nelle cuffie immersive. Tuttavia, l'invio in batch dinamico in Unity può essere difficile da abilitare perché GameObjects deve a ) condividere lo stesso materiale e b) soddisfare un lungo elenco di altri criteri.
Leggere Batching dinamicoin Draw Call Batching in Unity per l'elenco completo. In genere, gameobject diventano non validi per essere raggruppati dinamicamente, perché i dati della mesh associati non possono essere più di 300 vertici.
Altre tecniche
L'invio in batch può verificarsi solo se più GameObject sono in grado di condividere lo stesso materiale. In genere, questa operazione verrà bloccata dalla necessità che GameObjects disponga di una trama univoca per il rispettivo materiale. È comune combinare trame in una trama grande, un metodo noto come Atlante delle trame.
Inoltre, è preferibile combinare le mesh in un unico GameObject, dove possibile e ragionevole. Ogni renderer in Unity ha la chiamata di disegno associata rispetto all'invio di una mesh combinata in un renderer.
Nota
La modifica delle proprietà di Renderer.material in fase di esecuzione crea una copia del materiale e quindi potenzialmente interrompe l'invio in batch. Usare Renderer.sharedMaterial per modificare le proprietà del materiale condiviso in GameObjects.
Consigli sulle prestazioni della GPU
Larghezza di banda e frequenza di riempimento
Quando si esegue il rendering di un frame nella GPU, un'applicazione è associata alla larghezza di banda della memoria o alla frequenza di riempimento.
-
La larghezza di banda della memoria è la frequenza di letture e scritture che la GPU può eseguire dalla memoria
- In Unity modificare Qualità trama in Modifica>impostazioni progetto Impostazioni>qualità.
-
La frequenza di riempimento si riferisce ai pixel che possono essere disegnati al secondo dalla GPU.
- In Unity usare la proprietà XRSettings.renderViewportScale .
Ottimizzare la condivisione del buffer di profondità
È consigliabile abilitare la condivisione del buffer di profondità per ottimizzare la stabilità degli ologrammi. Quando si abilita la riprogettazione in fase avanzata basata sulla profondità con questa impostazione, è consigliabile selezionare il formato di profondità a 16 bit anziché il formato di profondità a 24 bit . I buffer di profondità a 16 bit ridurranno drasticamente la larghezza di banda (e quindi l'alimentazione) associata al traffico del buffer di profondità. Questo può essere un grande miglioramento sia nella riduzione della potenza che nelle prestazioni. Esistono tuttavia due possibili risultati negativi usando il formato di profondità a 16 bit.
Z-Fighting
La fedeltà dell'intervallo di profondità ridotto rende più probabile che si verifichi il combattimento z con 16 bit rispetto a 24 bit. Per evitare questi artefatti, modificare i piani di clip vicini/lontani della fotocamera Unity per tenere conto della precisione inferiore. Per le applicazioni basate su HoloLens, un piano di clip lontano di 50 m invece dei 1000 m predefiniti di Unity può in genere eliminare qualsiasi combattimento z.
Buffer stencil disabilitato
Quando Unity crea una trama di rendering con profondità a 16 bit, non viene creato alcun buffer stencil. Selezionando il formato di profondità a 24 bit, come descritto nella documentazione di Unity, verranno creati un buffer z a 24 bit e un buffer stencil a 8 bit (se 32 bit è applicabile in un dispositivo, ad esempio HoloLens), come in genere accade.
Evitare effetti a schermo intero
Le tecniche che operano a schermo intero possono essere costose perché il loro ordine di grandezza è di milioni di operazioni ogni fotogramma. È consigliabile evitare effetti post-elaborazione , ad esempio anti-aliasing, bloom e altro ancora.
Impostazioni di illuminazione ottimali
L'illuminazione globale in tempo reale in Unity può offrire risultati visivi eccezionali, ma comporta costosi calcoli di illuminazione. È consigliabile disabilitare l'illuminazione globale in tempo reale per ogni file di scena unity tramite impostazioni > diilluminazionedel rendering> della finestra> Deselezionare Illuminazione globale in tempo reale.
Inoltre, è consigliabile disabilitare tutti i cast di ombreggiatura perché aggiungono anche passaggi GPU costosi in una scena unity. Le ombre possono essere disabilitate per ogni luce, ma possono anche essere controllate in modo olistico tramite le impostazioni di qualità.
Redigere>Impostazioni progetto, quindi selezionare la categoria >Qualità selezionare Bassa qualità per la piattaforma UWP. È anche possibile impostare la proprietà Shadows su Disable Shadows (Disabilita ombreggiature).
È consigliabile usare l'illuminazione cotta con i modelli in Unity.
Ridurre il numero di poli
Il numero di poligoni viene ridotto di uno dei due
- Rimozione di oggetti da una scena
- Decimazione delle risorse, che riduce il numero di poligoni per una determinata mesh
- Implementazione di un sistema LOD (Level of Detail) nell'applicazione, che esegue il rendering di oggetti lontani con una versione poligonale inferiore della stessa geometria
Informazioni sugli shader in Unity
Un'approssimazione semplice per confrontare gli shader nelle prestazioni consiste nell'identificare il numero medio di operazioni eseguite in fase di esecuzione. Questa operazione può essere eseguita facilmente in Unity.
Seleziona l'asset shader o seleziona un materiale, quindi nell'angolo in alto a destra della finestra del controllo. Seleziona l'icona a ingranaggio seguita da "Seleziona shader"
Con l'asset shader selezionato, seleziona il pulsante "Compila e mostra codice" nella finestra del controllo
Dopo la compilazione, cercare la sezione statistiche nei risultati con il numero di operazioni diverse sia per il vertex shader che per il pixel shader (Nota: i pixel shader sono spesso chiamati anche fragment shader)
Ottimizzare i pixel shader
Esaminando i risultati delle statistiche compilate usando il metodo precedente, il fragment shader eseguirà in genere più operazioni rispetto al vertex shader, in media. Il fragment shader, noto anche come pixel shader, viene eseguito per pixel sull'output dello schermo, mentre il vertex shader viene eseguito solo per ogni vertice di tutte le mesh disegnate sullo schermo.
Di conseguenza, non solo i fragment shader hanno più istruzioni rispetto ai vertex shader a causa di tutti i calcoli di illuminazione, i fragment shader vengono quasi sempre eseguiti su un set di dati più grande. Ad esempio, se l'output dello schermo è un'immagine 2k per 2k, il fragment shader può essere eseguito 2.000*2.000 = 4.000.000 volte. Se si esegue il rendering di due occhi, questo numero raddoppia poiché sono presenti due schermi. Se un'applicazione di realtà mista ha più passaggi, effetti di post-elaborazione a schermo intero o rendering di più mesh nello stesso pixel, questo numero aumenta notevolmente.
Pertanto, la riduzione del numero di operazioni nel fragment shader può in genere offrire maggiori miglioramenti delle prestazioni rispetto alle ottimizzazioni nel vertex shader.
Alternative agli shader Standard Unity
Invece di usare un rendering basato fisicamente (PBR) o un altro shader di alta qualità, esaminare l'uso di uno shader più efficiente ed economico. Il toolkit Realtà mista fornisce lo shader standard MRTK ottimizzato per i progetti di realtà mista.
Unity offre anche opzioni di shader non illuminate, con vertex illuminate, diffuse e altre opzioni di shader semplificate che sono più veloci rispetto allo shader Standard Unity. Per informazioni più dettagliate, vedi Utilizzo e prestazioni degli shader predefiniti .
Precaricamento dello shader
Usa il precaricamento degli shader e altri trucchi per ottimizzare il tempo di caricamento dello shader. In particolare, il precaricamento dello shader significa che non vedrai alcun hitches a causa della compilazione dello shader di runtime.
Limitare l'overdraw
In Unity è possibile visualizzare l'overdraw per la scena attivando il menu della modalità disegno nell'angolo superiore sinistro della visualizzazione Scena e selezionando Sovrascriva.
In genere, l'overdraw può essere attenuato eliminando gli oggetti in anticipo prima che vengano inviati alla GPU. Unity fornisce informazioni dettagliate sull'implementazione di Occlusion Culling per il motore.
Consigli sulla memoria
Un'allocazione eccessiva della memoria & operazioni di deallocazione può avere effetti negativi sull'applicazione olografica, con conseguente incoerenza di prestazioni, frame bloccati e altri comportamenti dannosi. È particolarmente importante comprendere le considerazioni sulla memoria durante lo sviluppo in Unity poiché la gestione della memoria è controllata dal Garbage Collector.
Garbage Collection
Le app olografiche perdono il tempo di elaborazione per il Garbage Collector (GC) quando il gc viene attivato per analizzare gli oggetti che non sono più nell'ambito durante l'esecuzione e la relativa memoria deve essere rilasciata, in modo che possa essere resa disponibile per il riutilizzo. Le allocazioni costanti e le allocazioni richiedono in genere un'esecuzione più frequente del Garbage Collector, danneggiando così le prestazioni e l'esperienza utente.
Una delle procedure più comuni che comporta un'eccessiva garbage collection non consiste nel memorizzare nella cache i riferimenti a componenti e classi nello sviluppo di Unity. Tutti i riferimenti devono essere acquisiti durante Start() o Awake() e riutilizzati in funzioni successive, ad esempio Update() o LateUpdate().
Altri suggerimenti rapidi:
- Usare la classe C# StringBuilder per compilare in modo dinamico stringhe complesse in fase di esecuzione
- Rimuovere le chiamate a Debug.Log() quando non sono più necessarie, perché vengono comunque eseguite in tutte le versioni di compilazione di un'app
- Se l'app olografica richiede in genere molta memoria, è consigliabile chiamare System.GC.Collect() durante le fasi di caricamento, ad esempio quando si presenta una schermata di caricamento o transizione
Pool di oggetti
Il pool di oggetti è una tecnica comune per ridurre il costo dell'allocazione continua degli oggetti e delle deallocazione. Questa operazione viene eseguita allocando un pool di grandi dimensioni di oggetti identici e riutilizzando le istanze disponibili inattive di questo pool invece di generare e distruggere costantemente oggetti nel tempo. I pool di oggetti sono ideali per i componenti riutilizzabili che hanno una durata variabile durante un'app.
Prestazioni di avvio
È consigliabile avviare l'app con una scena più piccola, quindi usare SceneManager.LoadSceneAsync per caricare il resto della scena. In questo modo l'app può raggiungere uno stato interattivo il più velocemente possibile. Durante l'attivazione della nuova scena potrebbe verificarsi un picco elevato della CPU e che qualsiasi contenuto sottoposto a rendering potrebbe balbuziere o intoppi. Un modo per ovviare a questo errore consiste nell'impostare la proprietà AsyncOperation.allowSceneActivation su "false" nella scena caricata, attendere il caricamento della scena, cancellare lo schermo su nero e quindi impostarlo di nuovo su "true" per completare l'attivazione della scena.
Tenere presente che durante il caricamento della scena di avvio, la schermata iniziale olografica viene visualizzata all'utente.