Temporary Ragdoll

i’ve seen many people ask for help in making a temporary ragdoll system, so i wrote one myself to post here as a resource! (this could also be tweaked as a permanent ragdoll or a ragdoll on death)

wait()
local Character = game.Players.LocalPlayer.Character
local Hm = Character:WaitForChild("Humanoid")
local HmHRP = Character.HumanoidRootPart
local UIS = game:GetService("UserInputService")
local Ragdolling = Instance.new("BoolValue")
Ragdolling.Value = false
Ragdolling.Parent = Character
local SocketType = "BallSocketConstraint"
local RagdollKey = Enum.KeyCode.R

UIS.InputBegan:connect(function(input)
	if input.KeyCode == RagdollKey then
		local PlayerParts = Character:GetDescendants()		
		for i,M6D in pairs(PlayerParts) do
			if M6D:IsA("Motor6D") then
				if M6D.Name ~= "Root" then
					if not M6D.Parent:FindFirstChildWhichIsA(SocketType) then
						local Socket = Instance.new(SocketType)
						M6D.Parent = M6D.Part1
						Socket.LimitsEnabled = true
						Socket.Radius = .25
						Socket.TwistLimitsEnabled = false
						Socket.TwistLowerAngle = 360
						Socket.TwistUpperAngle = -180
						Socket.UpperAngle = 90
						local M0,M1
						if not M6D.Part0:FindFirstChild(M6D.Name .. "RigAttachment") then
							print("A")
							M0 = Instance.new("Attachment")
							M0.Name = M6D.Name .. "RigAttachment"
							M0.Parent = M6D.Part0
							M0.CFrame = M6D.C0
							print(M0.Name .. "A0")
						end
						if not M6D.Part1:FindFirstChild(M6D.Name .. "RigAttachment") then
							M1 = Instance.new("Attachment")
							M1.Name = M6D.Name .. "RigAttachment"
							M1.Parent = M6D.Part1
							M1.CFrame = M6D.C1
							print(M1.Name .. "A1")
						end
						Socket.Parent = M6D.Parent	
						Socket.Attachment0 = M6D.Part0:FindFirstChild(M6D.Name .. "RigAttachment")
						Socket.Attachment1 = M6D.Part1:FindFirstChild(M6D.Name .. "RigAttachment")
						game.Workspace.CurrentCamera.CameraSubject = Character.Head
						M6D.Enabled = false
						Hm:ChangeState(Enum.HumanoidStateType.Physics)
						Ragdolling = true
						HmHRP.CanCollide = false
					end
				end
			end
		end
	end
end)

UIS.InputEnded:connect(function(input)
	if input.KeyCode == RagdollKey then
		local PlayerParts = Character:GetDescendants()	
		if Ragdolling == true then
			for i,M6DBSC in pairs(PlayerParts) do
				if M6DBSC:IsA(SocketType) then
					M6DBSC:Destroy()
				elseif M6DBSC:IsA("Motor6D") then
					M6DBSC.Enabled = true
				end
			end
			HmHRP.CFrame = HmHRP.CFrame + Vector3.new(0,2,0)
			HmHRP.CanCollide = true
			game.Workspace.CurrentCamera.CameraSubject = Character.Humanoid
			Hm:ChangeState(Enum.HumanoidStateType.GettingUp)
		end
	end
end)
20 Likes

Is this compatible with all rig types? (R6 & R15)

Also, you should update the code to use :Connect instead of :connect.

6 Likes

Yes I also see that most people use that mistake from old tutorials or old free scripts from the toolbox.

2 Likes

BallSocketConstraints are a nice way of making ragdolls, but the body-part-collisions feel unrealistic sometimes. Do these Angles work for every body part or is it a generalization?

Can you make a test-play place?

Nice resource :heart:

3 Likes

Can you explain the script and how you created it? It’s kinda odd getting it with it being a “ragdoll” but not knowing how it works.

2 Likes

It works by using BallSocketConstraints

Every Roblox character body part is held together using Motor6D welds.
This simply replaces those welds with something more elastic to hold the body parts together.
https://developer.roblox.com/en-us/articles/Constraints

A critique I have about the code though is he named the Character variable “Player” which is a little confusing because Players are a class of their own.

Here’s another resource for making Ragdolls

2 Likes

That resource only works for R15 ragdolling IIRC, hence I asked if this resource also works on R6.

1 Like

Will this work on R6 rigs?

1 Like

