Techniken und Konvertierung

*Dieser Inhalt wurde mit KI (Beta) übersetzt und kann Fehler enthalten. Um diese Seite auf Englisch zu sehen, klicke hier.

Dieser Leitfaden beschreibt mehrere Techniken zur effizienten und effektiven Nutzung des In-Game Instanzstreamings. Während es keine "Einheitslösung" für das Design eines Streaming-Spiels gibt, werden Sie mit diesen allgemeinen Schritten die meisten Anforderungen erfüllen.

Streaming-Eigenschaften

Sobald StreamingEnabled im Studio für das Workspace-Objekt aktiviert ist, setzen Sie die zugehörigen Eigenschaften auf die folgenden empfohlenen Werte:

EigenschaftEmpfehlung
EnableSLIMAvatarsVerwenden Sie Enabled, um Standard-Rig-Avatare als leichte, animierte Stellvertreter darzustellen, wenn dies angemessen ist. Weitere Informationen finden Sie unter SLIM-Avatare.
ModelStreamingBehaviorVerwenden Sie Improved, um das effizienteste Streaming für Models mit Nachkommen von BasePart zu aktivieren.
StreamingIntegrityModeVerwenden Sie PauseOutsideLoadedArea, um die Spielintegrität zu wahren, ohne unnötig oder zu oft zu pausieren.
StreamingMinRadiusVerwenden Sie den Standardwert von 64, um zu maximieren, wie stark die Engine das Spiel für Geräte mit niedriger Leistung skalieren kann.
StreamingTargetRadiusVerwenden Sie den Standardwert von 1024, um ein gutes Gleichgewicht zwischen Sichtbarkeit für Spieler auf Hochleistungsgeräten und einem angemessenen Speicherbedarf zu erreichen.
StreamOutBehaviorVerwenden Sie Opportunistic, um dem Client zu ermöglichen, Inhalte aggressiv zu bereinigen, was den Speicherverbrauch erheblich reduziert und hilft, Speicherüberläufe zu verhindern.

Modell-Level-of-Detail

Model.LevelOfDetail hilft dabei, nicht gestreamte Model-Inhalte mit leichten Composite- oder Imposter-Meshes zu füllen, wodurch die Welt visuell vollständig aussieht. SLIM (Scalable Lightweight Interactive Models) sind besonders effektiv, da Spieler oft keinen Unterschied zwischen einem SLIM-Mesh und dem vollständig gestreamten Original erkennen können.

Für die besten Ergebnisse:

  • Gruppieren Sie Teile, die räumlich und logisch zusammenhängen, zum Beispiel alle Teile eines Autos.
  • Setzen Sie LevelOfDetail auf SLIM für Modelle, die statische Meshes und Teile enthalten. Modelle, die zur Laufzeit geändert werden oder Animationen abspielen, werden nicht unterstützt.
  • Halten Sie das räumliche Ausmaß jedes Modells unter ~64 kubischen Studs, um die Wahrscheinlichkeit zu erhöhen, dass das gesamte tatsächliche Modell zusammen gestreamt wird. Wenn ein Modell sehr große Ausmaße hat, zerlegen Sie es in kleinere modulare Modelle und wenden Sie ein entsprechendes LevelOfDetail auf jedes an.

Modellstruktur

Neben der Festlegung des Modell-Level-of-Detail hat die Struktur und die Einstellung Ihrer Models einen erheblichen Einfluss darauf, wie gut das Streaming funktioniert. Während Sie ein bestehendes Spiel erstellen oder konvertieren:

  • Verwenden Sie atomare Modelle für logische Gruppierungen — Wenn ein Skript Zugriff auf alle Teile innerhalb eines Modells benötigt, setzen Sie den ModelStreamingMode auf Atomic. Dies ermöglicht es clientseitigen Skripten, sicher auf Instanzen innerhalb des Modells zuzugreifen, ohne übermäßigen Gebrauch von WaitForChild() zu machen (obwohl solche Skripte immer noch WaitForChild() für das gesamte atomare Modell verwenden müssen).

  • Minimieren Sie persistente ModellePersistente Modelle laden nach dem Beitritt und streamen niemals aus, wodurch sie dauerhaft Speicher belegen. Setzen Sie den ModelStreamingMode eines Modells auf Persistent, wenn es immer verfügbar und für Skripte zugänglich sein muss.

  • Zerlegen Sie Container-Modelle — Ein häufiges Nicht-Streaming-Muster ist ein einzelnes riesiges Model, das viele NPCs, Requisiten oder ähnliche Gruppierungen enthält. Unter Streaming verringern Container-Modelle die Streaming-Effizienz und sind nicht optimal für das Modell-Level-of-Detail, das am besten mit eng gruppierten Instanzen funktioniert. Zerlegen Sie Container-Modelle in kleinere Modelle mit physisch nahen oder logisch verwandten Teilen.

  • Flachere tief verschachtelte Modellhierarchien — Das Nisten eines persistenten Modells innerhalb eines atomaren Modells zwingt das atomare Modell effektiv dazu, sich wie ein persistentes Modell zu verhalten. Flache Hierarchien sind unter Streaming einfacher zu verstehen.

