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)
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?
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.
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.
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
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.
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.
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