How to make ragdoll effect on character?

How can I make a ragdoll effect on my player? I want the player to fall down onto the ground but not have the parts clip through the ground or the player to spam out. I was looking at some other posts but I could not exactly find what I was looking for or was not able to make anything work. Was wondering if anyone could help me out?


Functions["Ragdoll"] = function(Chr: Model, Enabled: boolean)
	-- Validate Chr
	-------------------------
	assert(Chr ~= nil, "[MainScript.Ragdoll] Chr argument is nil")
	assert(typeof(Chr) == "Instance" and Chr:IsA("Model"),
		(`[MainScript.Ragdoll] 'Chr' must be Model, got {typeof(Chr)}`))

	local humanoid = Chr:FindFirstChildOfClass("Humanoid")
	if not humanoid then return end
	
	--	Validate Bool
	-------------------------------
	assert(typeof(Enabled) == "boolean",
		(`[MainScript.Ragdoll] 'Enabled' must be boolean, got {typeof(Enabled)}`))


	if Enabled == true then
		--Enable ragdoll
	
	elseif Enabled == false then
		--Disable ragdoll

		
	end
end

I have this version as well but this version clips through the ground and spams out


Functions["Ragdoll"] = function(Chr: Model, Enabled: boolean)
	--Ragdoll effect for the players.
	
	-- Validate Chr
	-------------------------
	assert(Chr ~= nil, "[MainScript.Ragdoll] Chr argument is nil")
	assert(typeof(Chr) == "Instance" and Chr:IsA("Model"),
		(`[MainScript.Ragdoll] 'Chr' must be Model, instead got {typeof(Chr)}`))

	local humanoid = Chr:FindFirstChildOfClass("Humanoid")
	if not humanoid then return; end
	
	--	Validate Bool
	-------------------------------
	assert(typeof(Enabled) == "boolean",
		(`[MainScript.Ragdoll] 'Enabled' must be boolean, instead got {typeof(Enabled)}`))


	if Enabled then
		-- enable ragdoll
		humanoid:ChangeState(Enum.HumanoidStateType.Physics)
		for _, motor in ipairs(Chr:GetDescendants()) do
			if motor:IsA("Motor6D") then
				local socket = Instance.new("BallSocketConstraint")
				local attachment0 = Instance.new("Attachment")
				local attachment1 = Instance.new("Attachment")

				attachment0.CFrame = motor.C0
				attachment1.CFrame = motor.C1
				attachment0.Parent = motor.Part0
				attachment1.Parent = motor.Part1

				socket.Attachment0 = attachment0
				socket.Attachment1 = attachment1
				socket.LimitsEnabled = true
				socket.TwistLimitsEnabled = true
				socket.Parent = motor.Part0

				motor.Enabled = false
				motor.Name = "_RagdollDisabled"
			--elseif motor:IsA("BasePart") or motor:IsA("MeshPart") then --spams 
			--	motor.CanCollide = true
			end
		end
	else
		-- disable ragdoll
		for _, obj in ipairs(Chr:GetDescendants()) do
			if obj:IsA("Motor6D") and obj.Name == "_RagdollDisabled" then
				obj.Enabled = true
				obj.Name = "Motor6D"
			elseif obj:IsA("BallSocketConstraint") then
				obj:Destroy()
			elseif obj:IsA("Attachment") and obj.Parent and obj.Parent:IsA("BasePart") then
				-- remove ragdoll attachments only if they were added during ragdoll
				if obj.Name == "Attachment" then
					obj:Destroy()
				end
			end
		end
		humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
end


1 Like

There are countless ragdoll related topics on devforum and I refuse to believe that you didn’t find one to your satisfication.

For instance this one has a video of exactly what you mention in your post:

Nah thats too much need less. Plus never came across that and its not what im looking for.

1 Like

Apparently that’s exactly what the video shows

Yea but there has to be something more simpler than that. Bro look at how much code that mf did I dont need all that. Im looking for something simple to put in this function lol im not really trying to use a whole module unless I REALLY have too. Thats why im asking to see if there is something simpler out there cause all the modules I looked at were complicated for what.

None of the modules out there are complicated all, if you are really concerned about the no.of lines just go through the code take out whatever is relevant to you and implement it. There is no point in reinventing the wheel when there are tons of sources out there

1 Like

Alright what should I swap out then cause idk

Here’s a ragdoll module I made that works for all players and custom NPC’s.