SLIM-Avatare

Plattform-Avatare außerhalb des derzeit gestreamten Bereichs sind standardmäßig nicht sichtbar, aber die Aktivierung von Workspace.EnableSLIMAvatars rendert Standard-Rig Avatare als leichte, animierte Stellvertreter, wenn dies angemessen ist. Effektiv:

  • Rendert die Engine eine SLIM-Version, wenn ein tatsächliches Avatar-Modell gestreamt wird.
  • Wechselt zwischen SLIM- und hochauflösenden Darstellungen basierend auf verfügbaren Ressourcen, selbst innerhalb des Streaming-Radius.
  • Drosselt SLIM-Animationen basierend auf der Wichtigkeit der Szene und der verfügbaren Bandbreite.

SLIM-Avatare unterstützen R15-Standard-Rig-Spielercharaktere mit Körper, Kopf, geschichteter Kleidung und Accessoires. R6-Avatare, NPCs und Avatare mit benutzerdefinierten Proportionen sind ausgeschlossen. Für die vollständige Liste der unterstützten und ausgeschlossenen Avatar-Konfigurationen, Leistungsdaten und Fehlersuche-Tipps siehe SLIM-Avatare.

Skriptmuster

Die folgenden Skriptmuster sind am häufigsten vom Streaming betroffen. Die richtige Strategie hängt von der Absicht des Codes ab, daher listet jedes Muster mehrere Optionen auf, wo dies angemessen ist.

Direkter Index zu Nachkommen

Das Indizieren in Workspace-Nachkommen mit dem .-Operator wirft einen Fehler, wenn eine Instanz im Pfad derzeit nicht gestreamt ist. Das Gleiche gilt für FindFirstChild(), FindFirstChildWhichIsA() und FindFirstChildOfClass(), die nil zurückgeben, wenn das Kind nicht gestreamt ist.

Nachkommen-Suche
local house1 = workspace:FindFirstChild("House1") -- nil, wenn "House1" nicht gestreamt ist
local door = workspace.House1.Door -- Fehlerhaft, wenn "House1" oder "Door" nicht gestreamt ist

Ein ähnliches Muster ist der direkte Zugriff auf Humanoid oder andere Charakternachkommen innerhalb einer Player.CharacterAdded-Verbindung. Unter Streaming wird das Charaktermodell an Workspace angehängt, bevor alle seine Nachkommen repliziert wurden, sodass das direkte Indizieren fehlschlägt.

Charakternachkommen
local Players = game:GetService("Players")
local player = Players.LocalPlayer
player.CharacterAdded:Connect(function(character)
local humanoid = character.Humanoid
end)

Wenn das Skript ohne eine Instanz nicht fortfahren kann, warten Sie darauf mit WaitForChild():

Nachkommen-Suche
local house1 = workspace:WaitForChild("House1")
local door = house1:WaitForChild("Door")

Instanzen, die remote gesendet werden

Ein RemoteEvent/RemoteFunction-Signal und die Instanz, auf die es sich bezieht, reisen unabhängig, sodass das Signal beim Client ankommen kann, bevor die Instanz vorhanden ist — oder die Instanz möglicherweise überhaupt nicht vorhanden ist. Zwei wahrscheinliche Ursachen sind:

  • Unter Streaming kann es eine kleine Verzögerung geben, zwischen dem Zeitpunkt, an dem ein Teil/Modell auf dem Server erstellt wird, und dem Zeitpunkt, an dem es an die Clients repliziert wird. Effektiv kann ein Teil, auf das durch ein RemoteEvent/RemoteFunction verwiesen wird, einfach noch nicht existieren, selbst innerhalb eines gestreamten Bereichs.

  • Das Senden eines Teil-/Modellverweises vom Server an den Client über ein RemoteEvent oder RemoteFunction erfordert, dass die Instanz an den empfangenden Client repliziert wird. Das Senden eines Instanzpfads als Zeichenfolge hat dasselbe Problem, da der Pfad möglicherweise auf einen nicht existierenden Ort auf dem Client verweist:

    Client-Skript
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
    remoteEvent.OnClientEvent:Connect(function(data)
    local checkpoint = data.checkpoint -- Fehler, wenn "checkpoint" nicht gestreamt ist
    local level = workspace.Levels[data.levelPath] -- Fehler, wenn der Pfad nicht gestreamt ist
    end)

