Technieken en conversie

*Deze inhoud is vertaald met behulp van AI (bèta) en kan fouten bevatten. Klik hier om deze pagina in het Engels te bekijken.

Deze gids schetst verschillende technieken voor het efficiënt en effectief gebruiken van in-game instance streaming. Hoewel er geen "one size fits all" oplossing is voor het ontwerpen van een streaming spel, zullen deze algemene stappen je het grootste deel van de weg helpen.

Streaming eigenschappen

Zodra StreamingEnabled is ingeschakeld voor het Workspace object in Studio, stel je de gerelateerde eigenschappen in op de volgende aanbevolen waarden:

EigenschapAanbeveling
EnableSLIMAvatarsGebruik Enabled om R15 avatars weer te geven als lichte, geanimeerde stand-ins wanneer dat gepast is. Zie SLIM avatars voor meer info.
ModelStreamingBehaviorGebruik Improved om de meest efficiënte streaming voor Models met BasePart afstammelingen in te schakelen.
StreamingIntegrityModeGebruik PauseOutsideLoadedArea om de integriteit van het spel in balans te houden zonder onnodig of te vaak te pauzeren.
StreamingMinRadiusGebruik de standaardwaarde van 64 om te maximaliseren hoeveel de engine het spel kan verkleinen voor low-end apparaten.
StreamingTargetRadiusGebruik de standaardwaarde van 1024 om een goede balans te vinden tussen zichtbaarheid voor spelers op high-end apparaten en een redelijke geheugendruk.
StreamOutBehaviorGebruik Opportunistic om de client in staat te stellen om agressief ongebruikte inhoud te verwijderen, wat het geheugengebruik aanzienlijk vermindert en helpt om out-of-memory crashes te voorkomen.

Model niveau van detail

Model.LevelOfDetail helpt om niet-gestreamde Model inhoud in te vullen met lichte composiet- of imposter-meshes, waardoor de wereld visueel compleet lijkt. SLIM (Scalable Lightweight Interactive Models) zijn bijzonder effectief, omdat spelers vaak niet kunnen onderscheiden of een SLIM-mesh de volledig gestreamde originele is.

Voor de beste resultaten:

  • Groepeer delen die ruimtelijk en logisch gerelateerd zijn, bijvoorbeeld alle delen van een auto.
  • Stel LevelOfDetail in op SLIM voor modellen die statische meshes en delen bevatten. Modellen die tijdens runtime worden gewijzigd of animaties afspelen worden niet ondersteund.
  • Houd de ruimtelijke omvang van elk model onder ~64 kubieke studs om de kans te vergroten dat het hele daadwerkelijke model samen wordt gestreamd. Als een model zeer grote afmetingen heeft, splits het dan op in kleinere modulaire modellen en pas een geschikte LevelOfDetail toe op elk model.

Modelstructuur

Naast het instellen van model niveau van detail, heeft de structuur en instellingen van je Models een significante impact op hoe goed streaming presteert. Terwijl je een bestaand spel bouwt of converteert:

  • Gebruik atomische modellen voor logische groepering — Wanneer een script toegang nodig heeft tot alle delen binnen een model, stel je de ModelStreamingMode in op Atomic. Dit stelt client-side scripts in staat om veilig toegang te krijgen tot instanties binnen het model zonder overmatig gebruik van WaitForChild() (hoewel dergelijke scripts nog steeds WaitForChild() moeten gebruiken voor het algehele atomische model).

  • Minimaliseer persistente modellen — Persistente modellen laden na join en streamen nooit uit, waardoor ze permanent geheugen innemen. Stel de ModelStreamingMode van een model in op Persistent alleen als het moet beschikbaar en toegankelijk zijn voor scripts op elk moment.

  • Decompositie van container modellen — Een veelvoorkomend niet-streaming patroon is een enkel enorm Model dat veel NPC's, props of vergelijkbare groeperingen bevat. Onder streaming verminderen container modellen de streaming efficiëntie en zijn ze niet optimaal voor model niveau van detail dat het beste werkt met dicht bij elkaar gegroepeerde instanties. Decompose container modellen in kleinere modellen met fysiek dicht bij elkaar of logisch gerelateerde delen.

  • Vlak diep geneste modelhiërarchieën — Het nestelen van een persistente model binnen een atomisch model dwingt effectief het atomische model om zich als persistent te gedragen. Vlakke hiërarchieën zijn gemakkelijker te begrijpen onder streaming.

SLIM avatars

