Previously, in August 2020, we introduced some changes to the non-ReplicatedFirst loading order in this post: Changes to Non-ReplicatedFirst Loading Order. Due to issues we discovered with this change, we disabled it temporarily. We are excited to inform you that we are ready for these changes to go live once more!
Information from the post above is copied and pasted below for your convenience:
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.
The upcoming change to game join processing 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 → 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() ) before game.Loaded fires
- Add game.Loaded:Wait() in strategic places in your code to postpone work until the whole game has finished loading
Again, 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 January 19th , 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.
Questions asked Previously:
- Do we now need to use WaitForChild on descendants of ReplicatedFirst from ReplicatedFirst? I believe previously they were always available.
This change will have no impact on the contents of ReplicatedFirst
- Is this only effective for ReplicatedFirst code trying to access items in other services? Will code that, say, runs in PlayerScripts (protected by game.Loaded) be required to use WaitForChild against instances that are placed in Studio?
This will only affect the initial game load (before game.Loaded). So you only need to be concerned with scripts in ReplicatedFirst interacting with content outside of ReplicatedFirst.
Functions such as GetChildren() or GetDescendents() DO NOT AUTOMATICALLY CALL WaitForChild().
The presence of one child DOES NOT GUARANTEE the presence of any of its siblings. You must call WaitForChild() on each child you require for a given script.
Again, for visibility: We intend to flip this on in studio during the day on January 19th , and to enable for all game clients at some point after that (pending results).