Why do people use this in PlayerAdded events?

I have seen some YouTubers use this line of code after creating there PlayerAdded event:

Players.PlayerAdded:Connect(PlayerData.PlayerAdded) -- PlayerAdded event which adds stringvalues to player

for _, Player in next, Players:GetPlayers() do
	coroutine.wrap(PlayerData.PlayerAdded)(Player)
end

What does this for coroutine wrap do and why do people use it?

This would be used in case there is an infinate loop in the PlayerData.PlayerAdded code.

For example when we call :Connect on the PlayerAdded rbxscriptsignal, each time a player is added that code will run in its own thread. This behavior is default to the :Connect( f) method. Therefore, if the function yields the thread, like an infinate loop, it will not be a problem because the script can continue to execute (the thread created by the connection is yielded, not the script thread)

However, when youre looping through all the players the PlayerAdded code will run on that script’s thread. Therefore, if you run a function that yields the thread it will only run for the first iteration before the entire script yields. coroutine.wrap basically calls the PlayerAdded code on a new thread, similar to how :Connect() does, preventing the script from yielding and allowing the code to run for each player in the loop.

3 Likes

This is inside the PlayerData code:

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local PlayerDataFolder = ServerStorage.PlayerData

local PlayerData = {}

function PlayerData.PlayerAdded(Player)
	for _, Value in pairs(PlayerDataFolder:GetChildren()) do
		local ClonedValue = Value:Clone()
		ClonedValue.Parent = Player
	end
end

return PlayerData

In this case, a coroutine would be redundant and unneeded. Unless you have a function that yields the thread, you do not have to wrap it in a coroutine.

The only other thing I could think of is if the developer wanted to catch errors with the coroutine but there are two problems with this. First, wrap doesnt catch errors. You would have to use create and resume to catch the errors. Secondly, why do that when you can just use pcall which is meant to catch errors.

In addition, you need the for loop because you’re not guaranteed that your event will be connected before the first player joins—the loop runs the handler for any players that are already in the game, and the connection catches any that join later.

mc3334 has already explained the why part of it, but for a bit more clarification, what that code does is loops through all the players currently ingame and runs the same code on them that would have been ran had they joined after the event was created. It additionally wraps it in a coroutine, allowing the code to continue in case your PlayerAdded code yields or gets stuck for whatever reason.

This isn’t something that should ever really come up, as the server always gets ready before any players join in my experience, but it’s there anyway.

2 Likes

Actually, if this is the first thing in the script you are guaranteed that this will be connected before the first player joins.

Should I remove the coroutine wrap? Is it safe to keep it there for now?

It’s not going to do any harm if you leave it, as it will likely never run anyway (due to there always being 0 players when the server first starts), your choice on whether you want to or not.

2 Likes