Ragdoll module for all character

This is just a small module script i made for rigging character for ragdolls. It works with every single rig (R6,R15 and custom characters).

The module can:

  • Auto ragdoll when state set to Ragdoll
  • Keep all accessories on death

  • Code:
local module = {}

local PhysicsService = game:GetService("PhysicsService")
PhysicsService:CreateCollisionGroup("Players")
PhysicsService:CreateCollisionGroup("Collider")
PhysicsService:CollisionGroupSetCollidable("Players","Collider",false)

function module:RigPlayer(Character : Model)
	local hum : Humanoid = Character:WaitForChild("Humanoid")
	local hrp : BasePart = Character:WaitForChild("HumanoidRootPart")
	
	assert(hum,Character.Name.." isnt a humanoid")
	
	hum:SetAttribute("RiggedUser",true)
	
	local Colliders = Instance.new("Folder",Character)
	Colliders.Name = "ColliderFolder"
	hum.BreakJointsOnDeath = false
	
	for _,v in pairs(Character:GetDescendants()) do
		if v:IsA("Motor6D") then
			local BallSocket = Instance.new("BallSocketConstraint",v.Part0)
			BallSocket.Name = "BC"
			v.Part1.CanCollide = false
			v.Part0.CanCollide = false

			PhysicsService:SetPartCollisionGroup(v.Part1,"Players")

			local Holder = Instance.new("Part",Colliders)
			Holder.Name = v.Part1.Name
			PhysicsService:SetPartCollisionGroup(Holder,"Collider")
			Holder.Size = v.Part1.Size/2
			Holder.CFrame = v.Part1.CFrame
			
			local Weld = Instance.new("WeldConstraint",Holder) Weld.Part0 = v.Part1 Weld.Part1 = Holder
			Holder.Transparency = 1
			Holder.Massless = true
			Holder.CanCollide = false

			local att1 = Instance.new("Attachment",v.Part0) att1.Name = "AttRag"
			local att2 = Instance.new("Attachment",v.Part1) att1.Name = "AttRag"
			att2.Position = v.C1.Position
			att1.WorldPosition= att2.WorldPosition

			BallSocket.LimitsEnabled = true
			BallSocket.TwistLimitsEnabled = true

			BallSocket.Attachment0 = att1
			BallSocket.Attachment1 = att2
			
			if v.Part0 ~= Character.PrimaryPart and v.Part1 ~= Character.PrimaryPart then
				hum.Ragdoll:Connect(function(val)
					Holder.CanCollide = val
					v.Enabled = not val
				end)
			else
				local WeldConstranint = Instance.new("WeldConstraint",hrp)
				WeldConstranint.Part0 = Character.PrimaryPart
				WeldConstranint.Part1 = Character.PrimaryPart == v.Part1 and v.Part0 or v.Part1
				WeldConstranint.Enabled = false
				
				hum.Ragdoll:Connect(function(val) WeldConstranint.Enabled = val end)
			end
			
			hum.Died:Connect(function() v:Destroy() end)
		end
	end
	
	hum.Ragdoll:Connect(function(val)
		Character:SetPrimaryPartCFrame(val and Character.PrimaryPart.CFrame or CFrame.new(Character.PrimaryPart.Position + Vector3.new(0,hum.HipHeight,0),Character.PrimaryPart.Position + Character.PrimaryPart.CFrame.LookVector * 5)) -- custom characters tend to get stuck sometimes, this prevents them (if u want you can remove it)
	end)
end

return module

here is a video example

Here are more examples:
https://i.gyazo.com/c5355ebccc8547b0ba4ca4d23e526825.mp4 - Custom Character
https://i.gyazo.com/1067022f48edd332702d00d7ee0ca30c.mp4 - R15 (Custom Mesh)
https://i.gyazo.com/7d732d88746703ffa393df1e8d787d8d.mp4 - R6
https://i.gyazo.com/88b09af43bb5b11caee49f0f63564c37.mp4 - R15 (Layered clothing)

