Another Open Sourced Ragdoll System

INTRODUCTION

Hey Devforum, so I just made another Ragdoll System, I know there are like quadrillion other ones to use out there, but I still decided to make my own. I am being honest, I can’t really say why you should use this over other ones but

  1. I am using this for myself, so it will receive continued support
  2. It is easy to use
  3. It has some easy to configure settings

DISCLAIMER

Keep in mind, I am definitely not the best scripter, so some code may not be very good.

SCRIPTS (Version 1.4.2)

R6RagdollServer
--[[ System By @Liam 
-> Version 1.4.2
 ♥ Thanks for using this!! ♥ 
--]] 



--||Services||--
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")

--||Ragdoll CFrames (can be changed)||--
local attachmentCFrames = {
	--HEAD
	["Neck"] = {CFrame.new(0, 1, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1), CFrame.new(0, -0.5, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1)},
	--ARMS	
	["Left Shoulder"] = {CFrame.new(-1.3, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1), CFrame.new(0.2, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1)},
	["Right Shoulder"] = {CFrame.new(1.3, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CFrame.new(-0.2, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)},
	--LEGS	
	["Left Hip"] = {CFrame.new(-0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1), CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)},
	["Right Hip"] = {CFrame.new(0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1), CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)},
}

--||Don't change this||--
local ragdollInstanceNames = {
	["RagdollAttachment"] = true,
	["RagdollConstraint"] = true,
	["ColliderPart"] = true,
}

--||Settings||--
local ragdollSounds = true --if you wanna have ragdoll sounds when the body hits something set this to true
local ragdollOnDeath = true --if you want to automatically enable ragdoll on death
local ragdollOnGameStart = true --if you want every character that can be found in workspace at the start of the game to use this ragdoll system
local fixVoidBug = true --fixes the bug that the player doesnt respawn when they fall into the void 

local npcSettings = {
	fixNpcFling = true, --fixes the npc flinging away when they get up (this sets the enemies hrp networkownership to nil)	
	npcFolders = {}, --if you have specific npc folders add them in the table, example: npcFolders = {workspace.Enemies, workspace.Enemies2}
} 

------------------------------------------------------------------------------------------------------------------





--//
local function createImpactSound(parent, soundScript)
	local sound = soundScript:Clone()
	sound.Parent = parent
	sound.Disabled = false
end

--//
local function PlayRagdollSounds(char) --playing a sound when those body parts hit something
	if ragdollSounds then
		createImpactSound(char:WaitForChild("Head"), script.ImpactSound)
		createImpactSound(char:WaitForChild("Left Arm"), script.ImpactSound)
		createImpactSound(char:WaitForChild("Right Arm"), script.ImpactSound)
	end			
end

--//
local function createColliderPart(part) --creating the parts that are gonna be colliding with the world
	if not part then return end
	local rp = Instance.new("Part")
	rp.Name = "ColliderPart"
	rp.Size = part.Size / 1.7
	rp.Massless = true
	rp.CFrame = part.CFrame
	rp.Transparency = 1

	local wc = Instance.new("WeldConstraint")
	wc.Part0 = rp
	wc.Part1 = part
	wc.Parent = rp
	rp.Parent = part
end

--//
local function replaceJoints(char, hum) --replacing the joints and other stuff
	hum.PlatformStand = true
	hum.AutoRotate = false
	if not char:FindFirstChild("HumanoidRootPart") then return end
	char.HumanoidRootPart.Massless = true
	char.HumanoidRootPart.CanCollide = false

	for _, motor in char:GetDescendants() do
		if motor:IsA("Motor6D") and attachmentCFrames[motor.Name] then
			motor.Enabled = false
			
			PlayRagdollSounds(char)

			local a0, a1 = Instance.new("Attachment"), Instance.new("Attachment")
			a0.CFrame = attachmentCFrames[motor.Name][1]
			a1.CFrame = attachmentCFrames[motor.Name][2]

			a0.Name = "RagdollAttachment"
			a1.Name = "RagdollAttachment"

			createColliderPart(motor.Part1)

			local b = Instance.new("BallSocketConstraint")
			b.Attachment0 = a0
			b.Attachment1 = a1
			b.Name = "RagdollConstraint"

			b.Radius = 0.15
			b.LimitsEnabled = true
			b.TwistLimitsEnabled = motor.Name == "Neck"
			b.MaxFrictionTorque = 0
			b.Restitution = 0
			b.UpperAngle = motor.Name == "Neck" and 45 or 90
			b.TwistLowerAngle = motor.Name == "Neck" and -70 or -45
			b.TwistUpperAngle = motor.Name == "Neck" and 70 or 45

			a0.Parent = motor.Part0
			a1.Parent = motor.Part1
			b.Parent = motor.Parent
		end
	end
