Waits for the localplayer and returns it.
while game.Players.LocalPlayer == nil do
game.Players:GetPropertyChangedSignal('LocalPlayer'):wait()
end
player = game.Players.LocalPlayer
Becomes:
player = game.Players:WaitForLocalPlayer()
Waits for the localplayer and returns it.
while game.Players.LocalPlayer == nil do
game.Players:GetPropertyChangedSignal('LocalPlayer'):wait()
end
player = game.Players.LocalPlayer
Becomes:
player = game.Players:WaitForLocalPlayer()
I think the LocalPlayer is guaranteed to exist when local scripts start running. If this isnât the case, I think we should make it the case. I think the first pattern is only common because we need to do it in the corescripts and that makes other people think that it is necessary.
No one runs code in LocalScripts anymore. Itâs all in ModuleScripts, which are generally shared by both server and localscripts. So when the modulescript runs it needs to check if itâs in play solo or the client, then wait for the local player.
Thatâs cool but I run stuff in local scripts.
The top of all my local scripts uses my favorite line
repeat game:GetService("RunService").RenderStepped:wait() until game.Players.LocalPlayer ~= nil
I was thinking about writing a plugin to insert this into new localscripts but I think Iâll make it use @Sharksie 's more modern version
I also need to be able to determine whether a modulescript is being run locally or on the server.
Iâve never ran into a situation where client-running code had a nil LocalPlayer
. But I do agree with being able to tell environment from ModuleScript. Last time I suggested it though, it was kinda shot down.
My local code always starts with this:
repeat game:GetService("RunService").RenderStepped:wait() until game.Players.LocalPlayer.Character ~= nil
And yes, I know I couldâve just left out the last part (it triggers my OCD)
Edit: Iâve never had issues with the âlocalplayerâ not returning anything. Might be on your end?
IIRC LocalPlayer is nil when plugins run since it hasnât loaded in yet.
Is this just preference or is there some weird obscure reason to not just wait()
? i.e:
repeat wait() until game.Players.LocalPlayer
The best way to do this is probably:
local PlayersService = game:GetService("Player")
local localPlayer = PlayersService.LocalPlayer
while not localPlayer do
PlayerService.PlayerAdded:wait()
localPlayer = PlayersService.LocalPlayer
end
This avoids the unnecessary wait() when the LocalPlayer already exists and uses the PlayerAdded event rather than the RenderStepped event.
Why arbitrarily yield when you can get LocalPlayer as soon as itâs available?
local player = game:GetService'Players'.LocalPlayer or game:GetService'Players':GetPropertyChangedSignal'LocalPlayer':Wait() or game:GetService'Players'.LocalPlayer
Oo I like that one best.
@gkku
Itâs 60hz but the logic that creates the localplayer might be 30hz so probably redundant. I just wanted the shortest possible wait.
breathes in ⌠BOI
Not âeverybodyâ uses just module scripts
I believe he was referring to games using more modern development frameworks. For less experienced developers, they donât need to worry about this issue.
Ok. Looks like a lot of people arenât understanding the problem here.
Fact:
Now consider a common scenario:
Hereâs what happens when your game runs in play solo:
And thatâs where the use case is.
One could argue that this would be fixed by making the LocalPlayer exist before any scripts run in play solo, but even then thatâs a behavior thatâs prone to breaking. I would always have a failsafe that ensures my game doesnât break if roblox breaks LocalPlayer and then waits for a week before fixing it. So it makes sense to me that there may as well be a function for it.
After re-reading your post I understand. This makes sense because your module is being shared by the server and client in play solo.
Honestly it seems kinda messy that you have a module shared by both server and client that uses client only features.
Yeah because that didnât sound condescending at all.
Is a new function really necessary? Once your Util module acquires the LocalPlayer, all code that depends on the module wonât need to do the same check. You can even export the result as Util.LocalPlayer
or Util:WaitForLocalPlayer()
if you want to be explicit about the dependency.
Regardless, the example in your first post is simple, correct, and idiomatic. There arenât any glaring problems that would be solved by implementing it as a function.
You could say the same for GetDescendants and WaitForChild. Even FindFirstChild. I think âitâs possible to make this yourselfâ isnât a good reason for not having a quick api to do it.
WaitForLocalPlayer is not suitable because:
Server scripts in Play Solo can access LocalPlayer, so in Play Solo everything would be detected as a LocalScript. While this is kind of true, it means I have to spin up a test server to test my game and can never use Play Solo.
Server scripts will yield indefinitely since LocalPlayer will never exist in-game or in a test server. A timeout wouldnât work either because some use cases require the script to know instantly â for instance, when I made a spawn at camera plugin, I needed to know whether to wait for the player or to create a CFrame reference the plugin would reference when I went into play solo later â I had to do some really hacky workarounds to accomplish this (seeing if ChangeHistoryService was active)