this doesnt work with R6 because default R6 rigs lack the attachments inside the bodyparts im using to position the ballsocketconstraint, however i might update the script to add those attachments if the character doesnt already have them

and also point taken with :connect

2 Likes

How do you add ragdoll temporary for r6?

Is there a way for it to be where they fall they ragdoll?

if its over some magnitude or velocity then make it ragdoll

over here

2 Likes

Where do i put this at? The top middle end?

You got me wrong you need to change that part so when the player is over a magnitude it will ragdoll

Well over here at the top remove this or leave it if you dont know how to make so when a player is at a certain magnitude it ragdolls

and at the bottom
just do wait so u dont need to let go of the key and not be ragdolledUIS.InputBegan:Connect(function(input) if wait(time u want) then

also here you can remove this at the bottom

but so you know this is client sided not server sided

So what am i deleting and adding to make is so they ragdoll when they fall? Because I did what you said but i didnt ragdoll

local Character = game.Players.LocalPlayer.Character
local Hm = Character:WaitForChild("Humanoid")
local HmHRP = Character.HumanoidRootPart
local UIS = game:GetService("UserInputService")
local Ragdolling = Instance.new("BoolValue")
Ragdolling.Value = false
Ragdolling.Parent = Character
local SocketType = "BallSocketConstraint"
local RagdollKey = Enum.KeyCode.r

UIS.InputBegan:connect(function(input)
	if input.KeyCode == RagdollKey then
		local PlayerParts = Character:GetDescendants()		
		for i,M6D in pairs(PlayerParts) do
			if M6D:IsA("Motor6D") then
				if M6D.Name ~= "Root" then
					if not M6D.Parent:FindFirstChildWhichIsA(SocketType) then
						local Socket = Instance.new(SocketType)
						M6D.Parent = M6D.Part1
						Socket.LimitsEnabled = true
						Socket.Radius = .25
						Socket.TwistLimitsEnabled = false
						Socket.TwistLowerAngle = 360
						Socket.TwistUpperAngle = -180
						Socket.UpperAngle = 90
						local M0,M1
						if not M6D.Part0:FindFirstChild(M6D.Name .. "RigAttachment") then
							print("A")
							M0 = Instance.new("Attachment")
							M0.Name = M6D.Name .. "RigAttachment"
							M0.Parent = M6D.Part0
							M0.CFrame = M6D.C0
							print(M0.Name .. "A0")
						end
						if not M6D.Part1:FindFirstChild(M6D.Name .. "RigAttachment") then
							M1 = Instance.new("Attachment")
							M1.Name = M6D.Name .. "RigAttachment"
							M1.Parent = M6D.Part1
							M1.CFrame = M6D.C1
							print(M1.Name .. "A1")
						end
						Socket.Parent = M6D.Parent	
						Socket.Attachment0 = M6D.Part0:FindFirstChild(M6D.Name .. "RigAttachment")
						Socket.Attachment1 = M6D.Part1:FindFirstChild(M6D.Name .. "RigAttachment")
						game.Workspace.CurrentCamera.CameraSubject = Character.Head
						M6D.Enabled = false
						Hm:ChangeState(Enum.HumanoidStateType.Physics)
						Ragdolling = true
						HmHRP.CanCollide = false
					end
				end
			end
		end
	end
end)

UIS.InputEnded:connect(function(input)
	if input.KeyCode == RagdollKey then
		local PlayerParts = Character:GetDescendants()	
		if Ragdolling == true then
			for i,M6DBSC in pairs(PlayerParts) do
				if M6DBSC:IsA(SocketType) then
					M6DBSC:Destroy()
				elseif M6DBSC:IsA("Motor6D") then
					M6DBSC.Enabled = true
				end
			end
			HmHRP.CanCollide = true
			game.Workspace.CurrentCamera.CameraSubject = Character.Humanoid
			Hm:ChangeState(Enum.HumanoidStateType.GettingUp)
		end
	end
end)
UIS.InputBegan:Connect(function(input) if wait(1) then
		
	end
end)```
Theres the code

i already updated it some days ago to where it creates the attachments necessary for the BallSocketConstraints, it should be compatible with any Character now as long as its rigged.

1 Like

How would you make it so everyone in the server is able to see the ragdoll? When I test it, it only shows for the client and not the server. I assume you would use events, but I’m not too familiar.

Thanks for the effort you put into doing this, you are such a wonderful person

You would use Remote events, and i just did that

the local script would become this, instead of running the Ragdolling and Unragdolling function within the local script itself, it fires a remote event to a server script in server script service (this is also more efficient as you could fire that event for any ragdolling use case and you would have the actual function only once)

wait()
local Character = game.Players.LocalPlayer.Character
local Hm = Character:WaitForChild("Humanoid")
local HmHRP = Character.HumanoidRootPart
local UIS = game:GetService("UserInputService")
local Ragdolling = Instance.new("BoolValue")
Ragdolling.Value = false
Ragdolling.Parent = Character
local SocketType = "BallSocketConstraint"
local RagdollKey = Enum.KeyCode.G
local Randomizer
local RE = game.ReplicatedStorage:WaitForChild("TempRagdoll")
local REB = game.ReplicatedStorage:WaitForChild("UnRagdoll")

UIS.InputBegan:connect(function(input)
	if input.KeyCode == RagdollKey then
		RE:FireServer(SocketType,Character)
		Character.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
		game.Workspace.CurrentCamera.CameraSubject = Character.Head
		Ragdolling = true
		HmHRP.CanCollide = false	
	end
end)

UIS.InputEnded:connect(function(input)
	if input.KeyCode == RagdollKey then
		HmHRP.CFrame = HmHRP.CFrame + Vector3.new(0,2,0)
		HmHRP.CanCollide = true
		Character.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
		game.Workspace.CurrentCamera.CameraSubject = Character.Humanoid
		REB:FireServer(SocketType,Ragdolling,Character)
	end
end)

and then you would have 2 Remote Events (one for Ragdolling and one for Unragdolling) and a server script in ServerScriptService along the lines of this

local RE = game.ReplicatedStorage:WaitForChild("TempRagdoll")
local REB = game.ReplicatedStorage:WaitForChild("UnRagdoll")

local function Ragdoll(player,SocketType,Character)
	local PlayerParts = Character:GetDescendants()
	for i,M6D in pairs(PlayerParts) do
		if M6D:IsA("Motor6D") then
			if M6D.Name ~= "Root" then
				if not M6D.Parent:FindFirstChildWhichIsA(SocketType) then
					local Socket = Instance.new(SocketType)
					M6D.Parent = M6D.Part1
					Socket.LimitsEnabled = true
					Socket.Radius = .25
					Socket.TwistLimitsEnabled = false
					Socket.TwistLowerAngle = 360
					Socket.TwistUpperAngle = -180
					Socket.UpperAngle = 90
					local M0,M1
					if not M6D.Part0:FindFirstChild(M6D.Name .. "RigAttachment") then
						print("A")
						M0 = Instance.new("Attachment")
						M0.Name = M6D.Name .. "RigAttachment"
						M0.Parent = M6D.Part0
						M0.CFrame = M6D.C0
						print(M0.Name .. "A0")
					end
					if not M6D.Part1:FindFirstChild(M6D.Name .. "RigAttachment") then
						M1 = Instance.new("Attachment")
						M1.Name = M6D.Name .. "RigAttachment"
						M1.Parent = M6D.Part1
						M1.CFrame = M6D.C1
						print(M1.Name .. "A1")
					end
					Socket.Parent = M6D.Parent	
					Socket.Attachment0 = M6D.Part0:FindFirstChild(M6D.Name .. "RigAttachment")
					Socket.Attachment1 = M6D.Part1:FindFirstChild(M6D.Name .. "RigAttachment")
					M6D.Enabled = false	
					M6D.Parent.Velocity = M6D.Parent.Velocity + M6D.Parent.CFrame.LookVector * math.random(-3,5)
				end
			end
		end
	end
end

local function Unragdoll(player,SocketType,Ragdolling,Character)
	local PlayerParts = Character:GetDescendants()	
	if Ragdolling == true then
		for i,M6DBSC in pairs(PlayerParts) do
			if M6DBSC:IsA(SocketType) then
				M6DBSC:Destroy()
			elseif M6DBSC:IsA("Motor6D") then
				M6DBSC.Enabled = true
			end
		end
	end	
end

RE.OnServerEvent:connect(Ragdoll)
REB.OnServerEvent:connect(Unragdoll)

Now this is more or less just a “port” as im sure you could rewrite it to use only one Remote event or
change some function orders to be in the server script so it runs better, also the Character parameter is there in case you want to ragdoll a separate NPC (ex: pushing them) not necesarily the client’s character

Thank you for this :grin: I’m gonna use it with my sinking ship game