How to unload a player when they died (CharacterAutoLoads = false)?

Hi, I can’t figure out how to unload the character properly on death. I am using CharacterAutoLoads = false and whenever the player dies, my script calls :Destroy() on the player model, but then it starts spitting out loads of warnings (saying: Player:Move called, but player currently has no humanoid. (x553), YES, it done it 553 times in the space of 30 seconds and almost lagged me out of ROBLOX studio) and it breaks my respawn menu. Any help?

4 Likes

Apparently some default scripts still work on the character while player.Character exists.

LoadCharacter() clears the old character from workspace before a new one is assigned. So you can simulate this by setting player.Character to nil, waiting a reasonable time, and then calling :Destroy() on the old model before deciding to load the character again in the near future.

You may also want to take care of the camera, because it stays focused, which means the reference to the old character is kept by default scripts even after it’s subject to :Destroy(). Once the new character spawns, reference should be finally lost.

local Players = game:GetService("Players")

Players.CharacterAutoLoads = false

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")
		
		humanoid.Died:Once(function()
			task.wait(3)
			player.Character = nil
			task.wait(5)
			character:Destroy()
			player:LoadCharacter()
		end)
	end)
	
	player:LoadCharacter()
end)
6 Likes

I’ll try it right now, hopefully it works!

1 Like

Thank you, works a charm! No warnings or errors. Thank you so much!

2 Likes

I’m glad it works!

I’ve also done some quick tests to see how it works when it comes to garbage collection. I’ve done this with a random event, because they get disconnected once the instance is destroyed.

Based on that we know that when default character loading is enabled, characters don’t get destroyed atuomatically, and connections remain.

Code
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local player = Players.PlayerAdded:Wait()
local character: Model? = nil
local connection: RBXScriptConnection

player.CharacterAdded:Connect(function(char)
	-- Manually destroy -----------
	--if character then
	--	character:Destroy()
	--end
	-------------------------------
	character = char
	
	if not connection then
		connection = char:WaitForChild("Humanoid").Died:Connect(function() end)
	end
end)
repeat task.wait() until connection

task.spawn(function()
	repeat task.wait() until connection.Connected == false
	print("Disconnected")
end)

-- Stimulate garbage collection
RunService.Heartbeat:Connect(function()
	local part = Instance.new("Part")
	part.Parent = workspace
	task.wait(1); part:Destroy()
end)

→ This is a bit awkward, but I wanted to avoid nested connections. If humanoid was really destroyed upon resetting/removal, connection would disconnect, but it doesn’t by default.

And here’s the other example illustrating how :LoadCharacter(), as the docs say, clears the character, but it doesn’t destroy it.

Code
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

Players.CharacterAutoLoads = false

local player = Players.PlayerAdded:Wait()
local character: Model? = nil
local connection: RBXScriptConnection

player.CharacterAdded:Connect(function(char)
	-- Manually destroy -----------
	--if character then
	--	character:Destroy()
	--end
	-------------------------------
	character = char
	local humanoid = char:WaitForChild("Humanoid")
	
	if not connection then
		connection = humanoid.HealthChanged:Connect(function() end)
	end
	
	humanoid.Died:Once(function()
		task.wait(3)
		print("Loading new character")
		player:LoadCharacter()
	end)
end)

player:LoadCharacter()

repeat task.wait() until connection

task.spawn(function()
	repeat task.wait() until connection.Connected == false
	print("Disconnected")
end)

-- Stimulate garbage collection
RunService.Heartbeat:Connect(function()
	local part = Instance.new("Part")
	part.Parent = workspace
	task.wait(1); part:Destroy()
end)

→ Connection still remains. As I see it, the best way is to set player.Character to nil and either 1. destroy after a reasonable time or 2. destroy when the new character is added, while the old one is still referenced.

2 Likes

Yeah, already thought of that isssue & already resolved by #2 path, thank you anyway.

2 Likes

I find it a bit odd that ROBLOX doesn’t just give you a feature to auto-unload on death. Bizzare!

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.