Keeping ragdoll after death

Hi, I am wanting to make it so that after the ragdoll is formed, it stays instead of going away after the player respawns. How would I do that? Here’s my code:

local function ConnectLimbs(char)
	for i, limb in pairs(char:GetChildren()) do
		if limb:IsA("BasePart") then
			local atch0, atch1, atch2, atch3, atch4, atch5

			if limb.Name == "Head" then
				atch0 = char.Head.NeckRigAttachment
				atch1 = char.UpperTorso.NeckRigAttachment
			elseif limb.Name == "UpperTorso" then
				atch0 = char.UpperTorso.WaistRigAttachment
				atch1 = char.LowerTorso.WaistRigAttachment

				atch2 = char.UpperTorso.LeftShoulderRigAttachment
				atch3 = char.LeftUpperArm.LeftShoulderRigAttachment

				atch4 = char.UpperTorso.RightShoulderRigAttachment
				atch5 = char.RightUpperArm.RightShoulderRigAttachment
			elseif limb.Name == "LowerTorso" then
				atch0 = char.LowerTorso.LeftHipRigAttachment
				atch1 = char.LeftUpperLeg.LeftHipRigAttachment

				atch2 = char.LowerTorso.RightHipRigAttachment
				atch3 = char.RightUpperLeg.RightHipRigAttachment
			elseif limb.Name == "LeftUpperLeg" then
				atch0 = char.LeftUpperLeg.LeftKneeRigAttachment
				atch1 = char.LeftLowerLeg.LeftKneeRigAttachment
			elseif limb.Name == "RightUpperLeg" then
				atch0 = char.RightUpperLeg.RightKneeRigAttachment
				atch1 = char.RightLowerLeg.RightKneeRigAttachment
			elseif limb.Name == "LeftLowerLeg" then
				atch0 = char.LeftLowerLeg.LeftAnkleRigAttachment
				atch1 = char.LeftFoot.LeftAnkleRigAttachment
			elseif limb.Name == "RightLowerLeg" then
				atch0 = char.RightLowerLeg.RightAnkleRigAttachment
				atch1 = char.RightFoot.RightAnkleRigAttachment
			elseif limb.Name == "LeftUpperArm" then
				atch0 = char.LeftUpperArm.LeftElbowRigAttachment
				atch1 = char.LeftLowerArm.LeftElbowRigAttachment
			elseif limb.Name == "RightUpperArm" then
				atch0 = char.RightUpperArm.RightElbowRigAttachment
				atch1 = char.RightLowerArm.RightElbowRigAttachment
			elseif limb.Name == "LeftLowerArm" then
				atch0 = char.LeftLowerArm.LeftWristRigAttachment
				atch1 = char.LeftHand.LeftWristRigAttachment
			elseif limb.Name == "RightLowerArm" then
				atch0 = char.RightLowerArm.RightWristRigAttachment
				atch1 = char.RightHand.RightWristRigAttachment
			end

			if atch0 and atch1 then
				local ballInSocket = Instance.new("BallSocketConstraint", limb)
				ballInSocket.Attachment0 = atch0
				ballInSocket.Attachment1 = atch1
			end

			if atch2 and atch3 then
				local ballInSocket = Instance.new("BallSocketConstraint", limb)
				ballInSocket.Attachment0 = atch2
				ballInSocket.Attachment1 = atch3
			end

			if atch4 and atch5 then
				local ballInSocket = Instance.new("BallSocketConstraint", limb)
				ballInSocket.Attachment0 = atch4
				ballInSocket.Attachment1 = atch5
			end

		elseif limb:IsA("Accessory") then
			local h = limb:FindFirstChild("Handle")
			if h then
				local part0 = char.Head
				local atch = h:FindFirstChildOfClass("Attachment")

				if atch.Name == "HatAttachment" or atch.Name == "FaceFrontAttachment" then
					part0 = char.Head
				end

				local ap = Instance.new("AlignPosition", part0)
				if part0 == char.Head then
					ap.Attachment1 = char.Head:FindFirstChild(atch.Name)
					ap.Attachment0 = atch
					ap.RigidityEnabled = true
					ap.Responsiveness = 200
				end

				local ao = Instance.new("AlignOrientation", part0)
				if part0 == char.Head then
					ao.Attachment1 = char.Head:FindFirstChild(atch.Name)
					ao.Attachment0 = atch
					ao.RigidityEnabled = true
					ao.Responsiveness = 200
				end
			end
		end
	end
