Add an option to not destroy character on PlayerRemoving

I wanted to turn a player’s character into a ragdoll when they leave the game. So naturally, I tried to just tinker with the character in Players.PlayerRemoving but oh no - by the time that signal runs, the character has already been destroyed. I eventually solved this problem in a more hacky way, but I think making it possible to do it this way would be way nicer.

I’m proposing a new bool property, Players.KeepCharacterWhenPlayerLeaves. When set to true, characters of leaving players will NOT be destroyed, or even touched at all in any way.

This will be incredibly useful for the thousands of games that currently need to create fake/dummy characters when the player leaves, for all intents and purposes.

5 Likes

why you need ragdoll player then they leave? they dont care if they ragdoll or not then they are leave

2 Likes

In the game I’m making, you can take items from dead/ragdolled players. So it would be useful for that.

3 Likes

2 options 1 create after model then player die(if multiple peoples die can be laggy) 2 if player died then you can pickup items but if they leave body disappear and they disappear then respawn time is end

Or connect to the destroying event of the character model, and clone it

This in itself doesn’t disable character deletion, it just parents the character to nil when being removed instead of calling a full Destroy on the model.

All children are cleared by the time .Destroyed runs, so it will result in a model with nothing in it.

Can’t you just do this?

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterRemoving:Connect(function(char)
		char.Archivable = true
		
		local clone = char:Clone()
		clone.Parent = workspace
	end)
end)
1 Like

Try changing DeferredSignalBehavior to immediate if it is set to Deferred (or default?)

This I think will allow you to clone the character before it gets destroyed or parented to nil, in the CharacterRemoving event

Immediate signals are expected to be phased out in favor of deferred signals, but I absolutely hate deferred signals, and it’ll break a lot of games

1 Like

Still nil with immediate signal behavior. (I also share your disdain for deferred signals :wink:)

1 Like

Perhaps you could try connecting to Character.Destroying? I’m surprised CharacterRemoving fires after the character is removed, in immediate mode

Or :GetPropertyChangedSignal(“Parent”) if using the old character destroy behavior

This works. I tinkered around with it and ended up with this:

local clones = {}

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function()
		if clones[plr] then
			clones[plr]:Destroy()
			clones[plr] = nil
		end
	end)
	
	plr.CharacterRemoving:Connect(function(char)
		char.Archivable = true
		clones[plr] = char:Clone()
	end)
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local clone = clones[plr]
	-- Do what we want to do!
end)

The only difference between this approach and the feature request would be it getting cloned, but it might not matter for my particular use case. It also works with deferred signal behavior!

This works with immediate signal behavior, but not with deferred.

1 Like

My bad - I misread this as PlayerRemoving. That’s what I tried in the previous reply, and it does indeed work!

1 Like

Yeah but its easy enough to just reparent it

Just clone the character whenever it’s added to the workspace and then parent it when they die/leave.
This feature is a thing for a very good reason; it used to be the case that event connections created on players and characters wouldn’t be disconnected automatically as the Destroy function wouldn’t be called internally on these objects when removed from the game, which would lead to huge memory leaks if developers weren’t careful.

Please don’t set deferred signal behavior to immediate or player destruction behavior to disabled. Both of these are three phased rollouts that are explicitly intended to be forced away from what you are setting them to.

This feels a significantly niche footgun, so I don’t expect it to be added. I recommend something like this instead:

local savedCharacters = {}

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local existingCharacter = savedCharacters[player]
		if existingCharacter ~= nil then
			existingCharacter:Destroy()
		end

		character.Archivable = true
		savedCharacters[character] = character:Clone()
	end)
end)

Players.PlayerRemoving:Connect(function(player)
	local savedCharacter = savedCharacters[player]
	savedCharacters[player] = nil

	-- Do stuff with savedCharacter
end)
2 Likes

The same code works with .CharacterRemoving, so that’s nice! .CharacterRemoving is more useful in my case since I want the limb positions to be up to date. On a side note, using features that are being phased out is a way of pushing back against unwelcome changes, I’m aware of them not receiving support.

2 Likes

Defferred nor PlayerCharacterDestroyBehavior are unwelcome, deffered stops people from relying on execution order in their code, while PlayerCharacterDestroyBehavior fixes a long standing memory leak that existed if you didnt destroy player instances after that player leaves, and if you didnt destroy character instances in character removing as they’d otherwise just persist in memory forever.

For you - perhaps, but I personally dislike deferred signals. They are unwelcome in my eyes, I’m not speaking for others; I apologize if it came off that way.