end

--//
local function resetJoints(hum) --resetting the joints and all the other properties
	local char = hum.Parent
	local hrp = char.HumanoidRootPart

	char:SetAttribute("IsRagdoll", false)
	hum.PlatformStand = false
	hum.AutoRotate = true
	char.HumanoidRootPart.Massless = false
	char.HumanoidRootPart.CanCollide = true 
	
	if ragdollSounds then
		for _, v in char:GetDescendants() do
			if v:IsA("Script") and v.Name == "ImpactSound" and v.Enabled == true then
				v:Destroy()
			end
		end
	end	

	if hum.Health <= 0 then return end --we don't want the player to stand up again if they is dead	

	for _, instance in char:GetDescendants() do
		if ragdollInstanceNames[instance.Name] then
			instance:Destroy()
		end
		if instance:IsA("Motor6D") then
			instance.Enabled = true
		end
	end

	hum:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
	hum:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
	hum:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)

	local isPlayer = Players:GetPlayerFromCharacter(hum.Parent)
	if not isPlayer and npcSettings["fixNpcFling"] == true then --the body position and body gyro thing was something I found on the devforum so not my idea
		hrp:SetNetworkOwner(nil)
		local FloatThing = Instance.new("BodyPosition") do
			FloatThing.Position = hrp.Position + Vector3.new(0, 2, 0)
			FloatThing.Parent = hrp
			Debris:AddItem(FloatThing, 0.25)
		end

		local Stabilizer = Instance.new("BodyGyro") do
			Stabilizer.P = 1000000
			Stabilizer.D = 500
			Stabilizer.MaxTorque = Vector3.new(10000, 0, 10000)
			Stabilizer.Parent = hrp
			Debris:AddItem(Stabilizer, .25)
		end
	end

end


--//
local function applyRagdollToCharacter(char) --applying the ragdoll
	local hum = char:FindFirstChild("Humanoid")
	if hum then
		local torso = char:FindFirstChild("Torso")
		if torso then
			hum.BreakJointsOnDeath = false
			hum.RequiresNeck = false
			
			char:SetAttribute("IsRagdoll", false) --setting ragdoll to false from the beginning on

			char:GetAttributeChangedSignal("IsRagdoll"):Connect(function()
				if char:GetAttribute("IsRagdoll") then
					replaceJoints(char, hum)
				else
					resetJoints(hum)
				end
			end)

			hum.Died:Once(function() --on death
				if not ragdollOnDeath then return end
				char:SetAttribute("IsRagdoll", true)
				torso:ApplyImpulse(torso.CFrame.LookVector * 100)
			end)
		end
	end
end


--//
local function applyRagdollToAllCharacters()
	for _, char in workspace:GetDescendants() do
		applyRagdollToCharacter(char)
	end
end

if ragdollOnGameStart then applyRagdollToAllCharacters() end


--//applying the ragdoll to the specific npc folders
for _, folder in npcSettings.npcFolders do
	for _, char in folder:GetChildren() do
		applyRagdollToCharacter(char)
	end
	
	folder.ChildAdded:Connect(function(child)
		if child:IsA("Model") and child:FindFirstChild("Humanoid") then
			applyRagdollToCharacter(child)
		end
	end)
end



--//
Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		applyRagdollToCharacter(char)
		
		if fixVoidBug then
			char.ChildRemoved:Connect(function() --this fixes the void bug
				if char.WorldPivot.Position.Y <= workspace.FallenPartsDestroyHeight then	
					char.Humanoid.Health = 0 --so that the player just dies normaly when they fall into the void
				end
			end)
		end
		
	end)
