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 performance comuni e le migliori pratiche per mitigarli.

Calcolo degli script

Le operazioni costose nel codice Luau richiedono più tempo per essere elaborate e possono quindi influenzare il tasso di frame.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 della tabella - 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 coinvolgono 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 comporta 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 di 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 distribuire 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 nativa generazione di codice, una semplice bandiera che compila uno script in codice macchina piuttosto che bytecode.

Scopi del MicroProfiler

AmbitoCalcolo associato
RunService.PreRenderCodice che esegue sull'evento PreRender
EseguiService.PreSimulationCodice che esegue sull'evento Stepped
EseguiService.PostSimulationCodice che esegue sull'evento Heartbeat
Heartbeat di RunServiceCodice che esegue 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 è più in uso.Le perdite sono specificamente pervasive 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 necessita di ulteriori indagini:

  • LuaHeap - Un alto o crescente consumo 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 in modo coerente.
  • PlaceScriptMemory - Fornisce uno script per la rottura degli script dell'utilizzo della memoria.

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 supporre 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 importanti 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 dell'utente quando si uniscono.Ad esempio, il seguente esempio di codice crea una tabella che aggiunge informazioni sull'utente ogni volta che un utente si unisce:

    Esempio

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

    Se non rimuovi queste voci quando non sono più necessarie, la tabella continua a crescere in dimensioni e consuma più memoria man mano che 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 code 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 esce, 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 fisico

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

Problemi comuni

  • Frequenza del passaggio della 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 forza 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 calcoli fisici prendono 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 cui hanno bisogno.

  • Rilevamento della collisione troppo preciso - Le parti di 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 performance 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 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 restrizioni fisiche 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, usa 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 in 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=PreciseConvexDecomposition ai 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 approfondita 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

AmbitoCalcolo associato
fisicaSteppedCalcolo fisico complessivo
passo mondialePassi di fisica discreti compiuti ogni frame

Utilizzo della memoria fisica

Il movimento fisico e la rilevazione delle collisioni consumano memoria.Le parti mesh hanno una proprietà CollisionFidelity che determina l'approccio 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 il ridurre la fedeltà alla collisione degli oggetti nella tua esperienza.

Come mitigare

Per ridurre la memoria utilizzata per la fedeltà alla collisione:

  • 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.
    • È generalmente 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 mesh di collisione da oggetti più piccoli con fedeltà di collisione a scatola.

Umanoidi

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 necessario per i tuoi NPC.Ad esempio, a meno che il tuo NPC non salirà le scale, è sicuro disabilitare lo stato Climbing .
  • Istanziare, modificare e respawnare 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 respawn 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 - NPC statici che non si muovono generalmente non hanno bisogno della classe Humanoid.
  • Giocare 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 overhead non necessario.

