Hello developers,
If you’ve been working with Roblox Lua for even a brief time, you have no doubt used PlayerAdded
and PlayerRemoving
events before. These are useful for establishing server-side statistics, inventories, and abilities for every player in the game. They can also be useful on the client for creating UI’s that display information pertaining to each player.
However, if you’ve worked with these events for a long time, you may have run into an issue where the event does not run for all players. What may happen is, for example, the PlayerAdded
event is connected after someone has already joined the game, so the connected function is never run on that player. Another example is a rare instance wherein the PlayerRemoving
event is not fired if the server a player crashes.
I’m not sure what the name is for this issue, but there’s doubtless a fancy computer science term for it. Regardless, the solution is to connect the listener to your function, then run through all of the existing items of the same type and run the function on each of them.
function OnPlayerAdded(Player)
end
game:GetService("Players").PlayerAdded:Connect(OnPlayerAdded)
for _,Player in pairs(game:GetService("Players"):GetPlayers()) do
OnPlayerAdded(Player)
end
The module of discussion here …
… ensures that your onPlayerAdded and onPlayerRemoving functions work on absolutely every single player, regardless of if the script ran late or if the server or a player crashed. It also works for characters, but I don’t find that particularly useful.
How to use:
local Module = 4710901436 -- Replace this with the in-game path if you want to fork the module or you just don't like using on-site code
require(Module)(
function(JoiningPlayer)
end,
function(LeavingPlayer)
end,
function(Player, Character)
end
)
You do not need to input all three of these functions. If you don’t want to use one, leave it as nil
.
The following is just one example out of the many times I’ve used this. This is the server-side code for another module of mine that allows players to change their camera’s field of view with the command /fov
.
If you want to nitpick about the code sample above or ask why I’m placing non UI-related client code in a ScreenGui, message me in private.
When called, the module function will return the connections should you need them. For example, this code …
local PlayerAddedConnection, PlayerRemovingConnection, CharacterConnections = require(4710901436)(
function(JoiningPlayer)
end,
function(LeavingPlayer)
end,
function(Player, Character)
end
)
… returns the PlayerAdded connection, the PlayerRemoving connection, and a table for each player’s CharacterAdded connection (index == player instance), respectively. I don’t really know why anyone would need these connections, but they are available nonetheless.
Please provide feedback if you think this could have been done better or if you have a suggestion for extra functionality.
@sleitnick did a good video on the problem at hand here as well. Thanks to @IGOTHISLOL for the video link.