Questa pagina descrive problemi di performance comuni e migliori pratiche per mitigarli.
Calcolo dello script
Le operazioni costose in codice Lua richiedono più tempo per essere elaborate e possono quindi influenzare il tasso di frame rate. A meno che non venga eseguito in parallelo, il codice Lua viene eseguito in sincronia e blocca il thread principale fino a quando non incontri una funzione che genera il Filo.
Problemi comuni
Operazioni intense su strutture di tabelle - Operazioni complesse come serializzazione, deserializzazione e clonazione profonda incurano un alto costo di prestazioni, specialmente su strutture di tabelle grandi. Questo è particolarmente vero se queste operazioni sono ricorsive o coinvolgono l'iterazione su strutture di dati molto grandi.
Eventi ad alta frequenza - Legare operazioni costose a eventi basati sul frame di RunService senza limitare la frequenza in cui queste operazioni vengono ripetute ogni frame, il che spesso risulta in un aumento inutile del tempo di calcolo. Questi eventi includono:
Mitigazione
- Invoca il codice sui RunService eventi in modo da poter usare il codice in casi in cui l'invocazione ad alta frequenza è essenziale (ad esempio, l'aggiornamento della Telecamera). Puoi eseguire la maggior parte del codice in altri eventi o meno frequentemente in un loop.
- Distribuisci le grandi o costose attività utilizzando task.wait() per distribuire il lavoro su più frame.
- Identificare e ottimizzare operazioni non necessariamente costose e utilizzare multithreading per le attività computazionalmente costose che non richiedono l'accesso al modello di dati.
- Alcuni script lato server possono beneficiare di Generazione del codice nativo, un semplice flag che compila uno script in codice macchina piuttosto che in codice binario.
MicroProfiler Scopi
Scopo | Calcolo associato |
RunService.PreRender | Codice in esecuzione sull'evento PreRender |
RunService.PreSimulation | Codice in esecuzione sull'evento Stepped |
RunService.PostSimulation | Codice in esecuzione sull'evento Heartbeat |
RunService.Heartbeat | Codice in esecuzione sull'evento Heartbeat |
For more information on debugging scripts using the MicroProfiler, see the debug library, which includes functions for tagging specific code and further increasing specificity, such as debug.profilebegin and debug.profileend . Many Roblox API methods called by scripts also have their own associati microprofiler tags that can provide useful signal.
Uso della memoria dello script
Le perdite di memoria possono verificarsi quando scrivi script che consumano memoria che il raccoglitore di spazzatura non può rilasciare correttamente quando non è più in uso. Le perdite sono specificamente pervasive sul Server, poiché possono essere online continuamente per molti giorni, mentre una sessione client è molto più breve.
I seguenti valori della memoria nella Console del Sviluppatore possono indicare un problema che richiede ulteriori investigazioni:
- LuaHeap - Il consumo elevato o in rapida crescita suggerisce una perdita di memoria.
- InstanceCount - Crescere costantemente i numeri delle istanze suggerisce che alcune istanze nel tuo codice non stanno essere raccolte in modo da spazzatura.
- PlaceScriptMemory - Fornisce uno script per la distribuzione dello script dell'uso della memoria.
Problemi comuni
Lasciando le connessioni connesse - Il motore non raccoglie mai i dati degli eventi connessi a un'istanza e tutti i valori riferiti all'interno della Richiama. Pertanto, le connessioni attive degli eventi e del codice all'interno delle istanze connesse, delle funzioni connesse e dei valori riferiti, sono fuori dal raggio di azione del raccoglitore di memoria, anche dopo il fatto che gli eventi vengono eseguiti.
Although events are disconnected when the instance they belong to is destroyed, a common mistake is to assume this applies to Player objects. After a user leaves an esperienza, the engine doesn't automatically destroy their representative Player object and character modello, so connections to
Tabelle - Inserimento di oggetti in tabelle ma non rimozione quando non sono più necessari quando non sono più necessari causa un consumo di memoria non necessario, specialmente per le tabelle che tracciano i dati dell'utente quando si uniscono. Ad esempio, il seguente esempio di codice crea una tabella che aggiunge informazioni dell'utente ogni volta che si unisce:
Esempiolocal playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- qualche informazioneend)Se non rimuovi queste entradi quando non sono più necessarie, la tabella continua a crescere in dimensioni e consuma più memoria mentre più utenti si uniscono alla Sessione. Qualsiasi codice che itera su questa tabella diventa anche più costoso in termini di calcoli poiché la tabella cresce in dimensioni.
Mitigazione
Per pulire tutti i valori utilizzati per prevenire perdite di memoria:
Disconnect all connections - Go through your code base make sure each connection is clean up via one of the following paths:
- Disconnessione manuale utilizzando la funzione Disconnect() .
- Distruggere l'istanza a cui appartiene l'evento con la funzione Destroy() .
- Distruggere lo script oggetto che la connessione traccia indietro.
Rimuovi gli oggetti e i personaggi del giocatore dopo aver lasciato - implementa il codice per assicurarti che non ci siano connessioni persistenti dopo che un utente lascia, come nel seguente esempio:
EsempioPlayers.PlayerAdded:Connect(function(player)player.CharacterRemoving:Connect(function(character)task.defer(character.Destroy, character)end)end)Players.PlayerRemoving:Connect(function(player)task.defer(player.Destroy, player)end)
Calcolo fisico
La simulazione di fisica eccessiva può essere una causa chiave del tempo di calcolo per frame aumentato sia sul server che sul client.
Problemi comuni
Frequenza di ripetizione del tempo di fisica eccessiva - Per impostazione predefinita, il comportamento di step è in modalità adattiva , in cui le fasi di fisica si ripetono a 60 Hz, 120 Hz o 240 Hz, a seconda della complessità del meccanismo fisico.
Un modo fisso con una migliore accuratezza della fisica è anche disponibile, che forza tutte le assemblie fisiche a passare a 240 Hz (quattro volte per frame). Ciò risulta in un calcolo significativamente più elevato per ciascun frame.
Numero eccessivo di complessità di oggetti simulati - Più 3D assemblies che sono simulati, più lunghe sono le calcoli fisici per ciascun frame. Solitamente, le esperienze avranno oggetti simulati che non hanno bisogno di essere o avranno meccanismi che hanno più vincoli e articolazioni di cui non hanno bisogno.
Rilevamento delle collisioni troppo preciso - Le parti mesh hanno una proprietà CollisionFidelity per rilevare la collisione che offre una varietà di modelli con diversi livelli di impatto di prestazioni. La modalità di rilevazione delle collisioni più performante per le parti mesh ha il costo di prestazioni più costoso e richiede più tempo per calcolare.
Mitigazione
Ancorare parti che non richiedono simulazione - Ancorare tutte le parti che non richiedono di essere guidate dalla fisica, come per i NPC statici.
Usa adaptive physics stepping - Adaptive stepping dinamica regola il tasso di calcoli fisici per i meccanismi fisici, consentendo aggiornamenti fisici meno frequenti in alcuni casi.
Riduci la complessità del meccanismo * Ove possibile, minimizza il numero di vincoli fisici o congiunte in un'assembla.
- Riduci la quantità di collisioni di sottomissione all'interno di un meccanismo, come applicando limiti o restrizioni di non collisioni ai limbi ragdoll per impedire loro di collisionare tra loro.
Riduci l'uso della fedeltà di collisione precisa per le maglie * Per oggetti piccoli o non interattabili in cui gli utenti raramente noteranno la differenza, usa la fedeltà della scatola.
Per gli oggetti di piccole dimensioni o corpi medi, usa la fedeltà della scatola o della nave, a seconda della forma.
Per oggetti grandi e molto complessi, costruisci collisioni personalizzate utilizzando parti invisibili quando possibile.
Per gli oggetti che non richiedono collisioni, disabilita le collisioni e usa la fedeltà della scatola o della carcassa, poiché la geometria delle collisioni viene ancora memorizzata nella memoria.
Puoi rendere geometria di collisione per scopi di debug in Studio attivando fedeltà della collisione dal widget Opzioni di visualizzazione nell'angolo in alto a destra della finestra3D.
In alternativa, puoi applicare il filtro CollisionFidelity = Precise all' Explorer che mostra un conteggio di tutte le parti mesh con la fidelità precisa e ti consente di selezionarle facilmente.
Per un'esperienza di walkthrough in dettaglio su come scegliere un'opzione di fedeltà di collisione che bilancia le tue esigenze di precisione e prestazioni, vedi Imposta i parametri fisici e di rendering .
MicroProfiler Scopi
Scopo | Calcolo associato |
fisicaStep | Calcolo fisico generale |
passaggio di mondo | Passaggi fisici dispari presi per ciascun frame |
Utilizzo della memoria fisica
Il movimento e la rilevazione delle collisioni consuma memoria. Le parti della mesh hanno una proprietà CollisionFidelity che determina l'approccio che viene utilizzato per valutare i limiti di collisione della Mesh, maglia.
Problema comune
I modi di rilevamento delle collisioni predefiniti e precisi consumano notevolmente più memoria dei due altri modelli con forme di collisione di bassa fedeltà.
Se vedi i livelli elevati di utilizzo della memoria sotto Parti fisiche , potresti dover esplorare il ridurre la fiducia di collisione degli oggetti nella tua esperienza.
Come Mitigare
Per ridurre la memoria utilizzata per la fedeltà di collisione:
- For parts that do not need collisions, disable their collisions by setting BasePart.CanCollide , BasePart.CanTouch and BasePart.CanQuery to 1> false1> .
- Riduci la fedeltà delle collisioni usando il CollisionFidelity Configurazione. Box ha il minor sovraffollamento della memoria e Default e 2>Enum.CollisionFidelity.Precise
- Generalmente è sicuro impostare la fedeltà di collisione di qualsiasi parte ancorata a Box .
- Per molto grandi maglie, potresti voler costruire la tua maglia di collisione su oggetti più piccoli con la fedeltà di collisione della scatola.
Umanoidi
Humanoid è una classe che fornisce una gamma di funzionalità per i personaggi giocatore e non giocatore (NPC). Anche se potente, un Humanoid viene fornito con un costo di calcolo significativo.
Problemi comuni
- Lasciare tutti i tipi di stato umanoide abilitati sui NPCs - C'è un costo di performance per lasciare alcuni HumanoidStateTypes abilitati. Disabilita qualsiasi cosa che non sia necessaria per i tuoi NPC. Ad esempio, a meno che il tuo NPC non stia salendo le scale, è sicuro disabilitare lo stato Cl
- Modelli di istantanea istantanea, modifica e respawning con umanoidi frequentemente * Questo può essere intenso per il motore per elaborare, in particolare se questi modelli utilizzano Abbigliamento a più livelli . Questo può anche essere particolarmente problematico in esperienze in cui gli avatar respawn spesso.
- Nel MicroProfiler , le lunghe updateInvalidatedFastClusters tag (oltre 4 ms) sono spesso un segnale che l'istantanea/modifica dell'avatar sta attivando/modificando eccessive invalidazioni.
- Utilizzare Humanoid in casi in cui non sono richiesti - NPC dinamici che non si muovono in generale non hanno bisogno della classe Humanoid .
- Animazioni di gioco su un gran numero di NPC del server - Le animazioni NPC che si eseguono sul server devono essere simulate sul server e replicate al client. Questo può essere uno spreco di sovraffare.
Mitigazione
- Riproduci le animazioni NPC sul cliente - In esperienze con un grande numero di NPC, considera la creazione del Animator sul cliente e l'esecuzione delle animazioni localmente. Ciò riduce il carico sul server e la necessità di replicazione inutili. Consente anche ulteriori ottimizzazioni (ad esempio, la riproduzione delle animazioni solo per i personaggi vicini al personaggio).
- Usa alternative amichevoli per gli umanoidi - I modelli NPC non devono necessariamente contenere un oggetto umanoidi.
- For i NPC statici, usa un semplice AnimationController, perché non devono essere in movimento ma devono solo giocare alle animazioni.
- Per i NPC in movimento, considera di implementare il tuo controller di movimento e usare un AnimationController per le animazioni, a seconda della complessità dei tuoi NPC.
- Disabilita gli stati umanoidi non utilizzati - Usa Humanoid:SetStateEnabled() per abilitare solo gli stati necessari per ciascun umanoidi.
- Modelli NPC della piscina con respawning frequenti - Invece di distruggere completamente un NPC, invia il NPC in una piscina di NPC inattivi. Questo modo, quando è necessario respawnare un nuovo NPC, puoi semplicemente riattivare uno dei NPC dalla piscina. Questo processo è chiamato pooling, che minimizza il numero di volte che i personaggi devono essere istantizzati.
- Spawna solo NPC quando gli utenti sono nelle vicinanze - Non spawnare NPC quando gli utenti non sono in range, e filtrarli quando gli utenti lasciano il loro range.
- Evita di apportare modifiche alla gerarchia dell'avatar dopo averla istanziata. - Alcune modifiche alla gerarchia dell'avatar hanno implicazioni di prestazioni significative. Alcune ottimizzazioni sono disponibili:
- Per le animazioni procedurali personalizzate, non aggiornare le proprietà JointInstance.C0 e JointInstance.C1 ma Motor6D.Transform proprietà. Invece, aggiorna la Proprietà1> Class.Motor6D.Transform1> .
- Se devi associare qualsiasi oggetto BasePart agli Avatar, fallo all'esterno della gerarchia degli avatar Model .
MicroProfiler Scopi
Scopo | Calcolo associato |
stepUmanoidi | Controllo e fisica umanoidi |
animazione di passo | animazioniumanoide e animatore |
aggiornamentoInvalidatiFastClusters | Associazione con l'istantanea creazione o modifica di un Avatar |
Render
Una percentuale significativa del tempo che il client spende per ogni frame è sulla rappresentazione della scena nella finestra attuale. Il server non esegue alcun rendering, quindi questa sezione è esclusiva per il client.
Call di disegno
Un call di disegno è un insieme di istruzioni dall'ingegnere alGPU per rendere qualcosa. I call di disegno hanno un grande sovraffollamento. In generale, più call di disegno per frame, meno tempo di calcolo è speso per rendere un frame.
Puoi vedere quante chiamate di rendering sono attualmente in corso con l'elemento Statistiche di rendering > Timing in Studio. Puoi visualizzare Statistiche di rendering nell'area client premendo 1> Shift1> 3> F23> .
Più oggetti che devono essere disegnati nella tua scena in un determinato frame, più chiamate di disegno vengono eseguite sulGPU. Tuttavia, il motore Roblox utilizza un processo chiamato instancing per ridimensionare le texture simili con le stesse caratteristiche di meshes in un singolo chiamata disegno. In particolare, più meshi con la stessa MeshId vengono gestiti in una sola chiamata disegno quando:
- SurfaceAppearances sono identici. TextureIDs sono identici quando Class.SurfaceSpell non esiste.
- I materiali sono identici quando entrambi SurfaceAppearance e MeshPart.TextureID non esistono.
Altri problemi comuni
Eccessiva densità dell'oggetto - Se un grande numero di oggetti è concentrato con una alta densità, allora il rendimento di questa area della scena richiede più chiamate di disegno. Se stai trovando che la tua frequenza di frame cala quando guardi una certa parte della mappa, questo può essere un segnale positivo che la densità dell'oggetto in questa area è troppo alta.
Oggetti come adesivi, texture e parti non vengono visualizzati correttamente e introducono chiamate di disegno aggiuntive. Pay extra attention to these object types in a scene. In particolare, le modifiche delle proprietà a ParticleEmitters possono avere un impatto drammatico sulle Prestazione.
Opportunità di istallazione mancate - Spesso, una scena includerà lo stesso mesh duplicato più volte, ma ogni copia del mesh ha diversi ID di mesh o texture. Ciò impedisce l'istallazione e può comportare chiamate di disegno non necessarie.
Una causa comune di questo problema è quando viene importata un'intera scena contemporaneamente, invece che le singole risorse vengono importate in Roblox e poi duplicate post-import per assemblare la scena.
Complessità dell'oggetto eccessiva - Anche se non è importante come il numero di chiamate di disegno, il numero di triangoli in una scena influisce sulla durata di un frame per essere Renderizzare. Le scene con un grande numero di proprietà meshi molto complesso impostato su MeshPart.RenderFidelity su troppi meshi sono un problema comune, così come le scene con la proprietà En
Casting dell'ombra eccessivo - La gestione delle ombre è un processo costoso, e le mappe che contengono un alto numero e una densità di oggetti luce che casta le ombre (o un alto numero e una densità di piccole parti influenzate dalle ombre) potrebbero avere problemi di prestazioni.
Alta trasparenza overdraw - Posizionare gli oggetti con la trasparenza parziale l'uno vicino all'altro costringe il motore a rendere i pixel sovrapposizionati più volte, il che può danneggiare le Prestazione. Per ulteriori informazioni sull'identificazione e la correzione di questo problema, vedi Delete Layered Transparencies .
Mitigazione
- Instancing identical meshes and reducing the amount of unique meshes - Se ci assicuri che tutti i meshi identici hanno gli stessi ID di base, il motore può riconoscere e rendere conoscibili in un unico draw call. Assicurati di caricare solo ciascun mesh in una mappa una volta e poi duplicarli in Studio per il riutilizzo invece di importare grandi mappe come
- Culling - Culling describe the process of eliminating draw calls for objects that don't factor into the final rendered frame. By default, the engine skips draw calls for objects outside the Telecamera's field of view (frustum culling), but doesn't skip draw calls for objects occluded from view by other objects (oculation culling). If your scene has a large number of draw calls, consider implementing your own additional culling at runtime dynamically for every
- Per gli ambienti interni, implementa un sistema di camera o portale che nasconde gli oggetti non attualmente occupati da nessun utente.
- Riduzione della fedeltà di rendering - Imposta la fedeltà di rendering su Automatico o Prestazioni . Ciò consente alle maglie di cadere a soluzioni più semplici, il che può ridurre il numero di poligoni che devono essere disegnati.
- Disabilitare il cast dell'ombra su parti e oggetti di luce appropriati - La complessità delle ombre in una scena può essere ridotta selezionalmente disabilitando le proprietà di cast dell'ombra su parti e oggetti di luce. Questo può essere fatto al momento di modifica o dinamicamente in tempo Tempo esecuzione. Alcuni esempi sono:
Usa la proprietà BasePart.CastShadow per disabilitare il cast-ombra su piccole parti in cui gli ombre non sono probabili da vedere. Questo può essere particolarmente efficace quando applicato solo a parti lontane dalla Telecameradell'utente.
Disabilita ombre su oggetti in movimento quando possibile.
Disabilita Light.Shadows su le istanze di luce in cui l'oggetto non deve castare ombre.
Limitare la gamma e l'angolo delle istanze di luce.
Usa meno istanze di luce.
MicroProfiler Scopi
Scopo | Calcolo associato |
Prepara e esegui | Render generale |
Perform/Scene/computeLightingPerform | Aggiornamenti della griglia leggera e dell'ombra |
LightGridCPU | Aggiornamenti della griglia di luce Voxel |
Sistema delle mappe ombra | Mappa delle ombre |
Perform/Scene/UpdateView | Preparazione per aggiornamenti rendering e particle |
Perform/Scene/RenderView | Render링 e post-elaborazione |
Reti e Replicazione
La rete e la replicazione descrive il processo in cui i dati vengono inviati tra il server e i client connessi. L'informazione viene inviata tra il client e il server ogni frame, ma quantità più grandi di informazioni richiedono più tempo di elaborazione.
Problemi comuni
Traffico remoto eccessivo - L'invio di una grande quantità di dati attraverso RemoteEvent o RemoteFunction oggetti o l'invocazione di loro molto frequentemente può comportare un'ampia quantità di tempo di elaborazione speso per elaborare i pacchetti in arrivo in ogni frame. Gli errori comuni includono:
- Replicazione dei dati ogni frame che non ha bisogno di essere replicato.
- Replicazione dei dati sull'input dell'utente senza alcun meccanismo per limitarlo.
- Dispatching più dati di quanto richiesto. Ad esempio, l'invio dell'intero inventario del Giocatorequando acquista un oggetto invece che i dettagli dell'oggetto acquistato.
Creation o rimozione di alberi di istanza complessi - Quando una modifica viene apportata al modello di dati sul Server, viene replicata ai client connessi. Ciò significa che la creazione e la distruzione di grandi gerarchie di istanza come mappe in tempo di esecuzione può essere molto intensive di rete.
Un culpabile comune qui è i dati di animazione complessi salvati dai plugin dell'animatore nelle rig. Se questi non vengono rimossi prima che il gioco venga pubblicato e il modello animato venga clonato regolarmente, una grande quantità di dati viene replicata inutilmente.
Server-side TweenService - Se TweenService viene utilizzato per tween un server di oggetti, la proprietà tweened viene replicata a ogni client ogni frame. Non solo ciò comporta che il tween sia jittery mentre il traffico di rete aumenta, ma provoca un sacco di traffico di rete inutilizzato.
Mitigazione
Puoi usare le seguenti strategie per ridurre la replicazione non necessaria:
- Evita di inviare grandi quantità di dati contemporaneamente tramite eventi remoti . Invece, invia solo i dati necessari a una frequenza più bassa. Ad esempio, per lo stato di un personaggio, replica quando cambia invece che ogni frame.
- Ripristina gli alberi degli istanziamenti complessi come le mappe e caricali in pezzi per distribuire il lavoro di replicazione di questi su più frame.
- Pulisci i metadati dell'animazione , in particolare la cartella animazioni delle navi, dopo l'importazione.
- Riproduzione dell'istanza non necessaria , in particolare nei casi in cui il server non ha bisogno di avere conoscenza delle istanze che vengono create. Ciò include:
- Effetti visivi come un'esplosione o un incantesimo magico. Il server deve sapere solo la posizione per determinare l'esito, mentre i client possono creare visualizzazioni localmente.
- Modelli di visualizzazione dell'articolo a prima persona.
- Tween oggetti sul client piuttosto che sul Server.
MicroProfiler Scopi
Scopo | Calcolo associato |
Pacchetto di processi | Elaborazione dei pacchetti di rete in arrivo, come le chiamate all'evento e le modifiche delle proprietà |
Alloca la banda e esegui i mittenti | Eventi in arrivo rilevanti nei server |
Utilizzo della memoria delle risorse
Il meccanismo di impatto più elevato disponibile ai creatori per migliorare l'utilizzo della memoria del client è abilitare streaming delle istanze .
Streaming dell'istanza
Il caricamento in streaming dell'istanza carica in modo selettivo parti del modello di dati che non sono richieste, il che può comportare un caricamento del client in ritardo e aumentare la capacità del client di prevenire gli errori quando viene sottoposto a pressioni di memoria.
Se stai riscontrando problemi di memoria e hai disabilitato la sincronizzazione delle istanze, considera di aggiornare la tua esperienza per supportarla, in particolare se il tuo mondo 3D è grande. La sincronizzazione delle istanze è basata sulla distanza nello Spazio3D, quindi i mondi più grandi naturalmente ne traranno vantaggio.
Se è abilitato lo streaming delle istanze, puoi aumentare l'aggressività. Ad esempio, considera:
- Riduzione dell'uso della persistente StreamingIntegrity .
- Riduzione del radius di streaming .
For more information on streaming options and their benefits, see Streaming Properties .
Altri problemi comuni
- Duplicazione delle risorse - Un errore comune è caricare la stessa risorsa più volte, risultando in ID risorse diversi. Ciò può comportare il caricamento dello stesso contenuto in memoria più volte.
- Eccessivo volume delle risorse - Anche quando le risorse non sono identiche, ci sono casi in cui le opportunità per riutilizzare la stessa risorsa e risparmiare memoria vengono mancate.
- File audio - I file audio possono essere un contributore sorprendente all'utilizzo della memoria, in particolare se li carichi tutti nel client in una volta sola piuttosto che caricare solo ciò di cui hai bisogno per una parte dell'esperienza. Per le strategie, vedi Tempi di caricamento.
- Alti tramegni di risoluzione dei testi - Il consumo della memoria grafica per una texture non è correlato alla dimensione della texture sul disco, ma piuttosto al numero di pixel nella Struttura.
- Ad esempio, una texture di pixel 1024x1024 consuma quattro volte la memoria grafica di una Struttura512x512.
- Le immagini caricate su Roblox vengono transcodizzate in un formato fisso, quindi non ci sono vantaggi di memoria per caricare le immagini in un modello di colore associato a meno pixel per pixel. Allo stesso modo, la compressione delle immagini prima dell'invio o la rimozione del canale alfa dalle immagini che non ne hanno bisogno può ridurre la dimensione delle immagini sul disco, ma non migliora
- Puoi identificare il consumo della memoria grafica per una certa texture espandendo la categoria Grafica nella Console del sviluppatore.
Mitigazione
- Solo caricare risorse una volta - Riutilizzare gli stessi ID delle risorse su oggetti e assicurarsi che le stesse risorse, in particolare le maglie e le immagini, non vengono caricate separatamente più volte.
- Trova e ripara le risorse duplicates - Cerca le parti e le texture della mesh identiche che vengono caricate più volte con ID diversi.
- Anche se non esiste un'API per rilevare automaticamente la somiglianza delle risorse, puoi raccogliere tutti gli ID delle risorse dell'immagine nel tuo posto (e sia manualmente che con uno script), caricarli e confrontarli utilizzando strumenti di confronto esterni.
- Per le parti mesh, la migliore strategia è quella di prendere ID della mesh unici e organizzarli per dimensioni per identificare manualmente le duplicazioni.
- Invece di utilizzare texture separate per colori diversi, carica una singola texture e usa la proprietà SurfaceAppearance.Color per applicare varie tonalità a esso.
- Importazione delle risorse nella mappa separatamente - Invece di importare una mappa intera in una volta, importa e ricostruisce le risorse nella mappa individualmente e le ricostruisce. Il 3D importer non esegue alcuna duplicazione di mesh, quindi se importi una grande mappa con molti singoli riquadri di pavimento, ognuno di questi riquadri verrà importato
- Limita il pixel delle immagini a non più di quanto sia necessario. A meno che un'immagine non occupi una grande quantità di spazio fisico sullo schermo, di solito ha bisogno di almeno 512x512 pixel. La maggior parte delle immagini minori dovrebbe essere inferiore a 256x256 pixel.
- Usa le schede di taglio per garantire il massimo riutilizzo della texture nelle mappe 3D. Per gli step e gli esempi su come creare le schede di taglio, vedi Creazione di schede di taglio .
Caricamenti
Molte esperienze implementano schermi di caricamento personalizzati e utilizzano il metodo ContentProvider:PreloadAsync() per richiedere le risorse in modo che le immagini, i suoni e le maglie vengano caricati nel background.
L'avvantaggio di questo approccio è che ti consente di assicurarti che le parti importanti della tua esperienza siano caricate completamente senza pop-in. Tuttavia, un errore comune è quello di utilizzare in modo eccessivo questo metodo per pre-caricare più risorse di quanto siano effettivamente richieste.
Un esempio di una cattiva pratica è caricare il interoWorkspace . Mentre questo potrebbe prevenire pop-in di texture, aumenta notevolmente il tempo di caricamento.
Invece, utilizzare solo ContentProvider:PreloadAsync() in situazioni necessarie, tra cui:
- Immagini sullo schermo di caricamento.
- Importante immagini nel tuo menu di esperienza, come sfondi e icone dei pulsanti.
- Risorse importanti nell'area di avvio o spawn.
Se devi caricare un grande numero di risorse, ti consigliamo di fornire un pulsante Salta caricamento .