Wenn das empfangende Client-Skript die Instanz benötigt, um fortzufahren, fügen Sie WaitForChild() hinzu, bevor Sie sie verwenden. Beachten Sie, dass dies unbegrenzt warten kann, wenn die Instanz niemals gestreamt wird, daher sollten Sie in Betracht ziehen, ein Timeout als zweiten Parameter von WaitForChild() hinzuzufügen.

Client-Desynchronisation

Die Desynchronisation auf der Client-Seite sollte als Ausnahme und nicht als Standarddesignmuster behandelt werden. Das Einführen von nur-client-Kopien oder das Umordnen von Instanzen lokal kann ernsthafte Probleme verursachen. Überprüfen Sie Ihren Code auf Stellen, die auf diese Arten von Änderungen angewiesen sind, die auf dem Client bestehen bleiben.

Zum Beispiel kann das lokale Umordnen einer Instanz von ReplicatedStorage zu Workspace diese Instanz für das Streaming qualifizieren. Ebenso erzeugt das Klonen einer Instanz lokal (Instance:Clone()) von ReplicatedStorage in Workspace eine nur-client-Kopie, die nicht mehr Teil des Replikationspipelines des Servers ist und keine Aktualisierungen von der ursprünglichen serverbesessenen Instanz erhält.

Dasselbe Konzept gilt, wenn Instance:Destroy() auf dem Client für ein serverbesessenes Objekt aufgerufen wird. Dies entfernt die Instanz lokal, aber der Server hat sie weiterhin, sodass sie wieder mit ihrem ursprünglichen Zustand gestreamt wird, wenn sie berechtigt ist.

Proaktives Streaming

Wenn das nächste Ziel eines Spielers vorhersehbar ist, führen Sie serverseitige Aufrufe zu Player:RequestStreamAroundAsync() durch, um vorübergehende Bereiche für temporäres Laden zu streamen, oder verwenden Sie Player:AddReplicationFocus() auf begrenzter Basis für Bereiche, die bis zur expliziten Freigabe geladen bleiben sollen.

Zum Beispiel, wenn ein Spielercharakter durch eine CFrame-Änderung zu einem anderen Haus eines Spielers an einem entfernten Ort teleportiert werden soll, können Sie den Zielbereich vorab abrufen, um Pop-ins zu minimieren und einen reibungsloseren Übergang zu ermöglichen. Das folgende Skript zeigt, wie ein clientseitiges Remote-Ereignis ausgelöst werden kann, um einen Spielercharakter mithilfe einer Vorababrufmethode zu bewegen. Wenn die Vorababrufanfrage erfolgreich ist, wenn die Funktion zurückkehrt, sollte der minimale Radius um den Zielort auf dem Client vorhanden sein.

Server-Skript - Spielercharakter teleportieren
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local function teleportPlayer(player, teleportTarget)
-- Streaming um den Zielort anfordern
player:RequestStreamAroundAsync(teleportTarget)
-- Charakter teleportieren
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(teleportTarget))
end
end
-- Teleportfunktion aufrufen, wenn der Client das Remote-Ereignis auslöst
teleportEvent.OnServerEvent:Connect(teleportPlayer)

Instanzeigenschaften lesen

Sobald eine Instanz gestreamt wird, werden ihre Aktualisierungen der Eigenschaften nicht mehr an diesen Client repliziert. Das Lesen von Eigenschaften wie BasePart.Position funktioniert weiterhin, gibt jedoch den zuletzt replizierten Wert zurück, der beliebig veraltet sein kann.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- Position kann veraltet sein, wenn "target" gestreamt wurde
local dist = (target.Position - player.Character.HumanoidRootPart.Position).Magnitude