end)
R15RagdollServer
--[[ System By @Liam 
-> Version 1.4.2
 ♥ Thanks for using this!! ♥ 
--]] 



--||Services||--
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")

--||Ragdoll CFrames (can be changed)||-- 
local attachmentCFrames = {
	--HEAD
	["Neck"] = {CFrame.new(0, 1, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1), CFrame.new(0, -0.5, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1)},	
	--ARMS	
	["LeftShoulder"] = {CFrame.new(-1, 0.75, 0), CFrame.new(0, 0.75, 0)},
	["RightShoulder"] = {CFrame.new(1, 0.75, 0), CFrame.new(-0, 0.75, 0)},
	--
	["LeftElbow"] = {CFrame.new(-0, 0, 0), CFrame.new(0, 0.6, 0)},
	["RightElbow"] = {CFrame.new(0, 0, 0), CFrame.new(-0, 0.6, 0)},
	--
	["LeftWrist"] = {CFrame.new(-0, 0, 0), CFrame.new(0, .6, 0)},
	["RightWrist"] = {CFrame.new(0, 0, 0), CFrame.new(-0, .6, 0)},	
	--LEGS	
	["LeftHip"] = {CFrame.new(-0.5, -0, 0), CFrame.new(0, .9, 0)},
	["RightHip"] = {CFrame.new(0.5, -0, 0), CFrame.new(0, .9, 0)},	
	--
	["LeftKnee"] = {CFrame.new(-0, -0, 0), CFrame.new(0, .6, 0)},
	["RightKnee"] = {CFrame.new(0, -0, 0), CFrame.new(0, .6, 0)},
	--
	["LeftAnkle"] = {CFrame.new(-0, -0, 0), CFrame.new(0, .6, 0)},
	["RightAnkle"] = {CFrame.new(0, -0, 0), CFrame.new(0, .6, 0)},	
	--TORSO	
	["Root"] = {CFrame.new(0, 0, 0), CFrame.new(0, 0, 0)},
	--["Waist"] = {CFrame.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), CFrame.new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)},
}

--||Don't change this||--
local ragdollInstanceNames = {
	["RagdollAttachment"] = true,
	["RagdollConstraint"] = true,
	["ColliderPart"] = true,
}

--||Settings||--
local ragdollSounds = true --if you wanna have ragdoll sounds when the body hits something set this to true
local ragdollOnDeath = true --if you want to automatically enable ragdoll on death
local ragdollOnGameStart = true --if you want every character that can be found in workspace at the start of the game to use this ragdoll system
local fixVoidBug = true --fixes the bug that the player doesnt respawn when they fall into the void 

local npcSettings = {
	fixNpcFling = true, --fixes the npc flinging away when they get up (this sets the enemies hrp networkownership to nil)	
	npcFolders = {}, --if you have specific npc folders add them in the table, example: npcFolders = {workspace.Enemies, workspace.Enemies2}
} 

------------------------------------------------------------------------------------------------------------------





--//
local function createImpactSound(parent, soundScript)
	local sound = soundScript:Clone()
	sound.Parent = parent
	sound.Disabled = false
end

--//
local function PlayRagdollSounds(char) --playing a sound when those body parts hit something
	if ragdollSounds then
		createImpactSound(char:WaitForChild("Head"), script.ImpactSound)
		createImpactSound(char:WaitForChild("LeftLowerArm"), script.ImpactSound)
		createImpactSound(char:WaitForChild("RightLowerArm"), script.ImpactSound)
	end		
end

--//
local function createColliderPart(part) --creating the parts that are gonna be colliding with the world
	if not part then return end
	local rp = Instance.new("Part")
	rp.Name = "ColliderPart"
	rp.Size = part.Size / 1.7
	rp.Massless = true
	rp.CFrame = part.CFrame
	rp.Transparency = 1

	local wc = Instance.new("WeldConstraint")
	wc.Part0 = rp
	wc.Part1 = part
	wc.Parent = rp
	rp.Parent = part
