Hi Developers,
There are some changes coming to the non-ReplicatedFirst loading order that we want to walk you through before they go live.
ReplicatedFirst
exists as a means for game creators to create loading screens and otherwise manage and optimize game loading. The order and timing of the arrival of the rest of the instances is not guaranteed, so it is expected for developers to use WaitForChild
to determine when parts of the game have loaded.
If you want to read more about best practices for setting this up, here are two helpful DevHub articles about using ReplicatedFirst and WaitForChild.
The upcoming change to game join processing that will improve how these operate, but it will (as a side effect) re-order most of the instances received during join. Games that fully use WaitForChild
in scripts running in ReplicatedFirst
will not see any negative impacted by this change.
Before this change, the sending strategy would tend to send parents and their immediate children close together. This meant that, even though it was not officially supported or guaranteed, sometimes if you called WaitForChild
on some Model/Folder/etc, that WaitForChild
might return after that child plus some descendants had all loaded.
NOTE: If your game does not explicitly use WaitForChild
for every instance that you need to interact with while loading then your game may encounter an issue when we modify the send order in this upcoming change.
Here’s an example of something that might break after this change:
Workspace structure
Workspace
→ Folder
—→ Part1
—→ Part2
Script in ReplicatedFirst
local f = workspace:WaitForChild("Folder")
for i,c in ipairs(f:GetChildren()) do
trackingMap[c] = ...
end
Before this upcoming change, this script may get “lucky” and only run after Part1 and Part2 have loaded, after this upcoming change you are much less likely for this to work out. This case looks obvious, but with ModuleScripts
and require()
it is sometimes less obvious when situations like this might arise.
If you do use this behavior, here are two simple ways that you can resolve it:
- Make sure you use
:WaitForChild()
for every object you interact with (even implicitly through e.g.:GetChildren()
) beforegame.Loaded
fires - Add
game.Loaded:Wait()
in strategic places in your code to postpone work until the whole game has finished loading
To help you determine if your game has a bug like this lurking, we will be enabling this behavior for a period in Roblox Studio only before enabling for all live games. We intend to flip this on in studio during the day on Monday August 17th 2020, and to enable for all game clients at some point after that (pending results).
Thank you! And please let us know if you have any questions regarding this change.