Bewegen Sie die Logik auf den Server, da serverseitige Skripte alle Instanzen zu jeder Zeit sehen. Dies ist im Allgemeinen die zuverlässigste Option für Distanzprüfungen und andere positionssensitive Logik.

Warten auf dem kritischen Pfad

Einige Nicht-Streaming-Spiele laden ihre Karte, indem sie sie von ReplicatedStorage in Workspace klonen und dann auf dem Client warten, bevor sie einen Ladebildschirm schließen und die Bereitschaft signalisieren. Unter Streaming hängt dies unbegrenzt — der Charakter des Clients ist noch nicht erschienen, sodass es keinen Replikationsfokus gibt und die räumliche Karteninstanz niemals gestreamt wird.

Bewegen Sie die Logik des Ladebildschirms so, dass sie nicht von einer bestimmten räumlichen Instanz abhängt, indem Sie beispielsweise die Bereitschaft signalisieren, sobald der Charakter erschienen ist und der unmittelbare Umgebungsbereich gestreamt wurde.

Signaländerungsbehandlung

Signale wie Instance.ChildAdded/Instance.ChildRemoved und CollectionService-Signale wie GetInstanceAddedSignal() oder GetInstanceRemovedSignal() werden ebenfalls beim Streaming ein-/ausgeschaltet, ununterscheidbar von echten Spawns/Entfernungen. Empfangende Skripte können den Unterschied allein anhand des Signals nicht erkennen, sodass Logik, die davon ausgeht, dass ein Signal einem "echten" Ereignis entspricht, aktualisiert werden muss.

Überprüfen Sie Skripte auf alle Signal-Listener, die brechen oder sich erheblich ändern könnten, wenn sie durch Streaming ein- und/oder ausgesendet werden. Wenn Sie beispielsweise Audio oder visuelle Effekte abspielen, wenn ein feindlicher NPC ursprünglich in die Welt erscheint, weisen Sie jedem Feind ein Attribut wie Spawned beim ersten Spawn zu und überspringen Sie das Abspielen derselben Audio-/Effekte bei zukünftigen Streaming-Einheiten des Feindes.

Attributverfolgung
local CollectionService = game:GetService("CollectionService")
local TAG_NAME = "Enemy"
CollectionService:GetInstanceAddedSignal(TAG_NAME):Connect(function(enemy)
if not enemy:GetAttribute("Spawned") then
-- Setzen Sie das Attribut "Spawned" beim Feind für den ersten Spawn
enemy:SetAttribute("Spawned", true)
-- Spielen Sie Audio-/visuelle Effekte für diesen ersten Spawn ab
playSpawnEffects(enemy)
end
end)

Iteration über Sammlungen

Clientseitige Sammlungsiterationen wie Instance:GetChildren() und Instance:GetDescendants() geben nur die gestreamte Teilmenge der Nachkommen zurück. Dies gilt selbst dann, wenn der Elternteil immer repliziert wird, wie z. B. ein Folder, der direkt unter Workspace liegt, dessen räumliche Nachkommen ein- und ausgesendet werden.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- Der Ordner "Homes" wird immer repliziert, aber seine Kinder streamen ein und aus
-- Diese Schleife könnte Häuser verpassen, die derzeit nicht gestreamt sind
for _, home in workspace.Homes:GetChildren() do
if home.Settings.Owner.Value == player.Name then
return home
end
end

Wenn eine vollständige Aufzählung erforderlich ist, führen Sie den Scan auf dem Server durch und übergeben Sie das Ergebnis bei Bedarf an den Spieler über ein RemoteEvent.

Räumliche Abfragen

Clientseitige räumliche Abfragen wie WorldRoot:Raycast(), WorldRoot:GetPartBoundsInBox() und Model:GetBoundingBox() spiegeln nur gestreamte Inhalte wider. Ob das ein Problem darstellt, hängt davon ab, wofür die Abfrage verwendet wird.

Verwenden Sie den Server für Abfragen, deren Ergebnis die gesamte Welt widerspiegeln muss, z. B. einen Raycast, der überprüft, ob der Spieler Sichtlinie zu einem entfernten Ziel hat.

Andere Muster