Platform avatars buiten het momenteel gestreamde gebied zijn standaard niet zichtbaar, maar het inschakelen van Workspace.EnableSLIMAvatars rendert R15 avatars als lichte, geanimeerde stand-ins wanneer dat gepast is. Effectief:

  • Rendert de engine een SLIM-versie wanneer een daadwerkelijk avatar model uitstreamt.
  • Wisselt tussen SLIM en full-resolution representaties op basis van beschikbare middelen, zelfs binnen de streamingradius.
  • Beperkt SLIM-animaties op basis van scene belangrijkheid en beschikbare bandbreedte.

SLIM avatars ondersteunen R15 spelerpersonages met een lichaam, dynamisch hoofd, standaard of geavanceerd R15 rig, en rigide/gelaagde accessoires. R6 avatars, NPC's en avatars met aangepaste verhoudingen zijn uitgesloten. Voor de volledige lijst van ondersteunde en uitgesloten avatarconfiguraties, prestatiegegevens en probleemoplossingstips, zie SLIM avatars.

Script patronen

De volgende script patronen worden het meest beïnvloed door streaming. De juiste strategie hangt af van de intentie van de code, dus elk patroon vermeldt meerdere opties waar dat gepast is.

Directe index naar afstammelingen

Indexeren in Workspace afstammelingen met de . operator gooit een fout als een instantie in het pad momenteel niet is gestreamd. Hetzelfde geldt voor FindFirstChild(), FindFirstChildWhichIsA() en FindFirstChildOfClass() die nil retourneren als het kind niet is gestreamd.

Afstammeling Lookup
local house1 = workspace:FindFirstChild("House1") -- nil als "House1" niet is gestreamd
local door = workspace.House1.Door -- Gebroken als "House1" of "Door" niet is gestreamd

Een vergelijkbaar patroon is het direct benaderen van de Humanoid of andere karakterafstammelingen binnen een Player.CharacterAdded verbinding. Onder streaming is het karaktermodel aan Workspace gekoppeld voordat al zijn afstammelingen zijn gerepliceerd, dus directe indexering faalt.

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

Als het script geen vooruitgang kan boeken zonder een instantie, wacht er dan op met WaitForChild():

Afstammeling Lookup
local house1 = workspace:WaitForChild("House1")
local door = house1:WaitForChild("Door")

Instanties die op afstand worden verzonden

Een RemoteEvent/RemoteFunction signaal en de instantie waarnaar het verwijst, reizen onafhankelijk, zodat het signaal op de client kan aankomen voordat de instantie aanwezig is — of de instantie is misschien helemaal niet aanwezig. Twee waarschijnlijke oorzaken zijn:

  • Onder streaming kan er een kleine vertraging zijn tussen wanneer een deel/model op de server wordt gemaakt en wanneer het naar clients wordt gerepliceerd. Effectief kan een deel dat door een RemoteEvent/RemoteFunction wordt verwezen, simpelweg nog niet bestaan, zelfs niet binnen een gestreamd gebied.

  • Het verzenden van een deel/model referentie van server naar client via een RemoteEvent of RemoteFunction vereist dat de instantie naar de ontvangende client is gerepliceerd. Het verzenden van een instantiepad als een string heeft hetzelfde probleem, omdat het pad kan verwijzen naar een niet-bestaande locatie op de client:

    Client Script
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
    remoteEvent.OnClientEvent:Connect(function(data)
    local checkpoint = data.checkpoint -- Fouten als "checkpoint" niet is gestreamd
    local level = workspace.Levels[data.levelPath] -- Fouten als pad niet is gestreamd
    end)

Als het ontvangende clientscript de instantie nodig heeft om verder te gaan, voeg dan WaitForChild() toe voordat je het gebruikt. Merk op dat dit oneindig kan wachten als de instantie nooit wordt gestreamd, dus overweeg om een time-out toe te voegen als de tweede parameter van WaitForChild().

Client desynchronisatie

Client-side desynchronisatie moet worden behandeld als een uitzondering, niet als een standaard ontwerppatroon. Het introduceren van client-only kopieën of het lokaal herplaatsen van instanties kan ernstige problemen veroorzaken. Controleer je code op plaatsen die afhankelijk zijn van deze soorten wijzigingen die op de client blijven bestaan.

Bijvoorbeeld, het lokaal herplaatsen van een instantie van ReplicatedStorage naar Workspace kan die instantie in aanmerking brengen om uit te streamen. Evenzo, het lokaal klonen van een instantie (Instance:Clone()) van ReplicatedStorage naar Workspace creëert een client-only kopie die niet langer deel uitmaakt van de server replicatiepijplijn en geen eigenschapsupdates van de originele server-eigen instantie zal ontvangen.

Hetzelfde concept geldt wanneer je Instance:Destroy() op de client aanroept voor een server-eigen object. Dit verwijdert de instantie lokaal, maar de server heeft deze nog steeds, dus deze zal opnieuw worden gestreamd met zijn oorspronkelijke staat wanneer dat mogelijk is.