local PlayerService = game:GetService("Players")
local RunService = game:GetService("RunService")
if RunService:IsServer() then
	local PhysicsService = game:GetService("PhysicsService") -- errors if script requiring this module is Client
	PhysicsService:RegisterCollisionGroup("Ragdoll")
	PhysicsService:CollisionGroupSetCollidable("Ragdoll","Ragdoll",false)
end

local PhysicsState = Enum.HumanoidStateType.Physics
local GettingUp = Enum.HumanoidStateType.GettingUp
local JumpState = Enum.HumanoidStateType.Jumping

local module = {}

function module.newRagdoll(Char:Instance)
	local newThing = {
		HumRoot = Char.HumanoidRootPart::Part,
		Humanoid = Char.Humanoid::Humanoid,
		Sockets = {}, -- { [BallSockets] = true }
		MotorDs = {}, -- { [Motor6D] = true }
		OG = {}, -- { [BodyPart] = {CollisionGroup, CanCollide} }
	}
	for _,Obj in Char:GetDescendants() do
		if Obj.ClassName == "Motor6D" then
			local Part0 = Obj.Part0
			local Part1 = Obj.Part1
			if Obj.Parent.Name == "HumanoidRootPart" then
				if not newThing.OG[Part0] then newThing.OG[Part0] = {Part0.CollisionGroup,Part0.CanCollide} end
				if not newThing.OG[Part1] then newThing.OG[Part1] = {Part1.CollisionGroup,Part1.CanCollide} end
				continue -- doesn't set attachments and stuff for rootparts
			end
			local Attach0 = Instance.new("Attachment")
			Attach0.CFrame = Obj.C0

			local Attach1 = Instance.new("Attachment")
			Attach1.CFrame = Obj.C1

			local Socket = Instance.new("BallSocketConstraint")
			Socket.Attachment0 = Attach0
			Socket.Attachment1 = Attach1
			Socket.Enabled = false

			if not newThing.OG[Part0] then newThing.OG[Part0] = {Part0.CollisionGroup,Part0.CanCollide} end
			if not newThing.OG[Part1] then newThing.OG[Part1] = {Part1.CollisionGroup,Part1.CanCollide} end

			newThing.MotorDs[Obj] = true
			newThing.Sockets[Socket] = true

			Attach0.Parent = Obj.Part0
			Attach1.Parent = Obj.Part1
			Socket.Parent = Char.HumanoidRootPart
		end
	end
	return newThing
end

type RagdollInstance = typeof(module.newRagdoll())

function module.Enter(newThing:RagdollInstance)
	newThing.Humanoid.JumpHeight = 0
	newThing.Humanoid.PlatformStand = true
	newThing.HumRoot.Massless = true
	newThing.Humanoid:ChangeState(PhysicsState)
	for MotorD in newThing.MotorDs do MotorD.Enabled = false end
	for Socket in newThing.Sockets do Socket.Enabled = true end
	task.delay(.1,function()
		for Part:Part in newThing.OG do Part.CollisionGroup,Part.CanCollide = "Ragdoll",true end
	end)
end

function module.Exit(newThing:RagdollInstance)
	for Socket in newThing.Sockets do Socket.Enabled = false end
	for MotorD in newThing.MotorDs do MotorD.Enabled = true end
	for Part:Part,OGTbl in newThing.OG do Part.CollisionGroup,Part.CanCollide = OGTbl[1],OGTbl[2] end
	newThing.Humanoid.PlatformStand = false
	newThing.HumRoot.Massless = false
	newThing.Humanoid:ChangeState(GettingUp)
	newThing.Humanoid.JumpHeight = 7.2
end

return module

You can easily test it using this:

local Ragdoll = require(script.Ragdoll) -- module is under script
local Part = script.Parent

local canUse = true
Part.Touched:Connect(function(hit)
	local Char = hit.Parent
	if Char:FindFirstChild("Humanoid") then
		if canUse then
			canUse = false
			Ragdoll.Enter(Ragdoll.newRagdoll(Char))
		end
	end
end)
1 Like

Yes this works. Thank you for the help. I am glad someone actually smart was able to help.. With this information, I was able to fit it into a module with how I need that works well. See below.

Module:

task.wait()

--Services:
local PlayerService = game:GetService("Players")
local RunService = game:GetService("RunService")
local PhysicsService = game:GetService("PhysicsService")