end

game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		local humanoid = char:WaitForChild("Humanoid")
		humanoid.Died:Connect(function()
			ConnectLimbs(char)
		end)
	end)
end)
2 Likes

When Player.Character is set to nil or changed to something else, the character is automatically deleted.

You need to clone the character when they die and apply the ragdoll physics to the clone instead, and then immediately delete the original character.

How would I code that? I’m kinda lost…

1 Like

First you need a reference to the Workspace, so add this to the top of your script, before the ConnectLimbs function.

local Workspace = game:GetService("Workspace")

Cloned instances are not parented to anything when created, so you’ll need a reference to the Workspace to move the ragdoll there.

I chose to run the ConnectLimbs function before parenting it to Workspace because it’s better to set the parent of something after you’re done setting it up for performance reasons.

humanoid.Died:Connect(function()
	local ragdoll = char:Clone()
	ConnectLimbs(ragdoll)
	char:Destroy()
	ragdoll.Parent = Workspace
end)
2 Likes

It’s giving me this error:

1 Like

The function ConnectLimbs has lots of unnecessary if checks, instead of using if checks, you could use a table with keys.

Example:

local BodyPartTable = {
    ["Head"] = {
            Attachment0 = "NeckRigAttachment",
            Attachment1 = "NeckRigAttachment"
        }
}

local function ConnectLimbs(Character)
    ... -- other stuff
    local Attachment0, Attachment1, ...
    local AttachmentTable = BodyPartsTable[Limb.Name]
    Attachment0 = Character.Head[AttachmentTable.Attachment0]
    Attachment1 = Character.UpperTorso[AttachmentTable.Attachment1]
end

I was just following a tutorial, I have no idea what to do afterwards. I am not fully experienced with ragdolls either.

1 Like

Your code isn’t creating the clone in the first place, so look into this first:

1 Like

So I guess the fixed code would be this:

plr.CharacterAdded:Connect(function(char)
	char.Archivable = true
	local humanoid = char:WaitForChild("Humanoid")
	humanoid.Died:Connect(function()
		local ragdoll = char:Clone()
		ConnectLimbs(ragdoll)
		char:Destroy()
		ragdoll.Parent = Workspace
	end)
end)

That makes me wonder why Archivable is false by default… that just leaves weird and confusing scenarios like this. I was stumped trying to figure this out for 20 minutes.

This is kind of off topic, but Archivable = false means that an object is transient, it is not a part of the world, it should not remain when the place is saved.

It’s a remnant from the days when you could enter a place in Build mode, which was like Edit mode/current studio, but with your character, and with build tools and the ability to save the game.

Saving the game would (and still will) ignore all non-Archivable objects. If you set your character’s Archivable to true, saved the game and entered it again, then you would see your character in the exact position you last saved the game in.

Traditionally, Archivable is set to false on rockets, slingshot pellets, paintball splatter etc., things that would’ve disappeared on their own anyway. But that’s no longer strictly necessary.

What Archivable is still needed for, however, is visual effects created by plugins. If a plugin temporarily added some sort of model preview to the workspace and you published, saved or autosaved the game, then the preview should not linger on in the save file. Setting Archivable to false on anything that’s not meant to last will easily remove all of these.

2 Likes

After several hours of testing with @hipenguinflip, we’ve figured out a solution:

game:GetService("Players").PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(Character)
		Character:WaitForChild("Humanoid").Died:Connect(function()
			ConnectLimbs(Character)
			local test = (Character:GetChildren())

			local testing = Instance.new("Model",workspace)
			for i = 1, #test do
				local child = test[i]
				child:Clone()
				child.Parent = testing
			end
		end)
	end)
end)

Thank you @LexiDog5 for helping too!!

2 Likes

I did the same script but it doesn’t work sadly

