Changes to Sibling Instance Ordering Sent at Game Load

Greeting Developers,

There are some more changes coming to non-ReplicatedFirst loading order, and we want to explain the potential impact they may have on your games before they go live.

After the previous update, child instances sent during game join will arrive on the client in the correct relative order, but there may be an arbitrary number of other instances sent between each child.

Now, child instances sent during join will no longer have an order guarantee on the client: they will arrive in arbitrary order, and the order of children will be arbitrary.

Here’s a basic example that illustrates this change:

Server Workspace structure

Workspace

→ Part1

→ Part2

→ Part3

What the client might see

Workspace

→ Part2

→ Part1

→ Part3

We have updated existing engine logic (like that in the UI code) to compensate for this, but there is still a potential for disruption to your scripts.

Script

local superImportantPart = workspace:FindFirstChildWhichIsA("Part")

Before this change, this script would find Part1 reliably on the client. After this change it might find any of the parts, depending on what order they arrived at the client. If your script needed to find Part1 specifically for some specific game logic, that logic may break.

Similarly, some Scripts which call functions such as Instance:GetChildren() may break if they depended on the instances being reliably in the same order.

Pre-Launch Studio Testing

In order to help you determine if your game has a bug like the above example, we will once again be enabling this behavior for a period in Roblox Studio only before enabling for all live games. We have worked with our internal QA team to try out this new feature on a representative sample of games and have found no issues yet, so we expect most games to not be negatively impacted.

To make it easier to find bugs related to child order we have added a new studio setting that aggressively randomizes the order clients receive instances during join, and this setting will be enabled by default.

Advanced developers can toggle this behavior under File → Studio Settings → Network → Advanced → Randomize Test Join Order. Unchecking this box will make it harder to find any bugs in your game related to this change.

We intend to enable this on Studio on March 3rd, and will wait ~3 weeks to give you a chance to fix any lurking bugs before enabling this on Production.

Thank you, and please let us know if you have any questions regarding this change!

Update Regarding Launch

97 Likes

I mainly have one question.

What was the point of this?

Even if this doesn’t affect many games (which I doubt), why change this? Is there any noticeable benefit?

Also typo:

10 Likes

Does this only apply to when the game is initially loading? It would be pretty annoying if it stays out of order, since a display of a queue in one of my projects relies on this.

Why roblox why this shows me that roblox is just putting out some useless updates that break games for no reason! Like am i the only one here who is confused on why this was made.
EDIT:

1 Like

Thanks for the find!

The reason for this change is that it allowed us to make other changes to the Game Engine which improve game join processing.

13 Likes

Such as what? I kind am of Curious.

So is this improving performance? It’s a bit unclear what the actual reason behind this is, some clarification would be very nice.

3 Likes

Are there any other services than ReplicatedFirst that will replicate in some specific order (for instance, ReplicatedStorage before Workspace), and will this update change the order those services replicate? Or instead will only change the order that the items within that category replicate to the client?

Also, with the new changes to :WaitForChild and now this, it would be super useful to have a :WaitUntilLoaded() function that will wait until each descendant has been successfully loaded into the given object from the server. That way we can avoid a million wait for child’s and all that.

2 Likes

I think improvements to the game processing system will have nice long term effect, considering with every update people push the game past its limits. However how much of a performance increase will this generate?

Specifically, we are targeting improving game join processing times, both on the Server and Client side. This is part of an ongoing effort by Roblox to improve the Game Join experience, much like the recent previous change outlined in this post: Return of Changes to Non-ReplicatedFirst Loading Order.

Some improvements that this change helps bring about are highlighted here: Return of Changes to Non-ReplicatedFirst Loading Order - #13 by LordRugdumph

14 Likes

In at least two of my games, I have specifically-named instances in Workspace that my LocalScripts depend on. Since characters also exist in Workspace with their players’ names, there’s a chance that an oddly-named player can disrupt these LocalScripts. For example, “Multiplayer” in Open Flood Test, and “Mine” and “StarterChest” in ForbiddenJ’s Quarry. There are likely other workspace dependencies that I didn’t mention.

If players with these exact names join the game, players that join afterwards may have script failures because their LocalScripts are accidentally grabbing references to those characters instead of their intended targets, because those characters have the same name.

Historically, I didn’t have to worry about this because instances were sent in order (with StreamingEnabled off) and these scripts always grabbed their intended targets.

Are there any recommendations for accounting for this?

6 Likes

I’m fairly certain this has been known to bad practice, I hope people aren’t doing this in the current year.

Awesome, this is what I like to hear :sunglasses: keep up the good work with engine updates

1 Like

I can think of two methods for circumventing this:

  1. Call Players:GetPlayerFromCharacter (roblox.com) and see if it’s returning nil AKA the instance you’re expecting. If not then keep searching for it
  2. Use a special character in the instance’s name, such as :heart: AKA '\03'. This is something that I’ve done without issue and is the least resource intensive way I can think of going about it

Also there is CollectionService (roblox.com)

3 Likes

I think this is a really good change, even if it ends up breaking games. Programmers should not be relying on arbitrary order of instances and instead should use things like CollectionService and FindFirstChild. To be honest, I wasn’t even aware that Roblox guaranteed the same instance order on all machines.

8 Likes

You should probably prefer to use folders to contain critical instances instead. The likelihood of a user joining your game with the same name as the critical folder is very low if the user already exists, and otherwise you can just claim the account if you’re worried.

You shouldn’t really have anything in workspace other than containers and parts and other rendered things, scripts should almost never be in workspace, and if there are there is certainly a better solution (e.g. collection service and a batch processor).

4 Likes

Perhaps run an if statement that tries to find a humanoid as a child, if it does, that instance is ignored?

Is there anything being worked on to give developers manual control over replication of instances? There are many cases where I want to have instances in workspace on the server but not have them be replicated to the client, cases where I want to replicate to just a single client etc. The current networking API is very lacking and needs to be improved

2 Likes

For some reason this update is live in my game, and my game has been completely broken for the last 3 hours (Home Tycoon 2.0 🏡 [CARS] - Roblox).

This line of code breaks a very important LocalScript
local collectGui = p:WaitForChild("PlayerGui").Collect

you can mend these errors by using WaitForChild again, like so:

local collectGui = p:WaitForChild("PlayerGui"):WaitForChild('Collect')