I’ve created a module script which handles ragdolls, specifically ones meant to replicate the ones games use like Item Asylum (Player gets ragdolled and gets unragdolled after making a complete stop).
There are a few issues with the module script shown with the video below however. Those being:
The player doesn’t get unragdolled despite making a full stop.
The player seems to be softlocked when trying to reset while being ragdolled.
Script
local RagdollModule = {}
function RagdollModule.Ragdoll(Character)
local Humanoid = Character:WaitForChild("Humanoid")
Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
Humanoid.PlatformStand = true
for i,v in pairs(Character:GetDescendants()) do
if v:IsA("Motor6D") then
local ballSocketConstraint = Instance.new("BallSocketConstraint")
local attachment0 = Instance.new("Attachment")
local attachment1 = Instance.new("Attachment")
attachment0.Parent = v.Part0
attachment1.Parent = v.Part1
ballSocketConstraint.Parent = v.Parent
ballSocketConstraint.Attachment0 = attachment0
ballSocketConstraint.Attachment1 = attachment1
attachment0.CFrame = v.C0
attachment1.CFrame = v.C1
ballSocketConstraint.MaxFrictionTorque = 200
ballSocketConstraint.LimitsEnabled = true
ballSocketConstraint.TwistLimitsEnabled = true
v.Enabled = false
end
end
if Humanoid.MoveDirection.Magnitude == 0 then
task.wait(0.3)
for i,v in pairs(Character:GetDescendants()) do
if v:IsA("BallSocketConstraint") then
v:Destroy()
elseif v:IsA("Motor6D") then
v.Enabled = true
end
end
Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
Humanoid.PlatformStand = false
end
end
return RagdollModule
The above code is executed at the same time the player ragdolls. Consider using RunService.Stepped event instead, then for each player who ragdolls, add them to a table.
local RunService = game:GetService("RunService")
local UnragdollTimeDelay = 0.3
local MinimumVelocity = 0.05 -- The character won't be able to unragdoll if it's speed is almost, but not equal to 0.
local RagdollConnections = {} -- To deal with disconnecting events made by RagdollModule.Ragdoll()
local RagdolledCharacters = {}
local RagdollModule = {}
RunService.Stepped:Connect(function(_, DeltaTime)
for Character, TimeLeft in pairs(RagdolledCharacters) do
local MainPart = Character.PrimaryPart -- Assume the character has a PrimaryPart.
-- Check the PrimaryPart's velocity instead. Humanoid.MoveDirection is related to
-- the WALK direction of the character, not its velocity.
if MainPart.Velocity.Magnitude > MinimumVelocity then
RagdolledCharacters[Character] = UnragdollTimeDelay
continue -- Skip the next lines of code
end
-- If the character is still enough, start the countdown.
TimeLeft -= DeltaTime
RagdolledCharacters[Character] = TimeLeft
if TimeLeft > 0 then
continue
end
-- It's good to unragdoll the character at this point.
RagdollModule.Unragdoll(Character)
end
end)
local function _unlistCharacter(Character)
-- Disconnect the connections for Humanoid.Died and Model.Destroying made by RagdollSystem.Ragdoll()
for _, connection in ipairs(RagdollConnections) do
connection:Disconnect()
end
RagdollConnections[Character] = nil
RagdolledCharacters[Character] = nil
end
local function _listCharacter(Character)
-- Extra code just in case the character either: dies or is deleted.
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
local function _removeFromList()
_unlistCharacter(Character)
end
local Connections = {
Character.Destroying:Once(_removeFromList),
Humanoid.Died:Once(_removeFromList)
}
RagdolledCharacters[Character] = UnragdollTimeDelay -- Give this character a set time until it can be unragdolled.
RagdollConnections[Character] = Connections
end
function RagdollModule.Ragdoll(Character : Model)
-- Do not ragdoll if this character is already ragdolled.
if RagdolledCharacters[Character] ~= nil then return end
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
Humanoid.PlatformStand = true
for i,v in pairs(Character:GetDescendants()) do
if v:IsA("Motor6D") then
local ballSocketConstraint = Instance.new("BallSocketConstraint")
local attachment0 = Instance.new("Attachment")
local attachment1 = Instance.new("Attachment")
attachment0.Parent = v.Part0
attachment1.Parent = v.Part1
ballSocketConstraint.Parent = v.Parent
ballSocketConstraint.Attachment0 = attachment0
ballSocketConstraint.Attachment1 = attachment1
attachment0.CFrame = v.C0
attachment1.CFrame = v.C1
ballSocketConstraint.MaxFrictionTorque = 200
ballSocketConstraint.LimitsEnabled = true
ballSocketConstraint.TwistLimitsEnabled = true
v.Enabled = false
end
end
_listCharacter(Character)
end
function RagdollModule.Unragdoll(Character : Model)
-- Do not unragdoll if the character isn't even ragdolled.
if RagdolledCharacters[Character] == nil then return end
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
for i,v in pairs(Character:GetDescendants()) do
if v:IsA("BallSocketConstraint") then
v:Destroy()
elseif v:IsA("Motor6D") then
v.Enabled = true
end
end
Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
Humanoid.PlatformStand = false
_unlistCharacter(Character)
end
return RagdollModule