local function ConnectLimbs(char)
	for i, limb in pairs(char:GetChildren()) do
		if limb:IsA("BasePart") then
			local atch0, atch1, atch2, atch3, atch4, atch5

			if limb.Name == "Head" then
				atch0 = char.Head.NeckRigAttachment
				atch1 = char.UpperTorso.NeckRigAttachment
			elseif limb.Name == "UpperTorso" then
				atch0 = char.UpperTorso.WaistRigAttachment
				atch1 = char.LowerTorso.WaistRigAttachment

				atch2 = char.UpperTorso.LeftShoulderRigAttachment
				atch3 = char.LeftUpperArm.LeftShoulderRigAttachment

				atch4 = char.UpperTorso.RightShoulderRigAttachment
				atch5 = char.RightUpperArm.RightShoulderRigAttachment
			elseif limb.Name == "LowerTorso" then
				atch0 = char.LowerTorso.LeftHipRigAttachment
				atch1 = char.LeftUpperLeg.LeftHipRigAttachment

				atch2 = char.LowerTorso.RightHipRigAttachment
				atch3 = char.RightUpperLeg.RightHipRigAttachment
			elseif limb.Name == "LeftUpperLeg" then
				atch0 = char.LeftUpperLeg.LeftKneeRigAttachment
				atch1 = char.LeftLowerLeg.LeftKneeRigAttachment
			elseif limb.Name == "RightUpperLeg" then
				atch0 = char.RightUpperLeg.RightKneeRigAttachment
				atch1 = char.RightLowerLeg.RightKneeRigAttachment
			elseif limb.Name == "LeftLowerLeg" then
				atch0 = char.LeftLowerLeg.LeftAnkleRigAttachment
				atch1 = char.LeftFoot.LeftAnkleRigAttachment
			elseif limb.Name == "RightLowerLeg" then
				atch0 = char.RightLowerLeg.RightAnkleRigAttachment
				atch1 = char.RightFoot.RightAnkleRigAttachment
			elseif limb.Name == "LeftUpperArm" then
				atch0 = char.LeftUpperArm.LeftElbowRigAttachment
				atch1 = char.LeftLowerArm.LeftElbowRigAttachment
			elseif limb.Name == "RightUpperArm" then
				atch0 = char.RightUpperArm.RightElbowRigAttachment
				atch1 = char.RightLowerArm.RightElbowRigAttachment
			elseif limb.Name == "LeftLowerArm" then
				atch0 = char.LeftLowerArm.LeftWristRigAttachment
				atch1 = char.LeftHand.LeftWristRigAttachment
			elseif limb.Name == "RightLowerArm" then
				atch0 = char.RightLowerArm.RightWristRigAttachment
				atch1 = char.RightHand.RightWristRigAttachment
			end

			if atch0 and atch1 then
				local ballInSocket = Instance.new("BallSocketConstraint", limb)
				ballInSocket.Attachment0 = atch0
				ballInSocket.Attachment1 = atch1
			end

			if atch2 and atch3 then
				local ballInSocket = Instance.new("BallSocketConstraint", limb)
				ballInSocket.Attachment0 = atch2
				ballInSocket.Attachment1 = atch3
			end

			if atch4 and atch5 then
				local ballInSocket = Instance.new("BallSocketConstraint", limb)
				ballInSocket.Attachment0 = atch4
				ballInSocket.Attachment1 = atch5
			end

		elseif limb:IsA("Accessory") then
			local h = limb:FindFirstChild("Handle")
			if h then
				local part0 = char.Head
				local atch = h:FindFirstChildOfClass("Attachment")

				if atch.Name == "HatAttachment" or atch.Name == "FaceFrontAttachment" then
					part0 = char.Head
				end

				local ap = Instance.new("AlignPosition", part0)
				if part0 == char.Head then
					ap.Attachment1 = char.Head:FindFirstChild(atch.Name)
					ap.Attachment0 = atch
					ap.RigidityEnabled = true
					ap.Responsiveness = 200
				end

				local ao = Instance.new("AlignOrientation", part0)
				if part0 == char.Head then
					ao.Attachment1 = char.Head:FindFirstChild(atch.Name)
					ao.Attachment0 = atch
					ao.RigidityEnabled = true
					ao.Responsiveness = 200
				end
			end
		end
	end
end


game:GetService("Players").PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(Character)
		Character:WaitForChild("Humanoid").Died:Connect(function()
			ConnectLimbs(Character)
			local test = (Character:GetChildren())

			local testing = Instance.new("Model",workspace)
			for i = 1, #test do
				local child = test[i]
				child:Clone()
				child.Parent = testing
			end
		end)
	end)
end)