Proactieve streaming

Wanneer de volgende bestemming van een speler kan worden voorspeld, maak dan server-side aanroepen naar Player:RequestStreamAroundAsync() om tijdelijke gebieden voor tijdelijke laadtijd te streamen, of gebruik Player:AddReplicationFocus() op een beperkte basis voor gebieden die geladen moeten blijven totdat ze expliciet worden vrijgegeven.

Bijvoorbeeld, wanneer een speler karakter op het punt staat te teleporteren door een CFrame wijziging naar het huis van een andere speler op een verre locatie, kun je het bestemmingsgebied vooraf ophalen om pop-in te minimaliseren en een soepelere overgang te bieden. Het volgende script toont hoe een client-naar-server remote event kan worden afgevuurd om een speler karakter te verplaatsen met een vooraf ophalen methode. Als het vooraf ophalen verzoek succesvol is wanneer de functie retourneert, zou de minimale straal rond de doel locatie aanwezig moeten zijn op de client.

Server Script - Teleporteer Speler Karakter
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local function teleportPlayer(player, teleportTarget)
-- Vraag streaming aan rond de doel locatie
player:RequestStreamAroundAsync(teleportTarget)
-- Teleporteer karakter
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(teleportTarget))
end
end
-- Roep teleport functie aan wanneer de client het remote event afvuurt
teleportEvent.OnServerEvent:Connect(teleportPlayer)

Instantie-eigenschap lezen

Zodra een instantie uitstreamt, worden de eigenschapsupdates niet langer gerepliceerd naar die client. Het lezen van eigenschappen zoals BasePart.Position blijft succesvol, maar retourneert de laatst gerepliceerde waarde die willekeurig verouderd kan zijn.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- Positie kan verouderd zijn als "target" is gestreamd
local dist = (target.Position - player.Character.HumanoidRootPart.Position).Magnitude

Verplaats de logica naar de server, aangezien server-side scripts alle instanties op elk moment zien. Dit is over het algemeen de meest betrouwbare optie voor afstandscontroles en andere positiegevoelige logica.

Wachten op het kritieke pad

Sommige niet-streaming spellen laden hun kaart door deze te klonen van ReplicatedStorage naar Workspace, en wachten vervolgens op de client voordat ze een laadscreen afschaffen en gereedheid signaleren. Onder streaming blijft dit oneindig hangen — het karakter van de client is nog niet gespawned, dus er is geen replicatiefocus, en de ruimtelijke kaart instantie streamt nooit in.

Verplaats de laadscreen logica zodat deze niet afhankelijk is van een specifieke ruimtelijke instantie die aanwezig is, bijvoorbeeld door gereedheid te signaleren zodra het karakter is gespawned en het onmiddellijke omringende gebied is gestreamd.

Signaalverandering afhandeling

Signalen zoals Instance.ChildAdded/Instance.ChildRemoved en CollectionService signalen zoals GetInstanceAddedSignal() of GetInstanceRemovedSignal() worden ook geactiveerd bij stream in/uit, ononderscheidbaar van echte spawns/verwijderingen. Ontvangende scripts kunnen het verschil niet alleen aan het signaal vertellen, dus logica die aanneemt dat een signaal overeenkomt met een "echte" gebeurtenis moet worden bijgewerkt.

Controleer scripts op eventuele signaallisteners die kunnen breken of aanzienlijk kunnen veranderen wanneer ze worden geactiveerd door stream in en/of stream uit. Bijvoorbeeld, als je audio of visuele effecten afspeelt wanneer een vijand NPC aanvankelijk in de wereld spawnt, wijs dan elke vijand een attribuut zoals Spawned toe bij de eerste spawn, en sla het opnieuw afspelen van dezelfde audio/effecten over bij toekomstige stream-ins van de vijand.

Attribuut Tracking
local CollectionService = game:GetService("CollectionService")
local TAG_NAME = "Enemy"
CollectionService:GetInstanceAddedSignal(TAG_NAME):Connect(function(enemy)
if not enemy:GetAttribute("Spawned") then
-- Stel "Spawned" attribuut in op vijand voor initiële spawn
enemy:SetAttribute("Spawned", true)
-- Speel audio/visuele effecten af voor deze initiële spawn
playSpawnEffects(enemy)
end
end)

Iteratie over collecties

Client-side collectie iteraties zoals Instance:GetChildren() en Instance:GetDescendants() retourneren alleen de gestreamde subset van afstammelingen. Dit geldt zelfs wanneer de ouder zelf altijd wordt gerepliceerd, zoals een Folder direct onder Workspace waarvan de ruimtelijke afstammelingen in en uit streamen.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- Map "Homes" is altijd gerepliceerd maar zijn kinderen streamen in en uit
-- Deze lus kan huizen missen die momenteel niet zijn gestreamd
for _, home in workspace.Homes:GetChildren() do
if home.Settings.Owner.Value == player.Name then
return home
end
end