Here is a module with Ragdoll script (Very bad lol)

Another version that you could try:

70 Likes

where do i put the ragdoll module?

2 Likes

Try putting in replicatedstorage and make script require(module location)

2 Likes

yeah but it still dont work it just do nothing

1 Like

You have to rig the player you want to ragdoll using the module then set their state to ragdoll for it to work.

2 Likes

Thanks for the Ragdoll Module! It took a bit of work to figure it out how you do Ragdolls with it, but I eventually got it.

For those of you struggling like I did here is some code that works for me.

Script (Server side)

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Character)
		task.wait(0.1)
		local RagdollModule = require(game.ServerScriptService.RagdollModule)
		RagdollModule:RigPlayer(Character)
	end)
end)

LocalScript (Client Side) at (game.StarterPlayer.StarterCharacterScripts.LocalScript)

local function ChangeRagdoll(ragdoll : boolean)
	local Character  = script.Parent
	local Humanoid : Humanoid = Character:WaitForChild("Humanoid")
	
	for _,v in pairs(Enum.HumanoidStateType:GetEnumItems()) do 
		if v ~= Enum.HumanoidStateType.Ragdoll and v ~= Enum.HumanoidStateType.None then 
			Humanoid:SetStateEnabled(v, (not ragdoll))
		end
	end

	task.wait(0.1)
	if ragdoll then
		Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
	else
		Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
end

Do Note: you are going to have to trigger the ChangeRagdoll function yourself. I triggered the function with a RemoteEvent because I wanted the server can control when the player enters Ragdoll (I did not show this here).

I hope this helped you all! :smile:

19 Likes

Is there a way to make this work with npcs?

How would I implement this for dead characters?

Just change hum.Ragdoll to hum.Died at the botttom of the script

2 Likes

You dont have to do anything, when you die it auto ragdolls it, just do module:RigPlayer(Character)

Yea you need the character of the npc and just do

module:RigPlayer(NPC)

Oh thanks. I overcomplicated things a little. I’ll let you know if it works or not

Hey your module works very well with player but for some reason it have this strange behavior with npcs:
https://gyazo.com/e739abd87ed0c8edafb97e8ececa8d9d

I got it working fine with npcs for some time but it randomly broke and it doesnt work fine anymore, maybe I did something wrong?

found the issue: the problem was that ragdoll connections was apparently being cleared

2 Likes

How would you do that exactly? Like for a npc or a player

Nice, but it doesn’t seem to work for me @kalabgs. I’m rigging each player’s characters upon join, and I know that’s not the problem because the RiggedUser attribute is appearing on the humanoid. Whenever a player dies, their body just falls flat and their head falls off and goes through the baseplate.

local function PlayerAdded(Player: Player)
	Player.CharacterAdded:Connect(function(character)
		RagdollModule:RigPlayer(character)
	end)
end
Players.PlayerAdded:Connect(PlayerAdded)
for _, v in ipairs(Players:GetPlayers()) do
	task.spawn(function()
		PlayerAdded(v)
	end)
end

Getting some weird issues. I rig when a character is added, although for certain characters, it says v.Part0 of the weld is nil. When I go into the explorer and look at the weld, it’s not nil.

Edit: I fixed it by waiting to rig the character until the first time I ragdoll them, although this does not seem efficient.

Ok, I need to ask

Why are you connecting the events to functions inside the for loop?

Not sure if he changed the state change value but it works now after changing the HumanoidStateType to Enum.HumanoidStateType.Physics instead of .Ragdoll

Link to the module isn’t working

Community Update Version
by me

I Decided to change some stuff back-end meaning visually it all should be the same.
What I changed:

  • No more collision groups or extra parts.
  • Different way to track character died.
  • Took the connections out of the for loop.
  • Added GettingUp state to recover the character from being in ragdoll.
  • Ragdoll on Humanoids death.

Update! (2023-05-28):

  • Removed connections completely out of module.
  • Added 3 ragdoll states instead (Ragdoll, Recover and Death) trigger them in server script that checks if humanoid state changed or if the player has died.

