| title | Instance streaming |
|---|---|
| description | Instance streaming allows the Roblox engine to dynamically load and unload 3D content in regions of the world. |
In-game instance streaming allows the Roblox engine to dynamically load and unload 3D content and related instances in the Class.Workspace. This can improve the overall player experience in several ways, including:
- — Players can start playing in one part of the world while more of the world loads in the background.
- — Games can be played on devices with less memory since content is dynamically streamed in and out. More immersive and detailed worlds can be played on a wider range of devices.
- — Better frame rates and performance, as the server can spend less time and bandwidth synchronizing changes between the world and players in it. Clients spend less time updating instances that aren't currently relevant to the player.
- — When configured, distant models, platform avatars, and terrain remain visible even when they're not streamed to clients, keeping the game optimized without entirely sacrificing background visuals. SLIM provides the highest-fidelity level of detail for both models and avatars.
Instance streaming is controlled through the Class.Workspace.StreamingEnabled property, enabled by default for new places created in Studio. This property cannot be set in a script.
Streaming logic and features apply exclusively to instances that are descendants of Class.Workspace, while instances stored in other containers such as Class.ReplicatedStorage and Class.ReplicatedFirst are ineligible for streaming. For example, placing an atomic model under Class.ReplicatedStorage does not guarantee atomic replication.
When a player joins a game with instance streaming enabled:
-
Instances in the
Class.Workspaceare replicated to the client excluding the following:
`Class.BasePart|BaseParts` (`Class.Part|Parts` and `Class.MeshPart|MeshParts`)
`Class.Model|Models` set to [Atomic](#atomic), [Persistent](#persistent), or [PersistentPerPlayer](#persistentperplayer); see [per‑model streaming controls](#model-streaming-controls)
`Class.Model|Models` set to [Nonatomic](#nonatomic) (default) when `Class.Workspace.ModelStreamingBehavior` is set to `Enum.ModelStreamingBehavior.Improved|Improved`
Descendants of the above instances
-
During gameplay, the server may stream instances in the above deferred categories to the client based on the game's streaming properties, player position, client device performance, and other conditions.
During gameplay, a client may remove regions of Class.BasePart|BaseParts from the player's Class.Workspace based on the behavior set by Class.Workspace.StreamOutBehavior. The process begins with regions furthest away from the replication foci and moves in closer, as needed. Regions inside the Class.Workspace.StreamingMinRadius range never stream out.
Note that a Class.Model with no Class.BasePart descendants, such as one used merely as a "container" for non‑Class.BasePart instances like scripts, is exempt from streaming out unless it is made a descendant of a Class.BasePart.
Physical assemblies stream in as complete units, including their associated Class.Constraint|Constraints and Class.Attachment|Attachments, helping to ensure consistent physics updates on clients. The only exception is when the assembly is anchored, in which case only the Class.BasePart|BaseParts within the streaming radius are streamed in alongside their associated Class.Constraint|Constraints and Class.Attachment|Attachments.
Assemblies do not stream out until all of their Class.BasePart|BaseParts are eligible to stream out.
The following properties control how instance streaming applies to your game. All of these properties are non-scriptable and must be set on the Class.Workspace object in Studio.
| Property | Description |
|---|---|
| `Class.Workspace.EnableSLIMAvatars|EnableSLIMAvatars` | Controls whether a [SLIM](./slim.md#enabling-slim-for-avatars) model is generated for avatar characters in the game. When enabled, avatars render using SLIM in the same way that setting `Class.Model.LevelOfDetail` to `Enum.ModelLevelOfDetail.SLIM|SLIM` works for other models. See [SLIM](./slim.md) for details. |
| `Class.Workspace.ModelStreamingBehavior|ModelStreamingBehavior` | Controls how [Nonatomic](#nonatomic) (default) models stream in and out. Use `Enum.ModelStreamingBehavior.Improved|Improved` to enable the most efficient streaming for `Class.Model|Models` with `Class.BasePart` descendants. |
| `Class.Workspace.PredictiveStreamingMode|PredictiveStreamingMode` | Opts in to [predictive streaming](#predictive-streaming) which uses engine signals to proactively stream areas a player is likely to need soon, such as respawn locations or regions the player recently left via `Datatype.CFrame` change. Predictions are additive, expire after a short time if unused, and are skipped on resource‑constrained clients. |
| `Class.Workspace.StreamingIntegrityMode|StreamingIntegrityMode` | The game may behave in unintended ways if a player moves into a region of the world that hasn't been streamed to them. This property offers a way to avoid those potentially problematic situations. Use `Enum.StreamingIntegrityMode.PauseOutsideLoadedArea|PauseOutsideLoadedArea` to balance gameplay integrity without pausing unnecessarily or too often. You can also [customize the pause screen](#pause-screen-customization). |
| `Class.Workspace.StreamingMinRadius|StreamingMinRadius` | This property indicates the radius around the [replication foci](#replication-focus) in which instances stream in at the highest priority. Care should be taken when increasing the default, as doing so will require more memory and more server bandwidth at the expense of other components. Use the default of `64` to maximize how much the engine can scale the game down for low‑end devices. |
| `Class.Workspace.StreamingTargetRadius|StreamingTargetRadius` | This property controls the maximum distance away from the [replication foci](#replication-focus) in which instances stream in. Note that the engine is allowed to retain previously loaded instances beyond the target radius, memory permitting. A smaller `Class.Workspace.StreamingTargetRadius|StreamingTargetRadius` reduces server workload, as the server will not stream in additional instances beyond the set value. However, the target radius is also the maximum distance players will be able to see the full detail of your game, so you should pick a value that creates a nice balance between these. Use the default of `1024` to strike a good balance between visibility for players on high‑end devices and a reasonable memory footprint. |
| `Class.Workspace.StreamOutBehavior|StreamOutBehavior` | This property sets the [streaming out](#stream-out) behavior according to the value of `Enum.StreamOutBehavior`. If set to `Enum.StreamOutBehavior.LowMemory|LowMemory` (default), the client only streams out regions beyond the minimum radius in a low memory situation. If set to `Enum.StreamOutBehavior.Opportunistic|Opportunistic`, regions beyond `Class.Workspace.StreamingTargetRadius|StreamingTargetRadius` can be removed on the client even when there is no memory pressure (in this mode, the client never removes instances that are within the target radius, except in low memory situations). Use `Enum.StreamOutBehavior.Opportunistic|Opportunistic` to allow the client to aggressively garbage collect content, significantly reducing memory usage and helping prevent out‑of‑memory crashes. |
By default, streaming occurs around the local player's character's Class.Model.PrimaryPart|PrimaryPart, although you can specify a different replication focus point through Class.Player.ReplicationFocus.
You can also add and remove additional replication foci through Class.Player:AddReplicationFocus() and Class.Player:RemoveReplicationFocus() to dynamically enable streaming in multiple areas of the game.
On the client, too many foci for a player can limit the engine's ability to adjust to memory limitations and make it more likely for clients to be killed by the OS for using too much memory.
Client-side physics simulation, including prediction and resimulations when [server authority](../../projects/server-authority/index.md) is implemented, only occurs in streamed areas, even for locally created instances and for `Enum.ModelStreamingMode.Persistent|Persistent` instances. If you have instances that you'd like to keep simulating even when they're far away from the character, create an additional replication focus near those instances. In many games, players frequently move back and forth between the same areas, for example between their "home base" and a "trading hub." In such cases, you can create a replication focus point in each area to ensure those areas are readily present on client devices. Multiple replication points are useful when players can view specific, important regions through a scope, such as enemy bases scattered across a barren landscape. In such cases, you can create a replication focus point in each base to ensure players see details and simulated physics from afar.Predictive streaming is an opt‑in feature that uses engine signals to anticipate player movement and proactively stream areas the player is likely to need soon. When enabled by setting Class.Workspace.PredictiveStreamingMode|PredictiveStreamingMode to Enum.PredictiveStreamingMode.Enabled|Enabled, it can reduce streaming pauses and visual pop‑in without any code changes.
Predictive streaming is additive. It creates small, temporary streaming foci in addition to your existing replication foci, streams a small amount of extra content, and does not change your game logic or streaming contracts. If a prediction isn't needed, the predicted area expires after a short time and the engine unloads the content. The engine also takes client memory and performance into account, skipping predictions on resource‑constrained devices.
When Class.Workspace.PredictiveStreamingMode|PredictiveStreamingMode is Enum.PredictiveStreamingMode.Enabled|Enabled, the following predictive features are active:
| Feature | Description |
|---|---|
| Spawn pre‑fetching | When a player dies, the engine creates small, temporary streaming foci at possible spawn locations so that likely respawn areas begin streaming before the player character appears, reducing pauses and missing content immediately after respawn. |
| `Datatype.CFrame` return optimization | When a player `Datatype.CFrame|CFrames` away from an area, the engine creates a small, temporary streaming focus at the location they left. This helps keep that area streamed in if the player returns shortly after, a common scenario when moving between buildings, sublevels, shops, or hubs. |
To avoid issues with streaming on a per-model basis and minimize use of Class.Instance:WaitForChild()|WaitForChild(), you can customize how Class.Model|Models and their descendants stream through their Class.Model.ModelStreamingMode|ModelStreamingMode property.
By default, models are Enum.ModelStreamingMode.Nonatomic|Nonatomic and they stream in/out based on whether Class.Workspace.ModelStreamingBehavior is set to Enum.ModelStreamingBehavior.Legacy|Legacy (default) or Enum.ModelStreamingBehavior.Improved|Improved.
When Class.Workspace.ModelStreamingBehavior is set to Enum.ModelStreamingBehavior.Legacy|Legacy (default), the Class.Model container and its non‑Class.BasePart descendants such as Class.Script|Scripts replicate to the client when the player joins. Then, when eligible, the model's Class.BasePart descendants stream in.
When Class.Workspace.ModelStreamingBehavior is set to Enum.ModelStreamingBehavior.Improved|Improved, model streaming behavior varies by whether the model contains Class.BasePart descendants or does not contain Class.BasePart descendants:
-
A model with
Class.BasePartdescendants streams in only when one of itsClass.BasePartdescendants is eligible to stream in. At that point, the model and the eligibleClass.BasePartstreams in, along with the model's non‑Class.BasePartdescendants.When the very last remaining
Class.BasePartof the model streams out, the model itself will stream out along with it.
-
A model with no
Class.BasePartdescendants, such as one used merely as a "container" for non‑Class.BasePartinstances like scripts, replicates to the client soon after the player joins. This type of model is exempt from streaming out unless it is made a descendant of aClass.BasePart.
If a Class.Model is set to Enum.ModelStreamingMode.Atomic|Atomic, all of its initial descendants are streamed in together when a descendant Class.BasePart is eligible to be streamed in. As a result, a client‑side script that needs to access instances inside the model would need to use Class.Instance:WaitForChild()|WaitForChild() on the model itself, but not on a descendant Class.MeshPart or Class.Part since they are sent alongside the model.
An atomic model is only streamed out when all of its descendant parts are eligible for streaming out, at which point the entire model streams out together.
Enum.ModelStreamingMode.Persistent|Persistent models are not subject to normal streaming in or out. They are sent as a complete atomic unit soon after the player joins and before the Class.Workspace.PersistentLoaded event fires. Persistent models and their descendants are never streamed out, but to safely handle streaming in within a client‑side script, you should wait for the Class.Workspace.PersistentLoaded|PersistentLoaded event to fire.
Models set to Enum.ModelStreamingMode.PersistentPerPlayer|PersistentPerPlayer behave the same as Enum.ModelStreamingMode.Persistent|Persistent for players that have been added using Class.Model:AddPersistentPlayer(). For other players, behavior is the same as Enum.ModelStreamingMode.Atomic|Atomic. You can revert a model from player persistence via Class.Model:RemovePersistentPlayer().
Assuming Class.Workspace.StreamingIntegrityMode is set to the recommended Enum.StreamingIntegrityMode.PauseOutsideLoadedArea|PauseOutsideLoadedArea, the game will pause if a player moves into a region of the world that hasn't been streamed to them. In these cases, the Class.Player.GameplayPaused property indicates the player's current pause state which can be used with a Class.Instance:GetPropertyChangedSignal()|GetPropertyChangedSignal() connection to show or hide a custom GUI.
local Players = game:GetService("Players")
local GuiService = game:GetService("GuiService")
local player = Players.LocalPlayer
-- Disable default pause modal
GuiService:SetGameplayPausedNotificationEnabled(false)
local function onPauseStateChanged()
if player.GameplayPaused then
-- Show custom GUI
else
-- Hide custom GUI
end
end
player:GetPropertyChangedSignal("GameplayPaused"):Connect(onPauseStateChanged)The engine includes multiple on-screen debug panels that can be enabled on the client using keyboard shortcuts. To access streaming debug information:
- Open the Network Summary debug overlay via ShiftCtrlF3 (Windows) or Shift⌘F3 (Mac).
- Once the debug overlay is open, press Shift1 repeatedly to cycle through the available panels. The fourth panel is the Streaming debug view which displays useful runtime information:
- Active streaming settings
- Currently loaded (streamed in) regions
- Streaming behavior and state
Once enabled, colored highlighted regions appear in the 3D viewport:
| Color | Description |
|---|---|
| Less than `Class.Workspace.StreamingMinRadius|StreamingMinRadius` | |
| Greater than or equal to `Class.Workspace.StreamingMinRadius|StreamingMinRadius` and less than `Class.Workspace.StreamingTargetRadius|StreamingTargetRadius` | |
| Equal to `Class.Workspace.StreamingTargetRadius|StreamingTargetRadius` | |
| Greater than `Class.Workspace.StreamingTargetRadius|StreamingTargetRadius` |
Inside of the Streaming debug view, you can see colored highlighted spaces within the 2D Panel UI:
- Regular streaming
- Green: A streamed in space
- Yellow: A not yet fully streamed in space
- Prefetch related, e.g.
RequestStreamAroundAsync- Orange: A streamed in space through prefetch
- Purple: A not yet fully streamed in space through prefetch