Als een volledige enumeratie vereist is, voer dan de scan op de server uit en geef het resultaat door aan de speler via een RemoteEvent indien nodig.

Ruimtelijke queries

Client-side ruimtelijke queries zoals WorldRoot:Raycast(), WorldRoot:GetPartBoundsInBox(), en Model:GetBoundingBox() weerspiegelen alleen gestreamde inhoud. Of dat een probleem is, hangt af van waar de query voor wordt gebruikt.

Gebruik de server voor queries waarvan het resultaat de volledige wereld moet weerspiegelen, bijvoorbeeld een raycast die controleert of de speler zicht heeft op een verre doel.

Andere patronen

De volgende patronen kunnen ook van toepassing zijn en moeten zorgvuldig worden overwogen:

  • Een Sound of AudioPlayer die aan een 3D-object is gekoppeld, stopt wanneer dat object uitstreamt. Voor ambient audio die moet blijven bestaan, koppel de emitter aan een persistente model of aan een niet-streaming container.

  • In-game UI objecten zoals BillboardGui of SurfaceGui evenals visuele effecten zoals Beams of Highlights waarvan de adornee of bevestiging uitstreamt, stoppen gewoon met renderen. Dit kan het beoogde gedrag zijn, maar je moet het verifiëren.

  • BasePart.Touched evenementen, ProximityPrompts, DragDetectors, en ClickDetectors werken niet voor spelers wiens client het bijbehorende deel/model niet heeft gestreamd. Als interactie mogelijk moet zijn vanuit elke afstand, moet het model persistent zijn of moet de interactie een ander mechanisme hebben.

  • Voor PathfindingService en client-side padfinding, ziet de padvinder alleen gestreamde geometrie op de client en kan het door obstakels routeren die op de server bestaan. Voor strategieën, zie Pathfinding - Strategieën voor strategieën.

Realistische testomstandigheden

Zodra scripts zijn bijgewerkt, test het spel grondig. Streaming bugs manifesteren zich vaak alleen aan de randen van het gestreamde gebied of tijdens overgangen, dus alleen testen nabij spawn of op doelradius is niet voldoende.

  • Test met Workspace.StreamingTargetRadius ingesteld op de minimale waarde (64). Sommige streaming bugs verschijnen alleen wanneer het gestreamde gebied klein is.

  • Speel door de volledige traversiepatronen van het spel, teleport tussen verre gebieden, en bezoek gebieden opnieuw nadat je ze hebt verlaten. Dit zijn de situaties die het meest gebruik maken van stream in en stream uit.

  • Gebruik de streaming debug overlay om de actieve streaminginstellingen, momenteel geladen regio's en runtime streamingstatus te monitoren.

  • Kijk naar het Output venster en de Developer Console voor fouten, aangezien veel van de script patronen fouten produceren in plaats van stille misgedragingen. Let vooral op fouten van de vorm attempt to index nil with ... die vaak wijzen op een ontbrekende WaitForChild() aanroep.

  • Equip en activeer Tools, vuurt wapens af en activeer verschillende game-interacties.

AI streaming conversie vaardigheid

Om te helpen bij streaming conversie en optimalisatie, biedt Roblox een AI streaming vaardigheid die je spel evalueert, aanbevolen configuraties toepast en compatibiliteitsproblemen oplost, inclusief:


Om de AI vaardigheid in je spel te gebruiken:

  1. BELANGRIJK
    Maak een back-up van je spel. Het conversieproces kan complex zijn, dus je moet altijd een back-up opslaan (Bestand ⟩ Publiceer naar Roblox Als) voordat je de vaardigheid uitvoert.

  2. Je kunt deze vaardigheid rechtstreeks in Assistant uitvoeren of met behulp van een LLM naar keuze via het Model Context Protocol (MCP) in Studio. Hogere AI-modellen met grote contextvensters worden aanbevolen; voor een typische conversie kan een frontier-model 20-30 minuten duren en ongeveer 200.000 tokens aan context gebruiken.

    1. Open je spel in Studio.
    2. Open Assistant Instellingen ⟩ Vaardigheden en zorg ervoor dat rbx-convert-to-streaming is ingeschakeld.
    3. Vraag Assistant (of je LLM verbonden via MCP) om de vaardigheid te gebruiken.
©2026 Roblox Corporation. Roblox, het Roblox-logo en Powering Imagination behoren tot onze geregistreerde en niet-geregistreerde handelsmerken in de VS en andere landen.