Usage is pretty much the same, except that you will now have to change humanoid state into gettingup for the character to stand back up to normal.

Usage is the same except now you handle connection functions outside the module and tell the module to perform its task from the script instead.

Example Localscript
local plr = game:GetService("Players").LocalPlayer
local char = script.Parent
local input = game:GetService("UserInputService")
local db = false

input.InputBegan:Connect(function(key)
	if key.KeyCode == Enum.KeyCode.P then
		if db == false then
			db = true
			--Ragdoll character!
			plr.Character.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
		else
			db = false
			--Recover character from ragdoll!
			plr.Character.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
		end
	end
end)

(also remember that in this module you have to use physics state to trigger ragdoll)

My update on this module:

Module(Updated)
local mod = {}

function mod:RigPlayer(Character : Model)
	local hum : Humanoid? = Character:WaitForChild("Humanoid")
	local hrp : BasePart? = Character:WaitForChild("HumanoidRootPart")

	assert(hum,Character.Name.." isnt a humanoid")

	hum.BreakJointsOnDeath = false
	local WeldConstranint = Instance.new("WeldConstraint",hrp)
	for _,v in pairs(Character:GetDescendants()) do
		if v:IsA("Motor6D") then
			local BallSocket = Instance.new("BallSocketConstraint",v.Part0)
			BallSocket.Name = "BC"
			if v.Part1 ~= Character.PrimaryPart and v.Part0 ~= Character.PrimaryPart then
				v.Part1.CanCollide = false
				v.Part0.CanCollide = false
			end

			local att1 = Instance.new("Attachment",v.Part0) att1.Name = "AttRag"
			local att2 = Instance.new("Attachment",v.Part1) att1.Name = "AttRag"
			att2.Position = v.C1.Position
			att1.WorldPosition= att2.WorldPosition

			BallSocket.LimitsEnabled = true
			BallSocket.TwistLimitsEnabled = true

			BallSocket.Attachment0 = att1
			BallSocket.Attachment1 = att2

			if v.Part0 == Character.PrimaryPart and v.Part1 ~= Character.PrimaryPart then
				WeldConstranint.Part0 = Character.PrimaryPart
				WeldConstranint.Part1 = v.Part1
				WeldConstranint.Enabled = false
			end
		end
	end
end

function mod:Ragdoll(Character : Model)
	local humanoid : Humanoid = Character:WaitForChild("Humanoid")
	for _, v in ipairs(Character:GetDescendants()) do
		if v:IsA("Motor6D") then
			if v.Part1 ~= Character.PrimaryPart and v.Part0 ~= Character.PrimaryPart then
				v.Part1.CanCollide = true
				v.Enabled = false
			else
				Character.PrimaryPart:FindFirstChild("WeldConstraint").Enabled = true
				Character.PrimaryPart.CanCollide = false
			end
		end
	end
end

function mod:Recover(Character : Model)
	local humanoid : Humanoid = Character:WaitForChild("Humanoid")
	for _, v in ipairs(Character:GetDescendants()) do
		if v:IsA("Motor6D") then
			if v.Part1 ~= Character.PrimaryPart and v.Part0 ~= Character.PrimaryPart then
				v.Part1.CanCollide = false
				v.Enabled = true
			else
				Character.PrimaryPart:FindFirstChild("WeldConstraint").Enabled = false
				Character.PrimaryPart.CanCollide = true
			end
		end
	end
end

function mod:Deathphysics(Character : Model)
	for _, v in ipairs(Character:GetDescendants()) do
		if v:IsA("Motor6D") then
			if v.Part1 ~= Character.PrimaryPart and v.Part0 ~= Character.PrimaryPart then
				v.Part1.CanCollide = true
				v:Destroy()
			else
				Character.PrimaryPart:FindFirstChild("WeldConstraint").Enabled = true
				Character.PrimaryPart.CanCollide = false
			end
		end
	end
end

return mod

The original can be found at the top of the page! This is not the original, this is a community updated version.

6 Likes