I will be using custom characters a lot as well, along with Player.CharacterAutoLoads disabled.
In this case it seems the workflow shouldn’t differ from what you’re doing right now, as the new feature will clean up the old character if it still exists when the new one is added, as visible in the code below.
CharacterAdded always fires before Destorying.
The new feature is pretty neat, and is compatible with manual removal of the character.
Connecting to Players.PlayerAdded and Players.PlayerRemoving does not necessarily create a memory leak, because the connection is only related to the Players service. If you maintain references to the Player argument that gets passed by those events however, that’s where you could see a memory leak.
To give some examples:
Fixed by this change (because the CharacterAdded connection would have maintained the reference under current behavior)
As for a reduction in server memory usage, you will a change to the rate at which memory increases if you had a memory leak patched by this. It will likely not have an impact on baseline memory usage.
If it is no longer possible to reparent characters on CharacterRemoving please add an alternative such as a character property to avoid being destroyed immediately on player death/leave.
This would be useful in cases where a death animation is played on a character and would be much simpler to play it on the existing character rather than having to clone it.
Well this is surprising, I kinda thought the new behavior was how it worked the whole time so this is a neat history lesson for me. Glad to see Roblox continuing to improve their core tech stack.
This is a great update and I have already been doing this in my game for a long time with a custom script. Will events like Players.PlayerRemoving() and Player.CharacterRemoving() be affected by this? Will the :Destroy() function happen after these events have run?
EDIT: This is the answer!
When a player leaves the experience, the Destroy method is called on the Player Instance. This task is deferred and occurs after bound event connections are invoked.
-- Broken by PlayerCharacterDestroyBehavior = Enabled
Players.PlayerRemoving:Connect(function(player)
task.wait(1) -- Because we are deferring, this code will not work
local points = player.leaderstats.Points.Value
print(`player.Name left with ${points} points!`)
end)
-- Still works, even with PlayerCharacterDestroyBehavior = Enabled
Players.PlayerRemoving:Connect(function(player)
local points = player.leaderstats.Points.Value
print(`player.Name left with ${points} points!`)
end)
I got a concern, does the “task.wait()” still breaks even so it is not at the start of the function.
Below is a summary of how I use “task.wait()”
game:GetService("Players").PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local StatsInfo = Player:WaitForChild("StatsInfo")
local PlayerLevel = StatsInfo:WaitForChild("PlayerLevel")
local PlayerClothes = StatsInfo:WaitForChild("PlayerClothes")
local FakeServerhop = game.ServerStorage.FakeServerhop
---About 40 ~ 50 lines down of info for Player
task.wait(1) --- I add this to let the info load, while the player respawns.
-- for I need the player to spawn to give them their clothes.
---About 40 ~ 50 lines down to Add Player Info to Gui, etc.
Character:WaitForChild("Humanoid").Died:Connect(function()
FakeServerhop:Fire(Player, 'PlayerClothesRenew')
end)
end)
end)
EDIT:
This is used every time the player dies. (And a few corrections)
Wow, I never knew this was even a thing, even after looking into oddities with removing players’ characters years ago (there was some change that made simply setting a player’s character to a different humanoid model cause a respawn… I never fully figured it out, but my current assumption is a change to the order objects are loaded into the player character model, and when removed, it would remove either the head or torso before the humanoid object, causing the Died event to fire?)
Any chance of getting a setting to control that? Manually controlling respawns fixed it, but I’d rather not have to do that in the first place.
I wonder why this wasn’t released by default, I see no negatives here, can you (or someone) explain to me the limitations/down sides of this feature that make it an “opt in” feature instead of just a general rollout/bugfix?
Due to this change it’s no longer possible to preserve the Character model to re-use for a ragdoll. The reason to keep the entire model is to prevent the need for re-replicating any of its contents to clients.
If nothing is done to solve this issue, ragdolls will need to be fully replicated to clients, increasing latency upon player death and thereby worsening game feel.
The only solution is to introduce a setting that prevents the Character model from destroying (and / or having its parent set to nil). Hopefully this is something you will consider before the opt-out period ends!
This change affects my game’s ragdolls. Ragdolls were designed to re-use Character models after death, and now that they’re being destroyed, the game simply spams errors and displays no ragdolls. My only choice is to abandon the optimization I’ve created.
About time this was addressed. This is something people have been complaining about for awhile now. I’ve had to resort to manually calling destroy on the player’s character when they died, and when they left the server to make sure it was cleaned up properly.
That’s actually a good point. Probably introduce a time setting to where after this many seconds, the character is destroyed. Probably two separate settings:
Player died and respawn, must be less than the respawn time.