Player instance now created on server instead of client

I don’t believe that’s the case. Local scripts don’t run until the game has been fully replicated to the client. If the server’s still sending game data to the client for the initial load, the scripts will not start until that’s finished (unless your script is in ReplicatedFirst).

1 Like

If I created NicePart in studio, then I would have zero problem indexing it as normally (workspace.NicePart). I never have. This changes that, and I have problems with the OP saying this is an invisible change that developers won’t notice.

I believe the OP was saying that in LocalScripts you should write game.Workspace:WaitForChild("NicePart") when writing code for production ( players joining games ). You can continue to use game.Workspace.NicePart while in studio or in places where you know the object exists.

I think that’s what he was saying too – which implies a very big change from the status quo. What the OP said implies that LocalScripts will begin to run immediately after they are replicated, which is troubling. There’s no reason to make that change since we have ReplicatedFirst anyways. I’m hoping OP just made an error in his example. Roblox has no reason to change this behavior so late in the platform’s life – especially when it’s just a major inconvenience and provides no benefit to the developer.

1 Like

From how current things are, yes, the client is able to modify workspace to a full extent (even if people on other clients won’t see the changes) due to workspace copying over to the client; however, if workspace would be fully ran by the server and not duplicated over to the client when players join, clients would only be able to add parts so only they will see them and can only remove/modify parts they’ve added themselves, so localparts would still work.
This is based off of assumption this will happen the way I’ve described it. I might have gotten offtrack a little bit, but this mechanism they’re adding has tons of potential.

LocalScripts already, to this date, run as soon as they are replicated. This is always how it has been.

1 Like

From the sounds of it, this feature only affects people who are doing loading stuff at the very beginning of a play session, when the place is being loaded by the client.

Can you give insight on the necessity of using :WaitForChild() in local scripts with the following initialization conditions?

  • StarterPlayerScripts
  • StarterCharacterScripts
  • ReplicatedFirst
  • StarterGui
  • Local script delivered to client when server script detects player joining
  • Local script delivered to client when character is created
  • Local script delivered to client when character touches a part

So what did you mean by your security comment? What you described is already how it works. There’s no way for a client to add new parts to the Workspace with or without this change.

That’s not what’s being implied. Refer back to the answer on whether we have to WaitForChild on parts created in studio.

If my assumption about the implications are wrong, the opposite means the client can never know if the game is completely loaded – there is always uncertainty about a part being replicated during the entire play session.

I’m more-or-less asking, in a kind of roundabout way, if there is any point at which we can be certain that parts are replicated.

If I read your question right: if you should use WaitForChild() for that list of objects,

StarterPlayerScripts is a service, and is initialized before any LocalScripts run. It can be indexed with game:GetService("StarterPlayerScripts").

Same with StarterCharacterScripts, and ReplicatedFirst, and StarterGui.

However, children inside of those services aren’t guaranteed to be replicated before any LocalScripts initialize, so it is best to use game.StarterPlayerScripts:WaitForChild("NicePart")

LocalScript delivered to client when ServerScript detects player join: The LocalScript will run as soon as it’s sent to the client (maybe it is inside of PlayerGui, etc). In theory, it should be sent only after everything else has replicated (because objects/property changes are replicated in the order they were made, however the initial join can be necessarily random), but I would not rely on this because this behavior can change. Use :WaitForChild() for anything replicated from the server.

Same with Character created, and when character touches a part.

Does that answer your question? Sorry if I misunderstood.

A test done with a LocalScript in ReplicatedFirst, StarterGui, StarterPlayerScripts, and one in a server script that is cloned into the player as soon as they join with no delay, done in a place with 67k+ parts: image

print("ReplicatedFirst Loaded", game:IsLoaded())
print("ReplicatedFirst Map", workspace.Map)

image

All scripts other than the one in ReplicatedFirst can access the Map (a model with the parts in it) with the dot accessor syntax and report the game as being loaded.

These LocalScripts don’t start running until the game is loaded. If I’m making some invalid assumption here then I’d love to learn where I went wrong, but from what I can tell, they just don’t run until the game is ready (they may be replicated, but they don’t get cloned into the Player object until the client is ready)

1 Like

The OP @KnightTakami liked my post

So I assume it is correct.

But like I said, it is not guarteed that LocalScripts will run before everything else is replicated, but it is certainly still possible. Your test needs more stress, like 12+ players in the game moving around, etc.

2 Likes

I’m sorry that I wasn’t very clear. I was asking if Local Scripts that began life in those ways had any benefit of using :WaitForChild() versus :FindFirstChild().

For example, the following script

local a = workspace:FindFirstChild("NicePart")

is placed in various locations or delivered in various ways to the client:
image

My hypotheses are the following:

  • The script will not find NicePart if it starts in ReplicatedStorage
  • The script may not find NicePart if it starts in StarterPlayerScripts
  • The script will find NicePart if it starts in StarterCharacterScripts
  • The script may not find NicePart if it starts in StarterGui
  • The script will find NicePart if it is delivered to the client when the server detects the player object was added to Players
  • The script will find NicePart if it is delivered to the client when the server detects the player’s character is added
  • The script will find NicePart if it is delivered to the client when the server detects a player has touched a specific part.

Or, in other words, is there ever a point at which the client has fully loaded the game, and is there a distribution method that distributes local scripts after this point?

Out of interest, does this have anything to do with any planned performance upgrades for the :LoadCharacter() method?

1 Like

That would be cool. But my first assumption is that it’s for the updating the way players’ join data works, so that we don’t need to rely on trusting the client.

1 Like

This thread is public and the old behavior is still enabled, so engineers can’t go into specifics, but the change is necessary for security reasons. It also fixes a few unrelated bugs like the playerlist showing Player instead of Player1/etc in test servers, and is a prerequisite for fixing some deeper-rooted bugs as well.

It’s unfortunate that some games may be impacted, but specifically for the security-related reasons it’s necessary. On the bright side, the impact this has on games sounds worse than it is. Roblox did their due diligence and tested the changes against a number of top games to confirm that there weren’t any problems. That being said, you should still make sure you’re using WaitForChild appropriately in your games, as replication order isn’t guaranteed and any number of changes could potentially break your game if you rely on it.

8 Likes

So, I’ve seen Sharksie’s post spread around a lot as some rules of thumb for using WaitForChild. Since this post appears to be incorrect based on what I’ve learned from @alexnewtron and OP, does that mean that the assumption that an object’s children will be present is also false?

If an object exists in Workspace, will the object’s children be there, or do those have a potential to load in at a later time? So do I need to nest WaitForChild indefinitely for every object I want, or only the root container (like accessing a part from a Model, is workspace:WaitForChild("Model").Part sufficient)?

Another Roblox staff member confirmed to me that when using require with an asset ID, all of its children will be guaranteed to be loaded before the ModuleScript runs. Is this the only place where that paradigm exists, or does it also extend to normal require calls?

The UserId replication was patched a long time ago (~2015).

I’ve been chatting with OP privately, and he tells me that what I’ve said in this post is correct. LocalScripts will run immediately after it is replicated to the client, no matter the state of the DataModel (game).

Services exist immediately, but its children are not replicated until anything inside ReplicatedFirst replicates. LocalScripts inside RF will run immediately while other objects are downloaded into all the other services.

LocalScripts inside of StarterPlayerScripts (as an example) run as soon as they are replicated, and can be replicated before anything in Workspace, etc is replicated.

4 Likes