How to know when a model has fully loaded

Hey guys, I am parenting a large model with many subcomponents from ServerStorage into Workspace and essentially I want to wait until the entire model has been replicated to the client before executing code.

I know that if I use WaitForChild on the model, this does not guarantee that the children of said model have also replicated, as outlined by this recent post from roblox staff: Changes to Non-ReplicatedFirst Loading Order

I also know that game:IsLoaded() only works for knowing when everything is loaded on the client initially, aka when the player first joins the game: DataModel | Documentation - Roblox Creator Hub

So, is there any way I can ensure that my code executes only after the entirety of the model has replicated to the client after being moved from ServerStorage to Workspace?

4 Likes

Have you tried using :GetDescendants on the serverside and then passing the number of descendants over on a RemoteFunction?

When the client receives the remotefunction it will create a connection that simply counts a value that’s 0 by default and do +1 on DescendantAdded until it has met the initially passed number, which at that moment, the connection would disconnect.

Past that, the only real checks you’d have to do would be for types of instances that contain asset URL’s, which I’m not too sure of yet on how to deal with.

Sounds and animations would simply require you to check if their durations (TimeLength, Length) are more than 0. Textures I’m not sure of yet.

15 Likes

Wow, that’s really hecking brilliant. Well done.

1 Like

I do something similar to this, but I don’t rely on the the DescendantAdded function because its frankly random.

I use a NumberValue on the parent mesh with the value of #GetDescendants() in it from the server, and check #GetDecendants() on the client.

1 Like

Hey, I figured this out last week, but there’s actually a perfect way to figure out exactly when ANY model gets replicated to a client:

On the server side, you parent the model in ServerStorage to Workspace, and right after that operation (with zero delay), you also fire a remoteevent. Now, on the client side, you listen for the remoteevent, and as soon as the remoteevent signal arrives and OnClientEvent is fired, you know 100% that the entire model has been replicated.

Why is this the case? I found this behavior on accident, and it turns out that in the list of things that can be replicated to the client, the replication of models takes TOP PRIORITY! So, if you fire a bunch of remotes while a model is still being replicated to a client, the client will hold onto all of those remotes but wait until the model has finished replication before firing the OnClientEvent event.

Here’s an extremely easy way to test this:
-Create a server script which fires a remoteevent each Heartbeat, and on the client, create a localscript listening to OnClientEvent and make it print something every time the remote event is received.
-Then, create a separate server script, wait a couple of seconds, and then parent a really large model from ServerStorage to Workspace.
-Now, in Play Solo, watch the client output and observe that your print statement is firing basically every frame; but, at the exact moments the model is being transferred from ServerStorage to Workspace, all of the print statements will stop and only resume until the model is done replicating.

14 Likes

That’s cool!

The drawback is if you think of the case where clients join after you’ve already sent that remote event.

This is why I switched to the method of embedding client-side meta data about models into StringValues and NumberValues, so I don’t have to worry about telling clients who join later about it, or if they move into streaming radius later.

Well, in the case of a client joining after that remote has been sent, that would mean the model is already put into workspace. I believe localscripts do not begin executing until everything in workspace has fully loaded for the first time, though I’m not sure. You could always wait for game:IsLoaded() as a backup.

No, they definitely start executing long before everything is loaded :smiley:

Streaming makes it even more obvious.

That’s a sneaky way to use replication order. I was looking for something like this, hopefully it doesn’t break in the future. Thanks for the help

1 Like