end

--//
local function replaceJoints(char, hum) --replacing the joints and other stuff
	hum.PlatformStand = true
	hum.AutoRotate = false
	if not char:FindFirstChild("HumanoidRootPart") then return end
	char.HumanoidRootPart.Massless = true
	char.HumanoidRootPart.CanCollide = false

	for _, motor in char:GetDescendants() do
		if motor:IsA("Motor6D") and attachmentCFrames[motor.Name] then
			motor.Enabled = false
		
			PlayRagdollSounds(char)

			local a0, a1 = Instance.new("Attachment"), Instance.new("Attachment")
			a0.CFrame = attachmentCFrames[motor.Name][1]
			a1.CFrame = attachmentCFrames[motor.Name][2]

			a0.Name = "RagdollAttachment"
			a1.Name = "RagdollAttachment"

			createColliderPart(motor.Part1)

			local b = Instance.new("BallSocketConstraint")
			b.Attachment0 = a0
			b.Attachment1 = a1
			b.Name = "RagdollConstraint"

			b.Radius = 0.15
			b.LimitsEnabled = true
			b.TwistLimitsEnabled = motor.Name == "Neck"
			b.MaxFrictionTorque = 0
			b.Restitution = 0
			b.UpperAngle = motor.Name == "Neck" and 45 or 90
			b.TwistLowerAngle = motor.Name == "Neck" and -70 or -45
			b.TwistUpperAngle = motor.Name == "Neck" and 70 or 45

			a0.Parent = motor.Part0
			a1.Parent = motor.Part1
			b.Parent = motor.Parent
		end
	end
end

--//
local function resetJoints(hum) --resetting the joints and all the other properties
	local char = hum.Parent
	local hrp = char.HumanoidRootPart

	char:SetAttribute("IsRagdoll", false)
	hum.PlatformStand = false
	hum.AutoRotate = true
	char.HumanoidRootPart.Massless = false
	char.HumanoidRootPart.CanCollide = true    

	if ragdollSounds then
		for _, v in char:GetDescendants() do
			if v:IsA("Script") and v.Name == "ImpactSound" and v.Enabled == true then
				v:Destroy()
			end
		end
	end	

	if hum.Health <= 0 then return end --we don't want the player to stand up again if they is dead	

	for _, instance in char:GetDescendants() do
		if ragdollInstanceNames[instance.Name] then
			instance:Destroy()
		end
		if instance:IsA("Motor6D") then
			instance.Enabled = true
		end
	end

	hum:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
	hum:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
	hum:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)

	local isPlayer = Players:GetPlayerFromCharacter(hum.Parent)
	if not isPlayer and npcSettings["fixNpcFling"] == true then --the body position and body gyro thing was something I found on the devforum so not my idea
		hrp:SetNetworkOwner(nil)
		local FloatThing = Instance.new("BodyPosition") do
			FloatThing.Position = hrp.Position + Vector3.new(0, 2, 0)
			FloatThing.Parent = hrp
			Debris:AddItem(FloatThing, 0.25)
		end

		local Stabilizer = Instance.new("BodyGyro") do
			Stabilizer.P = 1000000
			Stabilizer.D = 500
			Stabilizer.MaxTorque = Vector3.new(10000, 0, 10000)
			Stabilizer.Parent = hrp
			Debris:AddItem(Stabilizer, .25)
		end
	end

end


--//
local function applyRagdollToCharacter(char) --applying the ragdoll
	local hum = char:FindFirstChild("Humanoid")
	if hum then
		local upperTorso = char:FindFirstChild("UpperTorso")
		if upperTorso then
			hum.BreakJointsOnDeath = false
			hum.RequiresNeck = false
			
			char:SetAttribute("IsRagdoll", false) --setting ragdoll to false from the beginning on

			char:GetAttributeChangedSignal("IsRagdoll"):Connect(function()
				if char:GetAttribute("IsRagdoll") then
					replaceJoints(char, hum)
				else
					resetJoints(hum)
				end
			end)

			hum.Died:Once(function() --on death
				if not ragdollOnDeath then return end
				char:SetAttribute("IsRagdoll", true)
				upperTorso:ApplyImpulse(upperTorso.CFrame.LookVector * 100)
			end)
		end
	end