Die folgenden Muster können ebenfalls zutreffen und sollten sorgfältig berücksichtigt werden:

  • Ein Sound oder AudioPlayer, der an ein 3D-Objekt angehängt ist, stoppt, wenn dieses Objekt gestreamt wird. Für Umgebungsgeräusche, die unabhängig vom Streaming bestehen bleiben sollen, hängen Sie denEmitter an ein persistentes Modell oder an einen nicht-streamenden Container.

  • In-Game UI Objekte wie BillboardGui oder SurfaceGui sowie visuelle Effekte wie Beams oder Highlights, deren Adornee oder Anhang gestreamt wird, hören einfach auf zu rendern. Dies kann das beabsichtigte Verhalten sein, aber Sie sollten es überprüfen.

  • BasePart.Touched-Ereignisse, ProximityPrompts, DragDetectors und ClickDetectors funktionieren nicht für Spieler, deren Client das zugehörige Teil/Modell nicht gestreamt hat. Wenn Interaktionen aus jeder Entfernung möglich sein müssen, muss das Modell persistent sein oder die Interaktion benötigt einen anderen Mechanismus.

  • Für PathfindingService und clientseitiges Pathfinding sieht der Pathfinder nur gestreamte Geometrie auf dem Client und kann durch Hindernisse routen, die auf dem Server existieren. Siehe hier für Strategien.

Realistische Testbedingungen

Sobald Skripte aktualisiert sind, testen Sie das Spiel gründlich. Streaming-Fehler treten oft nur an den Rändern des gestreamten Bereichs oder während Übergängen auf, sodass es nicht ausreicht, nur in der Nähe des Spawns oder im Zielradius zu testen.

  • Testen Sie mit Workspace.StreamingTargetRadius, das auf seinen Minimalwert (64) gesetzt ist. Einige Streaming-Fehler treten nur auf, wenn der gestreamte Bereich klein ist.

  • Spielen Sie die vollständigen Durchlaufmuster des Spiels, teleportieren Sie zwischen entfernten Bereichen und besuchen Sie Bereiche erneut, nachdem Sie sie verlassen haben. Dies sind die Situationen, die das Streaming am meisten beanspruchen.

  • Verwenden Sie die Streaming-Debug-Überlagerung, um die aktiven Streaming-Einstellungen, derzeit geladenen Regionen und den Laufzeit-Streaming-Zustand zu überwachen.

  • Überwachen Sie das Output-Fenster und die Entwicklerkonsole auf Fehler, da viele der Skriptmuster Fehler erzeugen, anstatt stillschweigend fehlerhaft zu sein. Achten Sie besonders auf Fehler der Form attempt to index nil with ..., die oft auf einen fehlenden WaitForChild()-Aufruf hinweisen.

  • Rüsten Sie Tools aus, feuern Sie Waffen ab und lösen Sie verschiedene Spielinteraktionen aus.

AI-Streaming-Konvertierungsfähigkeit

Um bei der Streaming-Konvertierung und -Optimierung zu helfen, bietet Roblox eine AI-Streaming-Fähigkeit, die über den Studio MCP-Server zugänglich ist. Die Fähigkeit bewertet automatisch Ihr Spiel, wendet empfohlene Konfigurationen an und bereinigt Kompatibilitätsprobleme, einschließlich:


Um die AI-Fähigkeit in Ihrem Spiel zu verwenden:

  1. WICHTIG
    Sichern Sie Ihr Spiel. Der Konvertierungsprozess kann komplex sein, daher sollten Sie immer eine Sicherung speichern (Datei ⟩ Veröffentlichen bei Roblox als) bevor Sie die Fähigkeit ausführen.

  2. Sie können diese Fähigkeit mit jedem LLM, das Sie bevorzugen, über das Model Context Protocol (MCP) im Studio ausführen. Hochwertige AI-Modelle mit großen Kontextfenstern werden empfohlen; in Claude Opus dauert die typische Konvertierung 20-30 Minuten und nutzt ungefähr 200.000 Tokens Kontext.

    1. Öffnen Sie Ihr Spiel im Studio.
    2. Downloaden Sie die Fähigkeit und öffnen Sie in Ihrem AI-Client den entpackten Ordner (roblox-streaming-conversion) als aktuelles Projekt.
    3. Führen Sie die Fähigkeit mit /rbx-convert-to-streaming aus.
    4. Wie bei jedem AI-Ausgang, überprüfen Sie die Ergebnisse und testen Sie Ihr Spiel umfassend unter realistischen Testbedingungen.
©2026 Roblox Corporation. Roblox, das Roblox-Logo und "Powering Imagination" gehören zu unseren eingetragenen und nicht eingetragenen Markenzeichen in den USA und anderen Ländern.