Updates to Streaming Enabled

Hello Developers!

Following up on our March post on the current state of Streaming, we wanted to give a big thank you for all the great feedback and to provide an update per those comments, critiques, and bugs that you’ve brought to our attention.

Let’s dive in.

In Development :building_construction:

Here are a few improvements that we hope to deliver this summer:

  • Model:GetPersistentPlayers
    • You will be able to use this new call to find all players that a particular model is persistent for.

  • Improved Model Streaming Behavior
    • We are working on improvements to how models are streamed to help reduce the need for WaitForChild and speed up joins without needing to explicitly make models atomic.

  • Performance and Memory Improvements
    • We are hoping to see faster joins with the Improved Model Streaming from above and other improvements we’re making.

    • Better memory usage for massive worlds (some of these have already shipped).

  • Bug Fixes
    • Level of Detail (LOD) improvements to help with visuals. (In fact, we’ve already shipped a few terrain updates that you might’ve noticed!)

    • We fixed an issue where mechanisms that used JointsService could be broken when streamed out and back in. While JointsService is still deprecated, it should work better with streaming enabled.

    • We are working on a few physics issues when objects are streamed in and out.

    • We are further updating our guides and Engine API to better address Streaming functionality throughout.

Researching :mag_right:

You have highlighted some important issues that we’re actively considering. However, we are still working on determining the most effective solutions for your current and future Streaming needs. In simpler terms, these areas are on our minds and under active review:

  • Excluded Mode
    • The opposite of persistence, we’re exploring the idea of a mode that prevents replication, rather than requiring it.

  • Advanced Level of Detail Improvements
    • We are thinking hard about more seamless Level of Detail transitions so distant objects stream in more smoothly.

  • Use Model Streaming Controls Outside of Models
    • We are thinking about questions such as “What would it mean to bring streaming controls to other instance types, including folders?”

  • More Testing and Debugging Features
    • We’re considering a range of ideas, such as tools for emulating different network conditions and better tools in Studio to help you work with Streaming.

  • Regional Streaming Controls
    • We’re thinking about ways to designate an area and then stream it on demand.

  • Per Model and/or Per Player Radius Controls
    • We are discussing allowing custom stream radii for models and players. Server performance and cost are real concerns with solutions here. We are thinking about this further, but we also hope we mitigate this with improvements in other areas.

  • Per Instance Streaming Controls
    • Some of you want more control over when an instance is replicated to the client. This is a tough one - we hope the need for this is reduced with other various improvements, but we are considering it.

Streaming is the Future

We believe that Streaming is a key part of Roblox’s future. This technology enables massive worlds, improves join times, and helps reduce crashes, especially on lower-end devices. We will continue to invest and improve this technology and respond to your feedback.

We will also start to turn streaming on in Studio templates with the hope that all new experiences in the future will be streaming enabled. In fact, you might check out for inspiration the new Modern City Template which has Streaming turned on - our early tests show join times for this experience to be ~1.4 seconds versus ~3 seconds with Streaming off!

Keep the Feedback Coming!

As always, we appreciate your input and feedback. Please continue sharing any feature requests, issues, complaints, or comments you may have down below!

Thank you!


This topic was automatically opened after 10 minutes.

Really glad as always to see a proper follow-up to our requests.

I’m however surprised to see that after all this time, Roblox is still not considering a :WaitForDescendant() method; especially when we’re forced to chain several :WaitForChild() operations without possible recourse to a short-circuit operator.


Just because we didn’t mention a change in this post, such as something like WaitForDescendant, doesn’t indicate that we aren’t considering it or other options. The topics listed in this post weren’t intended to mention every option under consideration, or even every concern raised in previous feedback posts.

Having said that, using atomic models is one way to reduce the need for chained WaitForChild calls, but we are looking into other options. And obviously atomicity isn’t appropriate in all situations.


I’d like to start off by saying - absolutely lovely how transparent you guys are! showing what you plan on working as well as consider working on is incredibly helpful to gauge and plan into the future.

Regarding per-instance control, I believe my (and likely many others) request from this derives from the uncertainty of how streaming works internally. Consider the following two scenarios:

  • A small prop is completely contained inside a larger prop, such as a vase within a house. It’s streaming range should thus be affected accordingly to only replicate when in very close range, though I don’t believe this to be the case currently. Roblox wants to automate most of these issues from the player, but this seems hard to do considering edgecases with e.g. windows or transparent walls.
  • Deriving off the first point, and this is moreso of a question, is model size considered for streaming? that is, do ‘minor’ and less important props such as flowers get streamed out faster than trees and buildings?

Will there be an option to only select specific folders rather then having the entire workspace streamed?

aswell as the option to focus on the playercharacter, playercharacter and playercamera, or just playercamera?

really looking forward to see the possibilities with SE in the future!


Bug Fixes

  • Level of Detail (LOD) improvements to help with visuals. (In fact, we’ve already shipped a few terrain updates that you might’ve noticed!)

We have noticed a few changes to terrain LOD’s recently yes…
I’m part of a team that makes a combat flight-sim game where we use Roblox terrain for all our maps because of its ease of editing and comparably excellent visual fidelity.

About last week we noticed that the specular/roughness textures on the terrain now load out with distance, which for us results in super jarring “chunks” of different colored terrain. :confused:

On top of this, we’ve noticed much worse visuals with our terrain overall which is really disappointing for us and our players considering how well the previous LOD settings we working for us.

So our question is: can we expect more LOD controls specifically for terrain and terrain textures?