end


--//
local function applyRagdollToAllCharacters()
	for _, char in workspace:GetDescendants() do
		applyRagdollToCharacter(char)
	end
end

if ragdollOnGameStart then applyRagdollToAllCharacters() end


--//applying the ragdoll to the specific npc folders
for _, folder in npcSettings.npcFolders do
	for _, char in folder:GetChildren() do
		applyRagdollToCharacter(char)
	end
	
	folder.ChildAdded:Connect(function(child)
		if child:IsA("Model") and child:FindFirstChild("Humanoid") then
			applyRagdollToCharacter(child)
		end
	end)
end



--//
Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		applyRagdollToCharacter(char)

		if fixVoidBug then
			char.ChildRemoved:Connect(function() --this fixes the void bug
				if char.WorldPivot.Position.Y <= workspace.FallenPartsDestroyHeight then	
					char.Humanoid.Health = 0 --so that the player just dies normaly when they fall into the void
				end
			end)
		end

	end)
end)
RagdollClient
--[[ System By @Liam 
-> Version 1.4.2
 ♥ Thanks for using this!! ♥ 
--]] 



--||Character||--
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local torso = char:FindFirstChild("Torso") or char:FindFirstChild("UpperTorso")

------------------------------------------------------------------------------------------------------------------





--//when the player gets ragdolled / unRagdolled
char:GetAttributeChangedSignal("IsRagdoll"):Connect(function()
	local isRagdoll = char:GetAttribute("IsRagdoll")
	if isRagdoll and torso then
		hum:ChangeState(Enum.HumanoidStateType.Ragdoll)
		hum:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
		torso:ApplyImpulse(torso.CFrame.LookVector * 75)
	else
		hum:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
end)

--//this happens when the player dies
hum.Died:Connect(function()
	if not torso then return end
	torso:ApplyImpulse(torso.CFrame.LookVector * 100)
end)

THE MODEL

HOW TO USE

END

Not much more to say, have a nice day. If you find bugs, tell me and I will try to fix them!

Cute cat here:

CAT

9 Likes

Update Version 1.4.3:

· If "ragdollOnDeath" is false it just breaks your character like normal // 01.11.2025
· Fixed not being able to reset when ragdolled // 01.11.2025
-> It was kinda fixed by just setting the humanoid health to 0 on the client, however I am still searching for a better method cuz it rn looks kinda weird, but it kinda works!
-> the only problem is that it not works when the character never again gets up, so when you just set IsRagdoll to true and then reset but never set it to false again before then you will not respawn.

example: 

char:SetAttribute("IsRagdoll", true)
--reset here and you will respawn
task.wait(2)
char:SetAttribute("IsRagdoll", false)

------------------------------------------------------------

char:SetAttribute("IsRagdoll", true)
--reset here and you will not respawn

Btw if anyone knows how to fix it good, it would be appreciated.
The problem is that the humanoid died not fires when they reset while being ragdolled

If the problem isn’t present for other forms of dying, you can just do :SetCore(“ResetButtonCallback”, someBindableEvent) to detect when the player wants to reset.

Also, side note, what in the heavens is that font you’re using for script editor :sob:

1 Like

I know about that, but this can only be done on the client, and I would rather have a direct fix on the Server. I mean, if I would do it on the client I could also just use remote events you know- but I am searching for a method to avoid that, that’s my point.

Is there something wrong with my font, lol? I really like it and think it’s nice to read.

Ok so I think I found out why, you’re using the Ragdoll humanoid state which can’t actually be automatically changed by the Humanoid and has to be changed manually with :ChangeState() (it says so in the docstring!), and since Dead is a humanoid state it kinda breaks that.

The solution, I think, would be to just find an alternative to the Ragdoll humanoid state. It is deprecated, afterall.

Also, it’s not that there necessarily anything wrong about your font, it’s just that it looks too contrasted and bold for me, my bad if it’s offensive though xd

Alright, thanks for the Info. I’ll look into it when I have time.

And nah everythings fine, no worries xD