-- Collision group created once
if RunService:IsServer() then
	pcall(function()
		PhysicsService:RegisterCollisionGroup("Ragdoll")
	end)
	PhysicsService:CollisionGroupSetCollidable("Ragdoll","Ragdoll",false)
end

local Functions = {
	--returned functions:
	
	--Activate()
}
-- Storage per-character so setup only happens ONCE
local RagdollStates = {} -- [Character] = { HumRoot, Humanoid, Sockets, MotorDs, OG }
--------------------------				--------------------------------------
--- FUNCTIONS:
--

Functions["Activate"] = function(Chr: Model, Enabled: boolean)
	-- Validate Chr
	assert(Chr ~= nil, "[Ragdoll] Chr argument is nil")
	assert(typeof(Chr) == "Instance" and Chr:IsA("Model"),
		(`[Ragdoll] 'Chr' must be Model, got {typeof(Chr)}`))

	local humanoid = Chr:FindFirstChildOfClass("Humanoid")
	if not humanoid then return end

	-- Validate Bool
	assert(typeof(Enabled) == "boolean",
		(`[Ragdoll] 'Enabled' must be boolean, got {typeof(Enabled)}`))

	
	--SET UP:
	-------------------
	if not RagdollStates[Chr] then
		local HumRoot = Chr:FindFirstChild("HumanoidRootPart")
		if not HumRoot then return end

		local data = {
			HumRoot = HumRoot,
			Humanoid = humanoid,
			Sockets = {},    -- [BallSocketConstraint] = true
			MotorDs = {},    -- [Motor6D] = true
			OG = {},         -- [Part] = {CollisionGroup, CanCollide}
		}

		for _, Obj in ipairs(Chr:GetDescendants()) do
			if Obj:IsA("Motor6D") then
				local Part0 = Obj.Part0
				local Part1 = Obj.Part1

				-- Save original collision states
				if not data.OG[Part0] then
					data.OG[Part0] = { Part0.CollisionGroup, Part0.CanCollide }
				end
				if not data.OG[Part1] then
					data.OG[Part1] = { Part1.CollisionGroup, Part1.CanCollide }
				end

				-- Ignore root joint
				if Obj.Parent == HumRoot then
					continue;
				end

				-- Create attachments
				local Attach0 = Instance.new("Attachment")
				Attach0.CFrame = Obj.C0
				Attach0.Parent = Part0

				local Attach1 = Instance.new("Attachment")
				Attach1.CFrame = Obj.C1
				Attach1.Parent = Part1

				-- Create BallSocketConstraint
				local Socket = Instance.new("BallSocketConstraint")
				Socket.Attachment0 = Attach0
				Socket.Attachment1 = Attach1
				Socket.LimitsEnabled = true
				Socket.TwistLimitsEnabled = true
				Socket.Enabled = false
				Socket.Parent = Chr

				data.MotorDs[Obj] = true
				data.Sockets[Socket] = true
			end
		end

		RagdollStates[Chr] = data
	end
	local RD = RagdollStates[Chr]

	--BOOLEAN 
	if Enabled == true then
		-- ENTER RAGDOLL 
		--------------------------
		humanoid.JumpHeight = 0
		humanoid.PlatformStand = true
		RD.HumRoot.Massless = true
		humanoid:ChangeState(Enum.HumanoidStateType.Physics)

		-- Disable Motor6D, enable BallSockets
		for motor in pairs(RD.MotorDs) do
			motor.Enabled = false
		end
		for socket in pairs(RD.Sockets) do
			socket.Enabled = true
		end

		-- After a short delay, change collision groups
		task.delay(0.1, function()
			for part, original in pairs(RD.OG) do
				part.CollisionGroup = "Ragdoll"
				part.CanCollide = true
			end
		end)

	elseif Enabled == false then
		-- EXIT RAGDOLL 
		-------------------------
		for socket in pairs(RD.Sockets) do
			socket.Enabled = false
		end
		for motor in pairs(RD.MotorDs) do
			motor.Enabled = true
		end

		for part, original in pairs(RD.OG) do
			part.CollisionGroup = original[1]
			part.CanCollide = original[2]
		end

		humanoid.PlatformStand = false
		RD.HumRoot.Massless = false
		humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
		humanoid.JumpHeight = 7.2
	end
end

--
------------------------------------
---EXPORTS:
return Functions;

Script (How to use):

local ragdoll = require(script.Ragdoll)
ragdoll.Activate(game.Workspace.Player1, true) --true/false