The only reason I want streaming for my game is to quicken the loading speed of large Terrain pieces, but constantly streaming voxels in and out for 60+ players can overload the network and cause terrible ping spikes. Are there any improvements coming to how terrain is handled with streaming? It would be nice to have a way to publish a terrain so that it loads from a CDN rather than directly from the game server. It seems a bit silly to constantly need to transmit voxels for a terrain that’s static. I am targetting large playercounts of 100+ and I found that Streaming can cause a terrible latency for all players due to the amount of objects being transmitted.


Good to see engine performance being worked on, However…

I did some performance testing with Modern City Template. I wanted to check how well engine can handle detailed worlds.

I duplicated the entire city 5 times and placed them next to each other.
Even with streaming enabled, performance was terrible, CPU usage was over 100 ms, and most of the time I was getting barely 15 fps.

Keep in mind that the map wasn’t as big as it sounds, it was about 4k on 4k studs (with all the cities next to each other.

Then to further test studio performance, I deleted from the game all of the scripts, surface appearances, textures, decals, particle emitters, sounds, proximity prompts, trails, beams, surface guis, all the lights (pointlight, spotlight, surfacelight).
I also turned off CastShadow, CanCollide, CanQuery and CanTouch for all the parts and meshes, removed Unions, and anchored everything.
Changed the lighting technology to “Voxel”.

Even after this the performance was still exactly the same, barely 15 fps, both with streaming enabled on and off.

Sure, join (loading) time is extremely fast, however that is not at all the most important factor in performance. The above test showed that we unfortunately cannot build detailed and massive worlds, no matter how hard we optimize.

This is true also for small, but detailed worlds. Even roblox showcase games (Beyond the Dark, Duvall Drive), have extreme amount of lag.

Will this change anytime soon?


Adding on to this:

The current LoD is unacceptable for large worlds where terrain is a vital part of the gameplay.

In our game Glacier we have vehicle and infantry warfare, and this kind of terrain distortion ruins the possibility of long range combat or open fields.

Additionally, streaming takes 4 seconds (yes, 4 whole seconds) to load in the terrain when teleporting to different areas of the map. Faster join times are good, but not at the cost of making the game unplayable.

These features are also still very much needed:


THANKS U, we don’t need to manually fix A-Chassis anymore!!


Here’s my attempt at doing what you said, I tried to copy the errors and behavior the WaitForChild function has:

function WaitForDescendant(parent: Instance, name: string, t: number?): Instance?
	if parent == nil then error("Argument 1 missing or nil") end
	if name == nil then error("Argument 2 missing or nil") end
	if typeof(parent) ~= "Instance" then error("Argument 1 must be an Instance!") end 
	name = tostring(name) 
	local descendant = parent:FindFirstChild(name, true)
	if descendant then return descendant end
	if type(t) ~= "number" then t = 5 end 
	local start = os.clock()
	local result = nil 
	local connection: RBXScriptConnection
	connection = parent.DescendantAdded:Connect(function(descendant: Instance)
		if descendant.Name ~= name then return end 
		result = descendant 
	repeat task.wait() until result or os.clock()-start > t 
	if not result then 
		warn("Infinite yield possible on '"..parent.Name..":WaitForDescendant(\""..name.."\")'") 
	return result 

Not sure which one, but one of these is an issue with my game, Bloxy Kart in the Race place. Turning on StreamingEnabled completely breaks the Kart system probably because it uses legacy joints and Body Movers. I unfortunately tried converting them to the new system but it has not worked out well. As soon as these fixes ship, I will enable StreamingEnabled in the beta version of Bloxy Kart!


one liner “WaitForDescendant”

repeat task.wait() until workspace:FindFirstChild("Object",true)

you can also

repeat task.wait() until workspace:FindFirstDescendant("Object")

and its the exact same thing both of those search for the descendant


Uhhhhhh that’s not really good for performance but, ok, it works I guess! :person_shrugging:


The post is a bit old, but the problem has reappeared lately


Thanks for taking the time! I’m aware that there’s a way to create a function that does this. For the record, here’s how I implement it when I need it:

local function WaitForDescendant(Ancestor, Name)
	assert(typeof(Ancestor) == "Instance", "Ancestor is not an Instance")
	assert(type(Name) == "string", "Name is not a string")
	local Descendant
		Descendant = Ancestor:FindFirstChild(Name, true)
			or Ancestor.DescendantAdded:Wait()
	until Descendant and Descendant.Name == Name
	return Descendant

Thanks for taking the time to reply! First of all it’s worth noting that FindFirstDescendant has never been enabled.

Second of all, these methods require polling, which is inefficient, and they don’t support a timeout. To circumvent that, other similarly inefficient methods must be used. I’m advocating for a better, engine-implemented way.


This especially, is awesome. I’d really want to make this a setting in my game or have it as a script-controlled automatic setting for players with different hardware and network conditions.

By the way wouldn’t it help the server performance more than hurting it? If I have 20 players with 256 min. streaming radius vs 10 with 256 but 10 with 96 for example.

While I’m here I’d like to give some feedback:

  • There’s a bug which results in terrain loading spiked (with deformed triangles) if streaming radius is less than 96. It happens with 96 and 64 and doesn’t happen with 128 min. streaming radius, I think this is a known issue, is a fix for this on the way?

  • I use a system where elevators teleport to upper floor or another terrain piece. Players can use it together so I can’t yield the elevator for player loading, if I don’t though, some players just fall off of the map while loading. I have to use some sort of invisible local part tricks to fix this, maybe the collision data should be provided earlier than terrain textures or I’m sure Roblox has a better solution, just wanted to give feedback on this.


well I guess use the FindFirstChild(“name”,true) method (its alternative of FindFirstDescendant when you pass the second argument as true)