Migliora le prestazioni

*Questo contenuto è tradotto usando AI (Beta) e potrebbe contenere errori. Per visualizzare questa pagina in inglese, clicca qui.

Questa pagina descrive i problemi di prestazioni comuni e le migliori pratiche per mitigarli.

Calcolo dello script

Le operazioni costose nel codice Luau richiedono più tempo per essere elaborate e possono quindi influenzare il tasso di fotogrammi.A meno che non venga eseguito in parallelo, il codice Luau viene eseguito in modo sincronico e blocca il thread principale fino a quando non incontra una funzione che genera il thread.

Problemi comuni

  • Operazioni intense sulle strutture di tabelle - Le operazioni complesse come serializzazione, deserializzazione e clonazione profonda comportano un alto costo di prestazioni, in particolare su grandi strutture di tabelle.Questo è particolarmente vero se queste operazioni sono ricorsive o implicano l'iterazione su strutture dati molto grandi.

  • Eventi ad alta frequenza - Legare operazioni costose ad eventi basati sul framework di RunService senza limitare la frequenza, il che fa sì che queste operazioni vengono ripetute ogni frame, il che spesso provoca un aumento non necessario del tempo di calcolo.Questi eventi includono:

Mitigazione

  • Invoca il codice su RunService eventi in modo sporadico, limitando l'uso ai casi in cui l'invocazione ad alta frequenza è essenziale (ad esempio, l'aggiornamento della fotocamera).Puoi eseguire la maggior parte del codice rimanente in altri eventi o meno frequentemente in un ciclo.
  • Dividi le grandi o costose attività utilizzando task.wait() per diffondere il lavoro su più frame.
  • Identifica e ottimizza operazioni inutilmente costose e usa multithreading per compiti computazionalmente costosi che non hanno bisogno di accedere al modello di dati.
  • Alcuni script lato server possono beneficiare di generazione del codice nativo, una semplice bandiera che compila uno script in codice macchina piuttosto che bytecode.

Scopi del MicroProfiler

ScopoComputazione associata
Esegui servizio.PreRenderCodice in esecuzione sull'evento PreRender
EseguiService.PreSimulazioneCodice in esecuzione sull'evento Stepped
Eseguire il servizio PostSimulationCodice in esecuzione sull'evento Heartbeat
Heartbeat di RunServiceCodice in esecuzione sull'evento Heartbeat

Per maggiori informazioni sulla risoluzione degli script utilizzando il MicroProfiler, vedi la libreria debug, che include funzioni per contrassegnare codice specifico e aumentare ulteriormente la specificità, come debug.profilebegin e debug.profileend.Molti metodi API di Roblox chiamati dagli script hanno anche i propri tag MicroProfiler associati che possono fornire un segnale utile.

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 viene più utilizzato.Le perdite sono specificamente diffuse sul server, perché possono essere online continuamente per molti giorni, mentre una sessione client è molto più breve.

I seguenti valori di memoria nella Console dello sviluppatore possono indicare un problema che richiede ulteriori indagini:

  • LuaHeap - Un consumo elevato o in crescita suggerisce una perdita di memoria.
  • InstanceCount - Consistente aumento del numero di istanze suggerisce che le referenze a alcune istanze nel tuo codice non vengono raccolte regolarmente.
  • PlaceScriptMemory - Fornisce uno script per lo scadimento della memoria degli script.

Problemi comuni

  • Lasciare le connessioni connesse - Il motore non raccoglie mai eventi collegati a un'istanza e qualsiasi valore richiamato all'interno del callback connesso.Pertanto, le connessioni attive di eventi e codice all'interno delle istanze connesse, delle funzioni connesse e dei valori referenziati sono al di fuori del campo di applicazione del raccoglitore di memoria di spazzatura, anche dopo che gli eventi vengono attivati.

    Sebbene gli eventi si disconnettano quando l'istanza a cui appartengono viene distrutta, un errore comune è quello di assumere che questo si applichi agli oggetti Player .Dopo che un utente lascia un'esperienza, il motore non distrugge automaticamente l'oggetto rappresentante Player e il modello di personaggio, quindi le connessioni all'oggetto Player e alle istanze sotto il modello di personaggio, come Player.CharacterAdded, consumano ancora memoria se non le disconnetti nei tuoi script.Questo può causare perdite di memoria molto significative nel tempo sul server poiché centinaia di utenti si uniscono e lasciano l'esperienza.

  • Tabelle - Inserire oggetti nelle tabelle ma non rimuoverli quando non sono più necessari causa un consumo di memoria inutile, in particolare per le tabelle che tracciano i dati utente quando si uniscono.Ad esempio, il seguente esempio di codice crea una tabella che aggiunge le informazioni sull'utente ogni volta che un utente si unisce:

    Esempio

    local playerInfo = {}
    Players.PlayerAdded:Connect(function(player)
    playerInfo[player] = {} -- alcune informazioni
    end)

    Se non rimuovi queste voci quando non sono più necessarie, la tabella continua a crescere in dimensioni e consuma più memoria quando più utenti si uniscono alla sessione.Qualsiasi codice che itera su questa tabella diventa anche più costoso in termini di calcolo man mano che la tabella cresce in dimensioni.

Mitigazione

Per pulire tutti i valori utilizzati per prevenire perdite di memoria:

  • Disconnetti tutte le connessioni - Passa attraverso il tuo codice base assicurati che ogni connessione venga pulita attraverso uno dei seguenti percorsi:

    • Disconnessione manuale utilizzando la funzione Disconnect().
    • Distruggere l'istanza a cui appartiene l'evento con la funzione Destroy().
    • Distruggere l'oggetto script a cui le connessioni si riferiscono.
  • Rimuovi oggetti e personaggi del giocatore dopo aver lasciato - Implementa il codice per garantire che nessuna connessione persista dopo che un utente se ne va, come nel seguente esempio:

    Esempio

    Players.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 della fisica

La simulazione fisica eccessiva può essere una causa principale dell'aumento del tempo di calcolo per frame sul server e sul client.

Problemi comuni

  • Frequenza del passo di fisica eccessiva - Per impostazione predefinita, il passaggio del comportamento è in modalità adattiva, in cui i passi di fisica a 60 Hz, 120 Hz o 240 Hz, a seconda della complessità del meccanismo fisico.

    È inoltre disponibile una modalità fissa con precisione migliorata della fisica, che costringe tutte le assemblaggi di fisica a passare a 240 Hz (quattro volte per frame).Questo comporta una significativa maggiore elaborazione di ogni frame.

  • Numero eccessivo di complessità degli oggetti simulati - Più assemblaggi 3D vengono simulati, più a lungo le operazioni di fisica richiedono ogni frame.Spesso, le esperienze avranno oggetti che vengono simulati che non hanno bisogno di essere o avranno meccanismi che hanno più vincoli e articolazioni di quanto necessario.

  • Rilevamento collisioni troppo preciso - Le parti mesh hanno una proprietà CollisionFidelity per rilevare la collisione che offre una varietà di modi con diversi livelli di impatto sulle prestazioni.La modalità di rilevamento della collisione precisa per le parti di mesh ha il costo di prestazioni più elevato e richiede più tempo per il calcolo del motore.

Mitigazione

  • Parti di ancoraggio che non richiedono simulazione - Ancorare tutte le parti che non hanno bisogno di essere guidate dalla fisica, come per i NPC statici.

  • Usa l'adattamento della fisica passo dopo passo - L'adattamento della fisica passo dopo passo regola dinamicamente il tasso di calcoli fisici per i meccanismi fisici, consentendo di eseguire gli aggiornamenti della fisica con meno frequenza in alcuni casi.

  • Riduci la complessità del meccanismo * Ove possibile, minimizza il numero di vincoli fisici o giunti in un'assemblaggio.

    • Riduci la quantità di autocollisione all'interno di un meccanismo, come applicando limiti o vincoli di non collisione ai bracci ragdoll per impedire loro di scontrarsi tra loro.
  • Riduci l'uso della precisione della fedeltà della collisione per le maglie * Per oggetti piccoli o non interattivi in cui gli utenti raramente noterebbero la differenza, usa la fedeltà della scatola.

    • Per gli oggetti di piccole-medie dimensioni, utilizza la fedeltà della scatola o della conchiglia, 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 carena, poiché la geometria di collisione è ancora memorizzata nella memoria.

    • Puoi rendere la geometria di collisione per scopi di debug nel Studio attivando fedeltà di collisione dal widget Opzioni di visualizzazione nell'angolo in alto a destra della vista 3D.

      In alternativa, puoi applicare il filtro CollisionFidelity = Precise al Explorer che mostra un conteggio di tutte le parti mesh con la precisione e la fedeltà precise e ti consente di selezionarle facilmente.

    • Per una panoramica dettagliata su come scegliere un'opzione di fedeltà alla collisione che bilancia i requisiti di precisione e prestazioni, vedi Imposta i parametri di fisica e rendering.

Scopi del MicroProfiler

ScopoComputazione associata
fisicaSteppedCalcolo della fisica generale
passo mondialePassaggi di fisica discreti compiuti ogni frame

Consumo di memoria fisica

Il movimento fisico e la rilevazione della collisione consumano memoria.Le parti mesh hanno una proprietà CollisionFidelity che determina l'approccio che viene utilizzato per valutare i confini di collisione della mesh.

Problema comune

La modalità di rilevamento della collisione predefinita e precisa consuma notevolmente più memoria rispetto agli altri due modi con forme di collisione di minore fedeltà.

Se vedi alti livelli di consumo di memoria sotto PhysicsParts , potresti dover esplorare la riduzione della fedeltà alla collisione degli oggetti nella tua esperienza.

Come attenuare

Per ridurre la memoria utilizzata per la fedeltà alle collisioni:

  • Per le parti che non hanno bisogno di collisioni, disabilita le loro collisioni impostando BasePart.CanCollide, BasePart.CanTouch e BasePart.CanQuery a false .
  • Riduci la fedeltà delle collisioni utilizzando l'impostazione CollisionFidelity.Box ha il più basso overhead di memoria e Default e Precise sono generalmente più costosi.
    • In generale, è sicuro impostare la fedeltà della collisione di qualsiasi piccola parte ancorata a Box.
    • Per le maglie molto complesse di grandi dimensioni, potresti voler costruire la tua rete di collisione personalizzata da oggetti più piccoli con fedeltà di collisione a scatola.

Humanoidi

Humanoid è una classe che fornisce una vasta gamma di funzionalità ai personaggi giocatori e non giocatori (NPC).Sebbene potente, un Humanoid viene fornito con un costo di calcolo significativo.

Problemi comuni

  • Lasciando tutti gli HumanoidStateTypes abilitati su NPC - C'è un costo di performance per lasciare attivati alcuni HumanoidStateTypes .Disabilita qualsiasi non sia necessaria per i tuoi NPC.Ad esempio, a meno che il tuo NPC non salga le scale, è sicuro disabilitare lo stato Climbing .
  • Istanziare, modificare e rigenerare i modelli con Humanoids frequentemente * Questo può essere intenso per il motore per elaborare, in particolare se questi modelli utilizzano abbigliamento a strati .Questo può essere particolarmente problematico nelle esperienze in cui gli avatar respawnano spesso.
    • Nel MicroProfiler , le lunghe etichette aggiornamentoInvalutatoFastClusters (oltre 4 ms) sono spesso un segnale che l'istantaneazione/modifica dell'avatar sta generando invalidazioni eccessive.
  • Utilizzare gli umanoidi nei casi in cui non sono richiesti - Gli NPC statici che non si muovono generalmente non hanno bisogno della classe Humanoid.
  • Riproducendo le animazioni su un gran numero di NPC dal server - Le animazioni NPC che si eseguono sul server devono essere simulate sul server e replicate al client.Questo può essere un sovraccarico non necessario.

Mitigazione

  • Riproduci le animazioni NPC sul client - Nelle esperienze con un gran numero di NPC, considera di creare il Animator sul client e di eseguire le animazioni localmente.Ciò riduce il carico sul server e la necessità di replicazione non necessaria.Consente inoltre di effettuare ulteriori ottimizzazioni (ad esempio, di giocare solo le animazioni per i NPC che sono vicini al personaggio).
  • Usa alternative performanti a Humanoids - I modelli NPC non hanno necessariamente bisogno di contenere un oggetto umanoide.
    • Per i NPC statici, usa un semplice AnimationController, perché non hanno bisogno di muoversi ma hanno solo bisogno di giocare le animazioni.
    • Per spostare i NPC, considera di implementare il tuo proprio controller di movimento e utilizzare un AnimationController per le animazioni, a seconda della complessità dei tuoi NPC.
  • Disabilita gli stati umanoidi inutilizzati - Usa Humanoid:SetStateEnabled() per abilitare solo gli stati necessari per ogni umanoide.
  • Modelli NPC della piscina con frequente respawning - Invece di distruggere completamente un NPC, invia il NPC in una piscina di NPC inattivi.In questo modo, quando è necessario respawnare un nuovo NPC, puoi semplicemente riattivare uno degli NPC dalla piscina.Questo processo è chiamato pooling, che minimizza la quantità di volte in cui i personaggi devono essere istanziati.
  • Genera solo NPC quando gli utenti sono vicini - Non generare NPC quando gli utenti non sono a portata, e eliminarli quando gli utenti lasciano la loro portata.
  • Evita di apportare modifiche alla gerarchia dell'avatar dopo che è stata istanziata - Alcune modifiche a una gerarchia dell'avatar hanno implicazioni di prestazioni significative.Sono disponibili alcune ottimizzazioni:
    • Per le animazioni procedurali personalizzate, non aggiorna le proprietà JointInstance.C0 e JointInstance.C1. Aggiorna invece la proprietà Motor6D.Transform.
    • Se devi allegare qualsiasi oggetto BasePart all'avatar, fallo al di fuori della gerarchia dell'avatar Model.

Scopi del MicroProfiler

ScopoComputazione associata
stepHumanoidControllo e fisica umanoidali
stepAnimazioneAnimazione di umanoidi e animatori
aggiornaInvalidatedFastClustersAssociato con l'istantizzazione o la modifica di un avatar

Rendimento

Una percentuale significativa del tempo che il client spende ogni frame è sulla rappresentazione della scena nell'attuale frame.Il server non esegue alcun rendering, quindi questa sezione è esclusiva per il client.

Esegui chiamate

Una chiamata di disegno è un insieme di istruzioni dall'Engine alla GPU per rendere qualcosa.Le chiamate di disegno hanno un overhead significativo.In generale, minore sono le chiamate di disegno per frame, minore è il tempo di calcolo speso per rendere un frame.

Puoi vedere quante chiamate di disegno stanno attualmente accadendo con l'elemento Render Stats > Timing in Studio.Puoi visualizzare Rendi statistiche nel client premendo ShiftF2 .

Più oggetti devono essere disegnati nella tua scena in un dato frame, più chiamate di disegno vengono eseguite sulla GPU.Tuttavia, il motore Roblox utilizza un processo chiamato istanziazione per ridurre le maglie identiche con le stesse caratteristiche di texture in una singola chiamata di disegno.Nello specifico, più mesh con la stessa MeshId sono gestite in una singola chiamata di disegno quando:

Altri problemi comuni

  • Densità di oggetti eccessiva - Se un gran numero di oggetti è concentrato con una densità elevata, allora rendere quest'area della scena richiede più chiamate di disegno.Se stai trovando il tuo tasso di fotogrammi cade quando guardi una certa parte della mappa, questo può essere un buon segnale che la densità dell'oggetto in quest'area è troppo alta

    Oggetti come adesivi, texture e particelle non si batchizzano bene e introducono ulteriori richieste di disegno.Presta maggiore attenzione a questi tipi di oggetti in una scenaIn particolare, i cambiamenti di proprietà a ParticleEmitters possono avere un impatto drammatico sulle prestazioni

  • Occasioni di istanziamento mancate - Spesso, una scena includerà la stessa mesh duplicata più volte, ma ogni copia della mesh ha ID di risorsa mesh o texture diversi.Questo impedisce l'istanziazione e può portare a chiamate di disegno non necessarie.

    Una causa comune di questo problema è quando un'intera scena viene importata in una volta, anziché importare singole risorse in Roblox e poi duplicarle dopo l'importazione per assemblare la scena.

  • Complessità dell'oggetto eccessiva - Anche se non è importante quanto il numero di chiamate di disegno, il numero di triangoli in una scena influisce sul tempo che un frame impiega a rendersi.Le scene con un numero molto grande di mesh molto complesse sono un problema comune, così come le scene con la proprietà impostata su troppi mesh.

  • Casting ombra eccessivo - La gestione delle ombre è un processo costoso e le mappe che contengono un alto numero e una densità di oggetti luminosi che proiettano ombre (o un alto numero e una densità di piccole parti influenzate dalle ombre) è probabile che abbiano problemi di prestazioni.

  • Eccesso di trasparenza elevata - Posizionare oggetti con trasparenza parziale vicino l'uno all'altro costringe il motore a rendere i pixel sovrapposti più volte, il che può influire sulle prestazioni.Per ulteriori informazioni sull'identificazione e la risoluzione di questo problema, vedi Elimina trasparenze stratificate.

Mitigazione

  • Istanziare mesh identici e ridurre la quantità di mesh unici - Se garantisci che tutti i mesh identici abbiano gli stessi ID risorsa di base, l'engine può riconoscerli e renderli in una singola chiamata di disegno.Assicurati di caricare ciascuna mesh in una mappa solo una volta e quindi di duplicarle in Studio per riutilizzo piuttosto che importare grandi mappe in blocco, che potrebbero causare ID contenuti identici separati e essere riconosciute come risorse uniche dall'engine.I pacchetti sono un meccanismo utile per la riutilizzazione degli oggetti.
  • Selezione - La selezione descrive il processo di eliminazione delle chiamate di disegno per gli oggetti che non fanno parte del quadro finale renduto.Per impostazione predefinita, il motore ignora le chiamate di disegno per oggetti al di fuori del campo visivo della fotocamera (raccolta frustum), ma non ignora le chiamate di disegno per oggetti occlusi dalla vista da altri oggetti (raccolta occlusione).Se la tua scena ha un gran numero di chiamate di disegno, considera di implementare la tua propria selezione aggiuntiva in tempo reale dinamicamente per ogni frame, come l'applicazione delle seguenti strategie comuni:
    • Nascondi MeshPart e BasePart che sono molto lontani dalla fotocamera o dalla impostazione.
    • Per gli ambienti interni, implementa un sistema di stanze o portali che nasconda oggetti non attualmente occupati da nessun utente.
  • Riduzione della fedeltà al rendering - Imposta la fedeltà al rendering su Automatico o Prestazioni .Ciò consente alle maglie di tornare alle alternative meno complesse, che possono ridurre il numero di poligoni che devono essere disegnati.
  • Disattivare il lancio delle ombre su parti e oggetti luminosi appropriati - La complessità delle ombre in una scena può essere ridotta disabilitando selettivamente le proprietà di lancio delle ombre su parti e oggetti luminosi.Questo può essere fatto al momento dell'edizione o dinamicamente durante l'esecuzione.Alcuni esempi sono:
    • Usa la proprietà BasePart.CastShadow per disabilitare il lancio delle ombre su piccole parti in cui è improbabile che le ombre siano visibili.Questo può essere particolarmente efficace quando applicato solo alle parti che sono lontane dalla fotocamera dell'utente

    • Disabilita le ombre sugli oggetti in movimento quando possibile.

    • Disabilita Light.Shadows su istanze leggere in cui l'oggetto non ha bisogno di lanciare ombre.

    • Limita il raggio e l'angolo delle istanze di luce.

    • Usa meno istanze leggere.

Scopi del MicroProfiler

ScopoComputazione associata
Preparare ed eseguireRendimento generale
Eseguire/Scena/ computeLightingPerformAggiornamenti della griglia di luce e delle ombre
LightGridCPUAggiornamenti della griglia di luce Voxel
Sistema Mappa OmbraMappatura delle ombre
Esegui/Scena/AggiornaVistaPreparazione per il rendering e gli aggiornamenti delle particelle
Eseguire/Scena/RenderViewRendering e post-elaborazione

Reti e replicazione

La rete e la replicazione descrivono il processo attraverso cui i dati vengono inviati tra il server e i client connessi.Le informazioni vengono inviate 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 o oggetti o l'invocazione di essi molto frequentemente può portare a una grande quantità di tempo di CPU speso nel processare i pacchetti in arrivo ogni frame.Gli errori comuni comprendono:

    • Replicare i dati ogni frame che non deve essere replicato.
    • Replicazione dei dati sull'input dell'utente senza alcun meccanismo per limitarlo.
    • Invio di più dati di quanto richiesto.Ad esempio, inviare l'intero inventario del giocatore quando acquista un oggetto piuttosto che solo i dettagli dell'oggetto acquistato.
  • Creazione o rimozione di alberi di istanza complessi - Quando viene apportata una modifica al modello di dati sul server, viene replicata ai client connessi.Questo significa che la creazione e la distruzione di grandi gerarchie di istanza come le mappe durante l'esecuzione può essere molto intensiva in termini di rete.

    Un colpevole comune qui è i dati di animazione complessi salvati dai plugin dell'editor di animazione in righe.Se questi non vengono rimossi prima della pubblicazione del gioco e il modello animato viene clonato regolarmente, una grande quantità di dati verrà replicata inutilmente.

  • Servizio TweenSide del server - Se TweenService viene utilizzato per tweenare un oggetto lato server, la proprietà tweenata viene replicata ad ogni client ogni frame.Non solo questo risulta nel tween essere nervoso poiché la latenza dei client aumenta, ma causa un sacco di traffico di rete inutile.

Mitigazione

Puoi impiegare le seguenti tattiche per ridurre la duplicazione inutile:

  • Evita di inviare grandi quantità di dati contemporaneamente attraverso eventi remoti .Invece, invia solo i dati necessari a una frequenza più bassa.Ad esempio, per lo stato di un personaggio, replicatelo quando cambia piuttosto che ad ogni frame.
  • Raccogli alberi di istanze complessi come le mappe e caricali a pezzi per distribuire il lavoro che replica questi su più frame.
  • Pulisci i metadati dell'animazione , in particolare la directory di animazione dei rig, dopo l'importazione.
  • Limitare la replicazione delle istanze non necessarie , in particolare nei casi in cui il server non ha bisogno di avere conoscenza delle istanze che vengono create.Questo comprende:
    • Effetti visivi come un'esplosione o una magica esplosione di incantesimi.Il server deve solo conoscere la posizione per determinare il risultato, mentre i client possono creare visualizzazioni localmente.
    • Modelli di visualizzazione dell'elemento in prima persona.
    • Oggetti di transizione sul client piuttosto che sul server.

Scopi del MicroProfiler

ScopoComputazione associata
Pacchetti di processoElaborazione dei pacchetti di rete in arrivo, come le invocazioni di eventi e le modifiche delle proprietà
Assegnare larghezza di banda e inviare mittentiEventi in uscita rilevanti sui server

Uso della memoria delle risorse

Il meccanismo di impatto più elevato disponibile per i creatori per migliorare l'utilizzo della memoria del client è abilitare Streaming di istanza.

Streaming dell'istanza

Lo streaming delle istanze carica selettivamente parti del modello di dati che non sono richieste, il che può portare a un tempo di caricamento considerevolmente ridotto e aumentare la capacità del client di prevenire gli errori quando viene sotto pressione di memoria.

Se stai riscontrando problemi di memoria e hai disabilitato lo streaming delle istanze, considera di aggiornare la tua esperienza per supportarla, in particolare se il tuo mondo 3D è grande.Lo streaming delle istanze è basato sulla distanza nello spazio 3D, quindi i mondi più grandi ne traggono naturalmente più beneficio.

Se la trasmissione delle istanze è abilitata, puoi aumentare l'aggressività. Ad esempio, considera:

  • Riduzione dell'uso della persistente StreamingIntegrity .
  • Riduzione del raggio di streaming .

Per ulteriori informazioni sulle opzioni di streaming e sui loro vantaggi, vedi Proprietà di streaming.

Altri problemi comuni

  • Duplicazione delle risorse - Un errore comune è caricare più volte la stessa risorsa con ID risorse diversi.Questo può portare al caricamento dello stesso contenuto in memoria più volte.
  • Volume di risorse eccessivo - Anche quando le risorse non sono identiche, ci sono casi in cui vengono perse opportunità di riutilizzare la stessa risorsa e risparmiare memoria.
  • File audio - I file audio possono essere un contributore sorprendente all'utilizzo della memoria, in particolare se li carichi tutti nel client contemporaneamente anziché caricare solo quelli di cui hai bisogno per una parte dell'esperienza.Per le strategie, vedi Tempi di caricamento .
  • Texture ad alta risoluzione - Il consumo di memoria grafica per una texture non è correlato alla dimensione della texture sul disco, ma piuttosto al numero di pixel nella texture.
    • Ad esempio, una texture a 1024x1024 pixel consuma quattro volte la memoria grafica di una texture 512x512.
    • Le immagini caricate su Roblox vengono trasmesse in un formato fisso, quindi non c'è alcun vantaggio di memoria nell'aggiungere immagini in un modello di colore associato a meno byte per pixel.Allo stesso modo, la compressione delle immagini prima del caricamento o la rimozione del canale alfa dalle immagini che non ne hanno bisogno può ridurre la dimensione delle immagini sul disco, ma non migliora o migliora solo minimamente l'utilizzo della memoria.Anche se il motore riduce automaticamente la risoluzione della texture su alcuni dispositivi, l'estensione della riduzione dipende dalle caratteristiche del dispositivo e la risoluzione della texture eccessiva può ancora causare problemi.
    • Puoi identificare il consumo di memoria grafica per una texture data espandendo la categoria Texture grafica nella Console di sviluppatore .

Mitigazione

  • Carica solo le risorse una volta - Riutilizza lo stesso ID risorsa su oggetti diversi e assicurati che le stesse risorse, in particolare le maglie e le immagini, non vengano caricate separatamente più volte
  • Trova e correggi le risorse duplicate - Cerca parti e texture di mesh identiche che vengono caricate più volte con ID diversi.
    • Anche se non esiste un'API per rilevare la somiglianza delle risorse in modo automatico, puoi raccogliere tutti gli ID delle risorse dell'immagine nel tuo posto (manualmente o con uno script), scaricarli e confrontarli utilizzando strumenti di confronto esterni.
    • Per le parti a maglia, la migliore strategia è quella di prendere ID di maglia unici e organizzarli per dimensione per identificare manualmente i duplicati.
    • Invece di utilizzare texture separate per colori diversi, carica una texture singola e usa la proprietà SurfaceAppearance.Color per applicare vari toni ad essa.
  • Importare risorse in mappa separatamente - Invece di importare un'intera mappa in una volta, importa e ricostruisci le risorse nella mappa individualmente e ricostruiscile.L'importatore 3D non fa alcuna de-duplicazione delle maglie, quindi se importi una mappa grande con un sacco di piastrelle separate, ciascuna di quelle piastrelle verrebbe importata come risorsa separata (anche se sono duplicazioni).Questo può portare a problemi di prestazioni e memoria lungo la linea, poiché ogni mesh viene trattata individualmente e occupa memoria e richiama chiamate.
  • Limita i pixel delle immagini a non più della quantità necessaria.A meno che un'immagine occupi una grande quantità di spazio fisico sullo schermo, di solito ha bisogno di al massimo 512x512 pixel.La maggior parte delle immagini minori dovrebbe essere più piccola di 256x256 pixel.
  • Usa le schede di ritaglio per garantire il massimo riutilizzo della texture nelle mappe 3D.Per passaggi e esempi su come creare fogli di taglio, vedi Creazione di fogli di taglio.

Tempi di caricamento

Molte esperienze implementano schermi di caricamento personalizzati e utilizzano il metodo ContentProvider:PreloadAsync() per richiedere risorse in modo che le immagini, i suoni e le maglie vengano scaricate in background.

Il vantaggio di questo approccio è che ti consente di assicurarti che le parti importanti della tua esperienza siano completamente caricate senza pop-in.Tuttavia, un errore comune è quello di utilizzare in modo eccessivo questo metodo per precaricare più risorse di quanto effettivamente richiesto.

Un esempio di cattiva pratica è il caricamento dell'intero interoWorkspace.Mentre questo potrebbe impedire l'apparizione della texture, aumenta notevolmente il tempo di caricamento.

Invece, utilizza solo ContentProvider:PreloadAsync() nelle situazioni necessarie, che includono:

  • Immagini nella schermata di caricamento.
  • Immagini importanti nel menu della tua esperienza, come sfondi di pulsanti e icone.
  • Risorse importanti nell'area di partenza o di spawn.

Se devi caricare un gran numero di risorse, ti consigliamo di fornire un pulsante Salta caricamento .