Mitigazione

  • Gioca alle 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.Questo riduce il carico sul server e la necessità di replicazione non necessaria.Inoltre rende possibili ulteriori ottimizzazioni (ad esempio, giocare solo animazioni per 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 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 dei NPC dalla piscina.Questo processo è chiamato pooling, che minimizza il numero 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 sulle prestazioni significative.Alcune ottimizzazioni sono disponibili:
    • Per le animazioni procedurali personalizzate, non aggiorna le proprietà JointInstance.C0 e JointInstance.C1. Invece, aggiorna la proprietà Motor6D.Transform.
    • Se devi allegare qualsiasi oggetto BasePart all'avatar, fallo al di fuori della gerarchia dell'avatar Model .

Scopi del MicroProfiler

AmbitoCalcolo associato
stepHumanoidControllo e fisica umanoidi
stepAnimazioneAnimazione umanoide e animatore
aggiornaInvalidatedFastClustersAssociato con l'instaurazione o la modifica di un avatar

Rendimento

Una porzione importante del tempo che il client spende ogni frame è sulla rappresentazione della scena nell'attuale frame.Il server non fa 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.Generalmente, più poche chiamate di disegno per frame, meno tempo di calcolo viene speso per rendere un frame.

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

Più oggetti devono essere disegnati nella tua scena in un dato frame, più chiamate di disegno vengono fatte alla GPU.Tuttavia, il motore Roblox utilizza un processo chiamato istanza per ridurre le maglie identiche con le stesse caratteristiche di texture in una singola chiamata di disegno.In particolare, 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, poi rendere quest'area della scena richiede più chiamate di disegno.Se stai trovando il tuo frame rate diminuisce 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 batchano bene e introducono ulteriori richieste di disegno.Presta attenzione extra a questi tipi di oggetti in una scena.In particolare, i cambiamenti di proprietà a ParticleEmitters possono avere un impatto drammatico sulle prestazioni.

  • Opportunità 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 viene importata un'intera scena in una volta, piuttosto che importare singole risorse in Roblox e poi duplicarle dopo l'importazione per assemblare la scena.

    Persino uno script semplice come questo può aiutarti a identificare parti mesh con lo stesso nome che utilizzano ID mesh diversi:


    local Workspace = game:GetService("Workspace")
    for _, descendant in Workspace:GetDescendants() do
    if descendant:IsA("MeshPart") then
    print(descendant.Name .. ", " .. descendant.MeshId)
    end
    end

    L'output (con Linee Stack abilitate) potrebbe sembrare qualcosa del genere.Le linee ripetute indicano il riutilizzo della stessa mesh, che è buono.Le linee uniche non sono necessariamente cattive, ma a seconda del tuo schema di denominazione, potrebbero indicare mesh duplicati nella tua esperienza:


    LargeRock, rbxassetid://106420009602747 (x144) -- good
    LargeRock, rbxassetid://120109824668127
    LargeRock, rbxassetid://134460273008628
    LargeRock, rbxassetid://139288987285823
    LargeRock, rbxassetid://71302144984955
    LargeRock, rbxassetid://90621205713698
    LargeRock, rbxassetid://113160939160788
    LargeRock, rbxassetid://135944592365226 -- all possible duplicates
  • 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 necessario per rendere un frame.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 meshi.

  • Casting ombra eccessivo - La gestione delle ombre è un processo costoso e le mappe che contengono un alto numero e una densità di oggetti di luce 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 assicuri che tutti i mesh identici abbiano gli stessi ID di risorsa di base, l'engine può riconoscerli e renderli in una singola chiamata di disegno.Assicurati di caricare solo ogni mesh in una mappa una volta e poi 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 lontani dalla fotocamera o dalla impostazione.
    • Per gli ambienti interni, implementa un sistema di stanza o portale che nasconde oggetti non attualmente occupati da nessun utente.
  • Riduzione della fedeltà al rendering - Imposta la fedeltà al rendering su Automatico o Prestazioni .Questo 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 dove l'oggetto non ha bisogno di lanciare ombre.

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

    • Usa meno istanze di luce.

    • Considera di disabilitare le luci che sono al di fuori di una gamma specifica o su base stanza per stanza per gli ambienti interni.

Scopi del MicroProfiler

AmbitoCalcolo associato
Preparare e eseguireRendimento complessivo
Esegui/Scena/ computeLightingPerformAggiornamenti della griglia di luce e delle ombre
LightGridCPUAggiornamenti della griglia di luce Voxel
Sistema Mappa OmbraMappatura dell'ombra
Esegui/Scena/AggiornaVisualePreparazione per il rendering e gli aggiornamenti delle particelle
Esegui/Scena/RenderViewRendering e post-elaborazione

Networking 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 maggiori quantità 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 molto frequentemente può portare a una grande quantità di tempo di CPU speso nel processare i pacchetti in arrivo ogni frame.Gli errori comuni includono:

    • Replicare i dati ogni frame che non deve essere replicato.
    • Replicare i dati sull'input dell'utente senza alcun meccanismo per limitarlo.
    • Invio di più dati di quanto richiesto.Ad esempio, l'invio dell'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 apportato un cambiamento al modello di dati sul server, viene replicato 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 nelle righe.Se questi non vengono rimossi prima che il gioco venga pubblicato e il modello animato venga 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 a 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 non necessario.

Mitigazione

Puoi impiegare le seguenti tattiche per ridurre la duplicazione non necessaria:

  • Evita di inviare grandi quantità di dati in una volta 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 ogni frame.
  • Chunk up complex instance trees come le mappe e carica loro in pezzi per distribuire il lavoro replicando questi su più frame.
  • Pulisci i metadati dell'animazione , in particolare la directory di animazione dei rig, dopo l'importazione.
  • Riduci 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 include:
    • Effetti visivi come un'esplosione o un'ondata di magia.Il server deve solo conoscere la posizione per determinare l'esito, 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

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

Utilizzo della memoria delle risorse

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

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 maggior beneficio.

Se lo streaming delle istanze è abilitato, 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 la stessa risorsa più volte con risultati diversi ID risorse.Questo può portare allo stesso contenuto che viene caricato 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 contemporaneamente nel client piuttosto che 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 a 512x512.
    • Le immagini caricate su Roblox vengono trascescritte in un formato fisso, quindi non c'è alcun vantaggio di memoria nell'upload di immagini in un modello di colore associato a meno bytes per pixel.Allo stesso modo, la compressione delle immagini prima di caricare o rimuovere il canale alfa dalle immagini che non ne hanno bisogno può ridurre la dimensione dell'immagine 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 Developer .

Mitigazione

  • Carica solo le risorse una volta - Riutilizza lo stesso ID risorsa su oggetti 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 di mesh e texture 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.
  • Importa 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 duplicati).Questo può portare a problemi di performance e memoria lungo la linea, poiché ogni mesh viene trattata individualmente e occupa memoria e richiede chiamate di disegno.

  • Limita i pixel delle immagini a non più della quantità necessaria.A meno che un'immagine stia occupando 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 taglio per garantire il massimo riutilizzo della texture nelle mappe 3D.Per passaggi e esempi su come creare fogli di taglio, vedi Crea fogli di taglio.

    Potresti anche considerare l'uso di fogli di sprite per caricare molte immagini UI più piccole come un'unica immagine.Puoi quindi usare ImageLabel.ImageRectOffset e ImageLabel.ImageRectSize per visualizzare porzioni della foglia.

Tempi di caricamento

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

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

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

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

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

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