Those are anonymous functions. The following two samples are effectively the same.
someEvent:Connect(function() ... end)
local function Callback() ... end
someEvent:Connect(Callback)
Both pass a function as a parameter to :Connect()
. In turn, the engine calls that function each time the event occurs, and usually sends some arguments along, in your case player or player’s character. The latter function has a name and can be used in more than one :Connect()
or called by you, whereas the anonymous one cannot be.
:Connect()
also wraps the callback in a coroutine.
PlayerAdded runs a single time when the player joins. PlayerRemoving also runs once (except the studio play test - rarely - ends before it gets the chance to).
The LoadCharacter()
call triggers CharacterRemoving, then CharacterAdded, then CharacterAppearanceLoaded.
Regarding CharacterAppearanceLoaded code sample
Line 6 throws an error; GetAccessories()
is a method of humanoid, not character. Lines 14 and 15 are no longer needed because player and character instances now get destroyed automatically.
Players and characters actually indeed used to leak memory. By now, the New Player and Character Destroy Behavior should be enabled by default will soon be enabled by default, so that’s that will be taken care of on the server. Once an instance is destroyed, all connections bound to it are also deactivated.
The same script with only anonymous functions
local Players = game:GetService("Players")
local RESPAWN_DELAY = 5
Players.CharacterAutoLoads = false
local function PlayerAdded(player)
print(player.Name .. "'s player has been added")
player.CharacterAdded:Connect(function(character)
print(character.Name .. "'s character has been added")
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Once(function()
print(character.Name .. "'s character has died")
task.wait(RESPAWN_DELAY)
player:LoadCharacter()
end)
end)
player.CharacterRemoving:Connect(function(character)
print(character.Name .. "'s character has been removed")
end)
player.CharacterAppearanceLoaded:Connect(function(character)
print(character.Name .. "'s character appearance has been loaded")
end)
player:LoadCharacter()
end
for _, player in Players:GetPlayers() do
task.spawn(PlayerAdded, player)
end
Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(function(player)
print(player.Name .. " has left the experience")
end)
UPDATE @mc7oof
As it turns out, workspace.PlayerCharacterDestroyBehavior
does not default to Enabled
yet. According to the announcement, it will early this year.
I suggest to turn it on because it is planned to be the only behavior in the near future. If you opt to keep it disabled for the time being, it would be more efficient to utilise a maid or destroy old characters upon respawn and the player instance when the player leaves manually, rather than disconnecting individual connections.