Player instance now created on server instead of client

This is already what you should currently do. All the post did was remind that this is the best practice to use in local scripts.

Both now and after this change is live, you can’t guarantee anything exists yet on the client by the time your script tries to access it. The only change whatsoever happening here is that the player object will be created on the server after the change is live.

When in doubt, use WaitForChild. It is impossible to say with 100% certainty that an object will be there when you directly index it.

1 Like

I made a typo and wrote ReplicatedStorage instead of ReplicatedFirst, but I am confident the answer is “no it will not find NicePart”

What about Character, all the example scripts you see will use game:GetService(“Players”).LocalPlayer.Client
If you use a WaitForClient() I get an ‘infinite yield’ error.
Most of the time I will do… while not LocalPlayer.Character do wait() end

So what is the actual, correct and proper way to handle Player.Character, on the local side?

Yes, and that’s one point where it gets confusing. It is important to remember that scripts run depending on where they are located. Theoretically, a LocalScript might replicate and then begin running immediately. In most cases however, any container where they could replicate is a container where they can’t run (StarterGui, StarterPlayerScripts, almost everything, really). And, for any container where they can run (PlayerGui, etc), scripts are copied from the respective Starter container (StarterGui, etc) only after game.Loaded is set to true.

This is why I was particular about how step 7 was worded. It doesn’t say right out that LocalScripts become enabled. Rather, it is the Starter containers that depend on game.Loaded.

If you wanted, you could use a ReplicatedFirst script (which runs early) to insert another script into a script container, which would cause it to run, even if the game hasn’t finished loading. The container itself doesn’t care about game.Loaded, so the script runs unconditionally. Starter containers, which copy contained objects to their respective script containers do care about game.Loaded.

Main points

  • Script containers run scripts unconditionally.
    • Script containers include PlayerGui, PlayerScripts, Backpack, and the player’s character.
  • Each script container is created on the fly, so they and their contents may or may not be included in the DataModel snapshot.
  • Starter containers copy objects to their respective script containers.
    • Starter containers include StarterGui, StarterPlayerScripts, StarterGear, and StarterCharacterScripts.
  • Starter containers will start copying only after game.Loaded is true.

Conclusions

  • LocalScripts are not inherently protected by game.Loaded.
  • LocalScripts managed by Starter containers are protected by game.Loaded.
  • LocalScripts managed by other means (e.g. server script, ReplicatedFirst script) may not be protected by game.Loaded.

If the LocalScript is managed by a Starter container, and the BasePlate always exists, then WaitForChild does not need to be used.


All my information is based off of observing how the client behaves. Take that as you will.


How do I sign up?

10 Likes

This is what I wanted answered this whole thread. My scripts shouldn’t be affected by this. I feel the OP should’ve made this more clear, it would’ve cleared all this confusion.

Agreed, this was my issue as well. Everything posted was extremely ambiguous up until Anaminus’ post.

1 Like

Just as a heads up, to add to what @Anaminus is saying above (which I believe is correct):

The earlier version of this change (which was current when this thread was made) did invalidate an implicit contract about LocalScripts accessing existing content in game. Specifically, because of how the change affected PlayerGui replication, if you did not use StarterGui container and instead parented LocalScripts to PlayerGui on the server, the change would’ve replicated these parts of PlayerGui before Workspace, thereby breaking some Workspace accesses.

We are revising the change based on testing & feedback to not do this. The new version of the change would create Player on the server, but only replicate contents of PlayerGui and other descendants after game.Loaded, similarly to what happens right now.

New version of the change shouldn’t have any observable behavior changes wrt replication timing; we’ll still announce it when we enable it - it’s hard to anticipate all consequences of a change like this - but that’ll happen after we make sure we don’t have any known instances of games changing behavior.

Sorry about the confusion :slight_smile:

16 Likes

Wanting to note that until the Player’s character has spawned. NO contents from StarterGui will be replicated to PlayerGui. This breaks my game as the Player’s character is only spawned upon being requested, and causes all of my PlayerGui:WaitForChild()'s to time out because the contents simply do not exist until the server has spawned the Player’s character.

Is this intentional or a bug? @zeuxcg

What do you mean by “breaks my game”? Are you saying that this used to work and is currently broken on production, or are you saying that this behavior gets in your way and you’d like it changed, or something else?

I believe that this is intentional for CharacterAutoSpawn=True; for CharacterAutoSpawn=False it’s an unfortunate side-effect. We wanted to have special logic to start PlayerGui copying process on game.Loaded instead when CharacterAutoSpawn=False, but this can negatively impact games that rely on the current behavior - so we can’t easily change this now.

1 Like