Diese Seite beschreibt gängige Leistungsprobleme und Best Practices, um sie zu beheben.
Skriptberechnung
Teurer Operationen in Lua-Code dauern länger, um zu verarbeiten, und können daher die bewertenbeeinflussen. Es sei denn, es wird parallel ausgeführt, läuft Lua-Code synchron und blockiert den HauptThread, bis es eine Funktion findet, die den Thread erzeugt.
Gewöhnliche Probleme
Intensive Operationen auf Tabellenstrukturen - Komplexe Operationen wie Serialisierung, Deserialisierung und Tiefklonung verursachen eine hohe Leistungskosten, besonders auf großen Tabellenstrukturen. Dies gilt insbesondere, wenn diese Operationen recursiv sind oder über sehr große Datenstrukturen wiederholen.
Hohe Frequenz-ereignisse - Kopplung teure Operationen mit Frame-based-ereignissen von RunService ohne die Frequenzmittel, mit denen diese Operationen in jedem Frame wiederholt werden, was oft zu einer unnötigen Verlängerung der Berechnungszeit führt. Diese Ereignisse enthalten:
Schadensbehandlung
- Rufen Sie Code auf RunService -Ereignissen sparsam, begrenzt die Verwendung auf Fälle, in denen eine hohe Frequenz-Invocation notwendig ist (z. B. Aktualisierung der Kamera). Sie können die meisten anderen Code in anderen Ereignissen oder seltener in einer Loop-Anwendung ausführen.
- Teilen Sie große oder teure Aufgaben mit task.wait(), um die Arbeit auf mehrere Frames zu verteilen.
- Identifizieren und optimieren Sie unnötig teure Operationen und verwenden Sie Multithreading für kalkulatorisch teure Aufgaben, die keinen Zugriff auf das Modellbenötigen.
- Bestimmte serverseitige Skripte können von Native Code Generation profitieren, einer einfachen Flagge, die ein Skript in Maschinencode und nicht in Bytecode kompiliert.
MicroProfiler-Skope
Zielfernrohr | Verknüpfte Berechnung |
RunService.Vorlagen | Code wird beim Ausführen auf dem PreRender-Ereignis ausgeführt |
RunService.PreSimulation | Code wird beim Stepped-Ereignis ausgeführt |
RunService.PostSimulation ausführen | Code wird beim Heartbeat-Ereignis ausgeführt |
RunService.Heartbeat | Code wird beim Heartbeat-Ereignis ausgeführt |
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 associates MicroProfiler-Tags that can provide useful signal.
Skript-Speicherverbrauch
Memory leaks können auftritt, wenn du Skripte schreibst, die Speicher verbrauchen, den der Müll-Sammler nicht richtig loslassen kann, wenn er nicht mehr in Verwendung ist. Leaks sind auf dem Server besonders verbreitet, da sie kontinuierlich online für viele Tage sein können, während eine Client-Sitzung viel kürzer ist.
Die folgenden Speicherwerte in der Developer Console können ein Problem anzeigen, das weitere Untersuchungen erfordert:
- LuaHeap - Hohe oder wachsende Verbrauchs- oder Erinnerungslecks zeigen auf ein mögliches Problem hin.
- InstanzCount - Konstante Zahl der Instanzen deutet darauf hin, dass einige Instanzen in deinem Code keine Müll gesammelt werden.
- PlatzScriptMemory - gibt ein Skript durch Skript-Aufruf von Speicherverbrauch.
Gewöhnliche Probleme
Verbindungen, die verbunden sind - Der Motor sammelt niemals Müll-Ereignisse, die mit einer Instanz verbunden sind, und alle Werte, die in dem verbundenen Callbackverwendet werden, werden nicht vom Speicher-Garbage-Sammler übersehen, auch wenn die Ereignisse und der Code innerhalb der verbundenen Instanzen, verbundenen Funktionen und in den verwendeten Werte übergeordnet sind.
Obwohl Ereignisse getrennt sind, wenn die Instanz, zu der sie gehören, zerstört wird, ist ein häufiger Fehler, zu glauben, dass dies auf Player -Objekten angewendet gilt. Nachdem ein Benutzer eine Er
Tabelleaux - Das Einfügen von Objekten in Tabelle, aber nicht das Entfernen, wenn sie nicht mehr benötigt werden, verursacht unnötigen Speicherverbrauch, insbesondere für Tabelle, die Benutzerdaten verfolgen, wenn sie beitreten. Zum Beispiel erstellt der folgende Codebeispiel eine Tabelle, die Benutzerdaten jedes Mal einfügt, wenn ein Benutzer beitritt:
Beispiellocal playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- einige infosend)Wenn Sie diese Einreichungen nicht entfernen, wenn sie nicht mehr benötigt werden, wird die Tabelle weiterhin in der Größe wachsen und verbraucht mehr Speicher, da mehr Benutzer der Sitzung beitreten. Jeder Code, der über diese Tabelle wiederholt wird, wird auch komplexer, da die Tabelle in der Größe wächst.
Schadensbehandlung
Um alle verwendeten Werte für die Verhinderung von Speicherleaks sauber zu machen:
Verbinden Sie alle Verbindungen wieder ab - Gehen Sie durch Ihre Code-Basis, stellen Sie sicher, dass jede Verbindung über einen der folgenden Wege sauber ist:
- Verbindung manuell mit der Funktion Disconnect() wieder abbrechen.
- Zerstören der Instanz, zu der das Ereignis gehört, mit der Destroy() Funktion.
- Zerstören des Skript-Objekts, zu dem die Verbindung zurückverfolgt.
Entfernen Sie Spielerobjekte und -merkmale nach dem Verlassen - Umsetzen Sie den Code, um sicherzustellen, dass keine Verbindungen bestehen bleiben, nachdem ein Benutzer verlässt, wie in dem folgenden Beispiel:
BeispielPlayers.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)
Physikalische Berechnungen
Übermäßige Physiksimulation kann eine Schlüsselursache für die Verlängerung der Berechnungszeit pro Frame auf dem Server und dem Client sein.
Gewöhnliche Probleme
Excessive Physik-Zeit-Step-Frequenz - Standardmäßig ist die Steigung des Verhaltens in adaptive Modus, bei der die Physik-Schritte entweder 60 Hz, 120 Hz oder 240 Hz sind, abhängig von der Komplexität des Physikmechanismus.
Ein fester Modus mit verbessertem physikalischen Accuracy ist auch verfügbar, der alle Physik-Assemblies dazu zwingt, 240 Hz (viermal pro Frame) zu步驟。 Dies ergibt eine deutlich mehr Kalkulation pro Frame.
Überschüssige Anzahl der Komplexität von simulierten Objekten - Je mehr 3D-Assemblies simuliert werden, desto länger dauern Physiksimulationen pro Frame. Oft haben Erlebnisse Objekte, die keinen Mechanismus benötigen oder haben Mechanismen, die mehr Einschränkungen und Verbindungen haben als sie nicht benötigen.
Übermäßig präzise Kollisionserkennung - Mesh-Teile haben eine Class.MeshPart.CollisionFidelity|CollisionFidelity -Eigenschaft, um Kollisionen zu erkennen, die eine Vielzahl von Modi mit verschiedenen Leistungsniveaus bietet. Präzise Kollisionsmodus für Mesh-Teile hat den höchsten Leistungsaufwand und dauert länger, um den Engine zu berechnen.
Schadensbehandlung
Verankere Teile, die keine Simulation erfordern - Verankere alle Teile, die nicht von der Physik getrieben werden müssen, wie für statische NPCs.
Verwende adaptive Physik-Schritte - Adoptive Physik-Schritte dynamisch anpassen die Rate der Physik-Berechnungen für Physikmechanismen, so dass Physik-Updates in einigen Fällen seltener gemacht werden können.
Reduziere die Mechanism-Komplexität * Wo möglich, minimieren Sie die Anzahl von Physik-Einschränkungen oder Joints in einer Montagemaschine.
- Reduzieren Sie die Menge der Selbstkollision innerhalb eines Mechanismus, z. B. indem Sie Einschränkungen oder Kollisionsbeschränkungen anwenden, um die Ragdoll-Gliedmaßen zu verhindern, dass sie miteinander kollidieren.
Reduzieren Sie die Verwendung von präziser Kollisionsgenauigkeit für Meshes * Für kleine oder nicht interagierbare Objekte, bei denen Benutzer die Differenz selten bemerken, verwenden Sie Box-Fidelität.
Für kleine bis mittlere Objekte verwenden Sie Box- oder Hull-Fidelitäten, abhängig von der Form.
Für große und sehr komplizierte Objekte erstellen Sie benutzerdefinierte Kollisionen mit unsichtbaren Teilen, wenn möglich.
Für Objekte, die keine Kollisionen erfordern, deaktivieren Sie Kollisionen und verwenden Sie Box- oder Hull-Fidelität, da die Kollisionsgeometrie immer noch in der Speicher gespeichert ist.
Du kannst Kollisionen für Debug-Zwecke in Studio rendern, indem du Kollisionfidelität von den Ansichtsoptionen-Werkzeug in der oberen rechten Ecke des 3D-Ansichtsfensters umschaltest.
Alternativ kannst du den CollisionFidelity = Precise-Filter auf das Explorer anwenden, das eine Anzahl aller Meshes mit der präzisen Fidelität anzeigt und es dir ermöglicht, sie leicht auszuwählen.
Für eine umfassende Anleitung, wie man eine Kollisionsfidelitätsoption auswählt, die deine Präzisions- und Leistungsanforderungen ausbalanciert, siehe Setzen Sie Physics und Rendering Parameter.
MicroProfiler-Skope
Zielfernrohr | Verknüpfte Berechnung |
physicsStepped | Allgemeine Physik berechnen |
Welt | Diskrete Physikschritte für jeden Frame |
Kern-Physik-Verwendung
Die Physik-Bewegungs- und Kollisionserkennung verbraucht Speicher. Mesh-Teile haben eine CollisionFidelity -Eigenschaft, die den Ansatz definiert, der verwendet wird, um die Kollisionsgrenzen des Meshes zu bewerten.
Gemeines Problem
Die Standard- und präzisen Kollisionsmodi verbrauchen deutlich mehr Speicher als die beiden anderen Modi mit niedrigerer Kollisionsform.
Wenn Sie hohe Levels of memory consumption unter PhysicsParts sehen, müssen Sie möglicherweise die Zusammenfassungsfähigkeit der Kollision von Objekten in Ihrem Erlebnis erkunden.
Wie man es abmildert
Um die für die Kollisionsfähigkeit verwendete Speichermenge zu reduzieren:
- Für Teile, die keine Kollisionen benötigen, deaktivieren Sie ihre Kollisionen, indem Sie BasePart.CanCollide, BasePart.CanTouch und BasePart.CanQuery auf 2> false2> einstellen.
- Reduzieren Sie die Fidelität von Kollisionen mit der CollisionFidelity Einstellung. Box hat die niedrigste Memoiren Overhead und Default und 1> Enum.CollisionFidelity.
- Es ist in der Regel sicher, die Kollisionsfähigkeit von jedem kleinen verankerten Teil auf Box festzulegen.
- Für sehr komplexe große Meshes möchten Sie vielleicht Ihr eigenes Kollisionsnetz aus kleineren Objekten mit Kollisionsfähigkeit mit Box erzeugen.
Menschliche Formen
Humanoid ist eine Klasse, die eine Reihe von Funktionen für Spieler und Nicht-Spieler (NPCs) bietet. Obwohl es mächtig ist, bietet ein Humanoid einen erheblichen Berechnungskosten.
Gewöhnliche Probleme
- Alle HumanoidStateTypes auf NPCs deaktivieren - Es gibt eine Leistungskosten, wenn bestimmte HumanoidStateTypes aktiviert werden. Deaktivieren Sie alle, die nicht für Ihre NPCs notwendig sind. Zum Beispiel, wenn Ihr NPC nicht auf Steige klettern wird, ist es sicher, den Zustand Climbing zu deaktivieren.
- Modelle mit Humanoiden häufig instantiieren, modifizieren und respawnen * Dies kann für den Engine intensiv sein, insbesondere wenn diese Modelle mehrere Schichten Kleidung verwenden . Dies kann auch in Erlebnissen problematisch sein, in denen Avatare oft respawnen.
- In dem MicroProfiler , langen updateInvalidatedFastClusters Tags (über 4 ms) sind oft ein Signal, dass die Avatar-Instanzierung/Modifikation übermäßige Unverbindlichkeiten auslöst.
- Verwendung von Humanoids in Fällen, in denen sie nicht benötigt werden - Stellungskunden, die generell nicht benötigt werden, haben keinen Bedarf an der Humanoid -Klasse.
- Animationen auf einer großen Anzahl von NPCs vom Server spielen - Animationen, die auf dem Server ausgeführt werden, müssen auf dem Server simuliert und auf den Client repliziert werden. Dies kann überflüssige Überlastung sein.
Schadensbehandlung
- Spielen Sie NPC-Animationen auf dem Client - In Erfahrungen mit einer großen Anzahl von NPCs sollten Sie die Animator auf dem Client erstellen und die Animationen lokal ausführen. Dies reduziert die Last auf dem Server und die Notwendigkeit für eine unnötige Replikation. Es ermöglicht auch zusätzliche Optimierungen (z. B. nur die Animationen für NPCs zu spielen, die der Charakter in der Nähe sind).
- Verwenden Sie leistungsfreundliche Alternativen für Humanoiden - NPC-Modelle müssen nicht unbedingt ein Humanoid-Objekt enthalten.
- Für statische NPCs verwenden Sie ein einfaches AnimationController, da sie nicht umhergelaufen werden müssen, aber nur Animationen spielen müssen.
- Für den Bewegung von NPCs sollten Sie Ihren eigenen Bewegungs-Controller implementieren und einen AnimationController für Animationen verwenden, abhängig von der Komplexität Ihrer NPCs.
- Nicht verwendete humanoiden Zustände deaktivieren - Verwenden Sie Humanoid:SetStateEnabled() , um nur für jeden Humanoiden notwendige Zustände zu aktivieren.
- Pool-NPC-Modelle mit häufigem Respawning-Pool - Statt einen NPC vollständig zu zerstören, senden Sie den NPC in einen Pool von inaktiven NPCs. Dieser Prozess wird Pooling genannt, der die Anzahl der Zeiten minimiert, die ein NPC benötigt, um wiederzuspawnen.
- NSCs nur spawnen, wenn Benutzer in der Nähe sind - Spawnen Sie keine NSCs, wenn Benutzer nicht in Reichweite sind, und filtern Sie sie, wenn Benutzer Ihre Reichweite verlassen.
- Vermeiden Sie Änderungen an der Avatar-Hierarchie, nachdem sie eingerichtet ist - Einige Änderungen an einer Avatar-Hierarchie haben signifikante Leistungsimplikationen. Einige Optimierungen sind verfügbar:
- Für benutzerdefinierte prozedurale Animationen, aktualisieren Sie nicht die Eigenschaften JointInstance.C0 und JointInstance.C1. Stattdessen aktualisieren Sie die Eigenschaft Motor6D.Transform.
- Wenn Sie irgendwelche BasePart Objekte an den Avatar anhängen möchten, tun Sie dies außerhalb der Hierarchie des Avatars Model .
MicroProfiler-Skope
Zielfernrohr | Verknüpfte Berechnung |
stepHumanoid | Menschliche Steuerung und Physik |
AnimationSchritt | Menschliche und Animationen |
updateUnverifizierte Schnell-Cluster | Mit der Instantiation oder Modifizierung eines Avatars verbunden |
Rendern
Ein großer Teil der Zeit, den der Client für jeden Frame ausgibt, ist auf die Darstellung der Szene im aktuellen Frame. Der Server erledigt keine Darstellung, so ist dieses Abschnitt nur für den Client exklusiv.
Zieh Aufrufe
Ein Draw-Call ist eine Reihe von Anweisungen vom Engine zumGPU, um etwas zu rendern. Draw-Calls haben eine signifikante Overhead. Normalerweise wird weniger Draw-Calls pro Frame rendert, desto weniger Kalkulationszeit wird verbraucht.
Du kannst sehen, wie viele Zeichnungsanrufe derzeit mit dem Render Stats > Timing Element in Studio stattfinden. Du kannst die Render Stats im Client anzeigen, indem du 1> Shift1> 3> F23> drückst.
Je mehr Objekte in deiner Szene in einem bestimmten Frame gezeichnet werden müssen, desto mehr Draw Calls werden an denGPU ausgeführt. Die Roblox-Engine nutzt jedoch einen Prozess namens instancing, um identische Meshes mit den gleichen Texturmerkmalen in einem einzigen Draw Call zusammenzufassen. Insbesondere werden mehrere Meshes mit der gleichen MeshId in einem einzigen Draw Call behandelt, wenn:
- SurfaceAppearances sind identisch. TextureIDs sind identisch, wenn SurfaceAppearance nicht existiert.
- Materials sind identisch, wenn beide SurfaceAppearance und MeshPart.TextureID nicht existieren.
Andere häufige Probleme
Übertriebene Objekt-Dichte - Wenn eine große Anzahl von Objekten mit hoher Dichte konzentriert ist, dann erfordert die Rendering dieses Bereich der Szene mehr Draw-Aufrufe. Wenn Sie finden, dass Ihre Bildrate fällt, wenn Sie auf ein bestimmtes Teil der Karte schauen, kann dies ein guter Signal sein, dass die Objekt-Dichte in diesem Bereich zu hoch ist.
Objekte wie Aufkleber, Texturen und Partikel sind nicht gut zu spawnen und führen zusätzliche Zeichrufe ein. Pay extra attention to these object types in a scene. Im Besonderen können Eigenschaftsänderungen an ParticleEmitters zu einer dramatischen Erfüllungführen.
Fehlende Instanzchancen - Oft enthält eine Szene dieselben Mesh dupliziert, aber jede Kopie des Mesh hat verschiedene Mesh oder Textur-Asset-IDs. Dies verhindert das Instanzieren und kann zu unnötigen Draw-Aufrufen führen.
Eine häufige Ursache für dieses Problem ist, wenn eine ganze Szene auf einmal importiert wird, anstatt einzelne Assets in Roblox importiert und dann post-Import dupliziert werden, um die Szene zusammenzufassen.
Übertriebene Objektkomplexität - Obwohl nicht so wichtig ist wie die Anzahl der Zeichnungsanrufe, die Anzahl der Dreieck in einer Szene die Dauer, wie lange ein Frame rendern, beeinflusst. Szene mit einer sehr großen Anzahl von sehr komplexen Meshes sind ein häufiges Problem, da sind Szene mit der MeshPart.RenderFidelity -Eigenschaft auf dem zu viele Mes
Übertönungsschatten - Die Verarbeitung von Schatten ist ein teures Prozess, und Karten, die eine hohe Anzahl und Dichte von Lichtobjekten enthalten, die Schatten (oder eine hohe Anzahl und Dichte von kleinen Teilen, die von Schatten beeinflusst sind) enthalten, haben möglicherweise Leistungsprobleme.
Hohe Transparenz-Auswerfen - Objekte mit teilweiser Transparenz in der Nähe einander zwingen den Engine, die übereinstimmenden Pixel mehrere Male zu rendern, was die Erfüllungbeeinträchtzen kann. Weitere Informationen zum Identifizieren und Beheben dieses Problems finden Sie unter Delete Layered Transparencies .
Schadensbehandlung
- Identische Meshes und Reduzierung der Anzahl einzigartiger Meshes - Wenn Sie sicherstellen, dass alle identischen Meshes die gleichen unterliegenden Asset-IDs haben, kann der Engine sie in einer einzigen Draw-Call erkennen und rendern. Stellen Sie sicher, dass Sie jedes Meshes in einer Karte nur einmal hochladen und dann in Studio duplizieren, um einzigartige Assets durch den
- Culling - Culling beschreibt den Prozess der Entfernung von Draw-Calls für Objekte, die nicht in den finalen Render-Frame fällen. Standardmäßig überspringt der Engine Cull-Calls für Objekte außerhalb des Sichtfeldes der Kamera (Frustum-Culling), aber überspringt Cull-Calls für Objekte, die von anderen Objekten (Z
- Für Innenumgebungen implementieren Sie ein Raum- oder Portal-System, das Objekte nicht derzeit von Benutzern belegt.
- Reduzieren der Render-Fidelität - Setzen Sie die Render-Fidelität auf Automatisch oder Leistung . Dies ermöglicht es Meshes, auf weniger komplizierte Alternativen zurückzukehren, was die Anzahl der zu zeichnenden Polygone reduzieren kann.
- Schattenwerfen auf passenden Teilen und leichten Objekten deaktivieren - Die Komplexität der Schatten in einer Szene kann durch die selektive Deaktivierung von Schattenwerfen-Eigenschaften auf leichten Objekten und Teilen reduziert werden. Dies kann im Bearbeitungszeitpunkt oder dynamisch im Laufzeit erfolgen. Einige Beispiele sind:
Verwenden Sie die BasePart.CastShadow Eigenschaft, um das Schattencasten auf kleinen Teilen zu deaktivieren, bei denen Schatten in der Regel nicht sichtbar sind. Dies kann besonders effektiv sein, wenn nur auf Teile angewendet, die weit weg von der Kamera des Benutzers sind.
Schatten auf beweglichen Objekten deaktivieren, wenn möglich.
Deaktivieren Sie Light.Shadows auf leichten Instanzen, in denen das Objekt keine Schatten casten muss.
Begrenzen Sie die Reichweite und den Winkel von Lichtinstanzen.
Verwenden Sie weniger Lichtinstanzen.
MicroProfiler-Skope
Zielfernrohr | Verknüpfte Berechnung |
Vorbereiten und ausführen | Gesamte Darstellung |
Perform/Scene/computeLightingPerform | Lichtraster- und Schatten-Updates |
Leichte Kachel-CPU | Voxel-Lichtnetz-Updates |
ShadowMapSystem | Schatten-Kartierung |
Ausführen/Szene/UpdateView | Vorbereitung auf Rendering und Partikel-Updates |
Ausführen/Szene/RenderView | Rendernd und Post-Processing |
Netzwerk und Replikation
Netzwerk- und Replikations-Netzwerk beschreibt den Prozess, bei dem Daten zwischen dem Server und verbundenen Clients gesendet werden. Informationen werden zwischen dem Client und dem Server jeden Frame gesendet, aber größere Mengen Informationen benötigen mehr Zeit zum Berechnen.
Gewöhnliche Probleme
Überschüssiger Remote-Traffic - Senden einer großen Menge an Daten durch RemoteEvent oder RemoteFunction Objekte oder das häufige Aufrufen von ihnen kann dazu führen, dass eine große Menge an CPU-Zeit zum Verarbeiten der einkommenden Pakete pro Frame verbraucht wird. Gewöhnliche Fehler beinhalten:
- Daten jedes Frames, die nicht repliziert werden müssen.
- Replizieren von Daten auf dem Benutzereingang ohne irgendeinen Mechanismus, um es zu begrenzen.
- Versenden von mehr Daten als erforderlich. Zum Beispiel, das Versenden des gesamten Inventars des Spieler:in, wenn sie einen Artikel kaufen, anstatt nur Details des gekauften Artikels.
Erstellung oder Entfernung komplexer Instanzbäume - Wenn eine Änderung am Datenmodell auf dem Server vorgenommen wird, wird sie auf verbundene Clients repliziert. Dies bedeutet, dass das Erstellen und Zerstören großer Instanzhierarchien wie Karten zur Laufzeit sehr netzwerkintensiv sein kann.
Ein häufiger Schurke ist die komplexe Animation-Daten, die von der Animation-Editor-Plugins in den Ricks gespeichert werden. Wenn diese nicht vor der Veröffentlichung des Spiels entfernt werden und das animierte Modell regelmäßig kloniert wird, wird eine große Menge an Daten unnötig repliziert.
Server-seitige TweenService - Wenn TweenService verwendet wird, um einen Objekt-Server-seite zu tweenen, wird die tweened Eigenschaft an jeden Client jedes Frame repliziert. Nicht nur, dass dies das Tweening als Client unnötigen Netzwerkverkehr verursacht, sondern es verursacht auch viel unnötigen Netzwerkverkehr.
Schadensbehandlung
Du kannst die folgenden Taktiken verwenden, um unnötige Replikation zu reduzieren:
- Vermeiden Sie die gleichzeitige Verwendung großer Datenmengen über entfernte Ereignisse. Stattdessen senden Sie nur die notwendigen Daten in einer niedrigeren Frequenz. Zum Beispiel für den Zustand eines Charakters, replizieren Sie ihn, wenn er sich ändert, anstatt jedes Frames.
- Chunk up complex instance trees wie Karten und laden Sie sie in Stücken, um die Arbeit zu replizieren, die über mehrere Frames verteilt ist.
- Reinigen Sie die Animations-Metadaten , insbesondere die Animations-Ordner von Ricks, nach dem Importieren.
- Limitieren Sie die unnötige Instanz-Replikation , insbesondere in Fällen, in denen der Server keine Kenntnis der Instanzen, die erstellt werden, haben muss. Dies beinhaltet:
- Visuelle Effekte wie eine Explosion oder ein Zauberstab-Blast. Der Server muss nur den Standort kennen, um das Ergebnis zu bestimmen, während die Clients lokale Visualisierungen erstellen können.
- Erster-Person-Artikel-Ansichtsmodelle.
- Tweete Objekte auf dem Client, nicht auf dem Server.
MicroProfiler-Skope
Zielfernrohr | Verknüpfte Berechnung |
Prozesspakete | Verarbeite Netzwerk-Pakete, z. B. Ereigniseinladungen und Eigenschaftsänderungen |
Bandbreite zuweisen und Sender ausführen | Ausgehende Ereignisse auf Servern relevant |
Asset-Speicherverbrauch
Der höchste Einflussmechanismus, der Creator zur Verbesserung der Client-Speicher-Nutzung zur Verfügung stellen, ist Instanz-Streaming.
Instanz-Streaming
Instanz-Streaming laden selectiv Teile des Datenmodells, die nicht erforderlich sind, was die Ladezeit deutlich reduzieren und die Fähigkeit des Clients, unter Druck auf die Erinnerung zu verhindern, erhöhen kann.
Wenn Sie aufgrund von Speicherproblemen und der Deaktivierung von Instanz- Streaming Probleme haben, betrachten Sie die Aktualisierung Ihres Erlebnisses, um sie zu unterstützen, insbesondere, wenn Ihre 3D-Welt groß ist. Instanz- Streaming basiert auf der Entfernung im Platz, so dass größere Welten natürlich mehr davon profitieren.
Wenn die Instanz-Streaming aktiviert ist, können Sie die Aggressivität erhöhen. Zum Beispiel:
- Reduzieren Sie die Verwendung der persistenten StreamingIntegrity .
- Reduzieren des Streaming-Radius .
For more information on streaming options and their benefits, see Streaming-Eigenschaften .
Andere häufige Probleme
- Asset-Duplikation - Ein häufiger Fehler ist es, das gleiche Asset mehrmals hochzuladen, was zu verschiedenen Asset-IDs führt. Dies kann dazu führen, dass der gleiche Inhalt mehrmals in den Speicher geladen wird.
- Übertriebene Asset-Volumen - Selbst wenn Assets nicht identisch sind, gibt es Fälle, in denen die Möglichkeiten, dieselbe Asset wiederzuverwenden und Speicher zu sparen, verpasst werden.
- Audio-Dateien - Audio-Dateien können ein überraschender Beitrag zum Speicherverbrauch leisten, insbesondere, wenn Sie sie alle auf einmal laden, anstatt nur das zu laden, was Sie für einen Teil der Erlebnisbenötigen. Für Strategien, siehe Ladezeiten.
- Hohe Auflösungstexturen - Die Grafikspeicher-Verbrauch für eine Textur ist nicht mit der Größe der Textur auf der Festplatte verwandt, sondern vielmehr mit der Anzahl der Pixel in der Textur.
- Zum Beispiel verbraucht eine 1024x1024-Pixel-Textur 4 Mal die Grafikspeicherung einer 512x512-Textur.
- Bilder, die auf Roblox hochgeladen werden, werden in ein festes Format transcodiert, sodass kein Speicher-Vorteil beim Hochladen von Bildern in einem Farbmodell mit weniger Bytes pro Pixel besteht. Ebenso kann das Komprimieren von Bilder vor dem Hochladen oder das Entfernen des Alpha-Kanals von Bildern, die es nicht benötigen, die Bildgröße auf der Festplatte verringern, aber entweder verbessert
- Sie können den Grafikspeicherverbrauch für eine bestimmte Textur identifizieren, indem Sie die GraphicsTexture Kategorie in der Developer Console erweitern.
Schadensbehandlung
- Laden Sie Assets nur einmal hoch - Wiederverwenden Sie die gleiche Asset-ID über Objekte und stellen Sie sicher, dass die gleichen Assets, insbesondere Meshes und Bilder, nicht separat mehr als einmal hochgeladen werden.
- Finde und behebe Duplikate Assets. - Suche nach identischen Mesh-Parten und Texturen, die mehrfach mit verschiedenen IDs hochgeladen wurden.
- Obwohl es keine API gibt, um die Ähnlichkeit von Assets automatisch zu erkennen, können Sie alle Bild-Asset-IDs in Ihrem Platz sammeln (manuell oder mit einem Skript, das. PL: die Skripts), sie herunterladen und vergleichen Sie sie mit externen Vergleichs-Tools.
- Für Mesh-Teile ist die beste Strategie, einzigartige Mesh-IDs zu nehmen und sie nach Größe zu organisieren, um Duplikate manuell zu identifizieren.
- Statt separate Texturen für verschiedene Farben zu verwenden, laden Sie eine einzige Textur hoch und verwenden Sie die Eigenschaft SurfaceAppearance.Color, um verschiedene Farbtöne darauf anzuwenden.
- Assets in der Karte separat importieren - Statt eine gesamte Karte auf einmal zu importieren, importieren und konstruieren Sie Assets in der Karte individuell und konstruieren Sie sie. Der 3D-Importer führt keine Duplikation von Meshes durch, daher werden wenn Sie eine große Karte mit vielen einzelnen Stockwerksfliesen importieren, jedes dieser Stockwerke als separates Asset
- Begrenzen Sie die Pixel der Bilder auf nicht mehr als die notwendige Menge. Es sei denn, ein Bild besetzt eine große Menge physischen Platz auf dem Bildschirm, normalerweise benötigt es normalerweise nicht mehr als 512x512 Pixel. Die meisten kleineren Bilder sollten kleiner sein als 256x256 Pixel.
- Verwenden Sie Trim Sheets , um die maximale Textur wiederverwendung in 3D-Karten zu gewährleisten. Für Schritte und Beispiele, wie Sie Trim Sheets erstellen, sehen Sie Creating Trim Sheets .
Ladezeiten
Viele Erlebnisse implementieren benutzerdefinierte Ladebildschirme und verwenden die Methode ContentProvider:PreloadAsync(), um Assets zu erfordern, damit Bilder, Sounds und Meshes im Hintergrund heruntergeladen werden.
Der Vorteil dieser Ansicht ist, dass Sie sicherstellen können, dass wichtige Teile Ihres Erlebnisses vollständig geladen sind, ohne Pop-in. jedoch ist ein häufiger Fehler, diesen Methoden zu übertreiben, um mehr Assets vorzuladen, als tatsächlich erforderlich sind.
Ein Beispiel für eine schlechte Praxis ist das Laden der gesamtenWorkspace. Während dies die Textur-Pop-in verhindern kann, erhöht es die Ladezeit signifikant.
Stattdessen verwenden Sie nur ContentProvider:PreloadAsync() in notwendigen Situationen, die folgende Situationen umfassen:
- Bilder auf der Ladebildschirm.
- Importiere wichtige Bilder in deinem Erlebnis-Menü, wie Knopf-Hintergründe und Icons.
- Wichtige Assets in der Start- oder Spawn-Zone.
Wenn Sie eine große Anzahl von Assets laden müssen, empfehlen wir Ihnen, eine Skip-Laden-Schaltfläche zu bieten.