Hello, I’ve been making a fighting game with friends, and so far it’s been going pretty well, except for one problem:
The ragdoll system is buggy
Some bugs that with it:
-Ragdolled user is flung after getting up
-Ragdolled user can “float” (ragdolled but still has normal control)
-Ragdolled user unragdolls but stays on the floor unable to move for a while longer
Please keep in mind that local solutions might not be the best, as NPCs can also be ragdolled.
Here is my code:
local function ragdoll(char:Model,humanoid:Humanoid)
--humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, false)
humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
humanoid.PlatformStand = true
for i,joint in pairs(char:GetDescendants()) do
if typeof(joint) == "Instance" and joint:IsA("Motor6D") then
local attach1 = Instance.new("Attachment")
attach1.CFrame = joint.C0
attach1.Parent = joint.Part0
local attach2 = Instance.new("Attachment")
attach2.CFrame = joint.C1
attach2.Parent = joint.Part1
local socket = Instance.new("BallSocketConstraint")
socket.Attachment0 = attach1
socket.Attachment1 = attach2
socket.LimitsEnabled = true
socket.TwistLimitsEnabled = true
socket.Parent = joint.Parent
joint.Enabled = false
end
end
end
local function unragdoll(char:Model,humanoid:Humanoid)
for i,thing in pairs(char:GetDescendants()) do
if typeof(thing) == "Instance" then
if thing:IsA("BallSocketConstraint") then
thing:Destroy()
elseif thing:IsA("Motor6D") then
thing.Enabled = true
end
end
end
--humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, true)
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
local bodyvel = Instance.new("BodyVelocity")
bodyvel.MaxForce = Vector3.new(0,1,0)*300000
bodyvel.P = 25000
bodyvel.Velocity = Vector3.new(0,0,0)
bodyvel.Parent = char.HumanoidRootPart
game.Debris:AddItem(bodyvel,0.25)
--preventFling(char)
humanoid.PlatformStand = false
humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end
Note: The BodyVelocity made in the Unragdoll function was a test solution to try and fix the flinging bug, didn’t really fix it that well
for point 2. i would suggest instead of making the players state become “ragdoll”, that it be changed to “PlatformStanding”, as this means it will permanently be stuck in ragdoll and wont try to readjust back into the gettingup state by itself until changed.
for the other two, this is mainly dependant on the way Humanoids actually get up. if upside down or in a weird orientation, like point 3, they may get ragdolled again when trying to get up which makes the ragdoll seem longer than set to be. for point 1, sometimes when this get up state change fails, the force that would have been neutralised when making the character rapidly move into the standing animation is left untouched which means that it sends the character, while ragdolled, flying. for both these points, i would suggest teleporting the character into its right position, stood up, before letting the humanoid get up, so that once the humanoid tries standing up it minimalizes any stupid failures!
I changed it a bit based on what you said, would this be better?
local function ragdoll(char:Model,humanoid:Humanoid)
--humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
humanoid.PlatformStand = true
for i,joint in pairs(char:GetDescendants()) do
if typeof(joint) == "Instance" and joint:IsA("Motor6D") then
local attach1 = Instance.new("Attachment")
attach1.CFrame = joint.C0
attach1.Parent = joint.Part0
local attach2 = Instance.new("Attachment")
attach2.CFrame = joint.C1
attach2.Parent = joint.Part1
local socket = Instance.new("BallSocketConstraint")
socket.Attachment0 = attach1
socket.Attachment1 = attach2
socket.LimitsEnabled = true
socket.TwistLimitsEnabled = true
socket.Parent = joint.Parent
joint.Enabled = false
end
end
end
local function unragdoll(char:Model,humanoid:Humanoid)
for i,thing in pairs(char:GetDescendants()) do
if typeof(thing) == "Instance" then
if thing:IsA("BallSocketConstraint") then
thing:Destroy()
elseif thing:IsA("Motor6D") then
thing.Enabled = true
end
end
end
--humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, true)
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
--[[local bodyvel = Instance.new("BodyVelocity")
bodyvel.MaxForce = Vector3.new(0,1,0)*300000
bodyvel.P = 25000
bodyvel.Velocity = Vector3.new(0,0,0)
bodyvel.Parent = char.HumanoidRootPart
game.Debris:AddItem(bodyvel,0.25)--]]
--preventFling(char)
humanoid.PlatformStand = false
humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
char.HumanoidRootPart.CFrame += Vector3.new(0,1.5,0)
end
this line isnt very necessary as once the Humanoid is put into the PlatformStand state, it will be forced into ragdoll and wont try to change its state back until you change this variable back.
however as i said you will need to actually teleport the player back standing up manually so the humanoid wont freak out on occasions when it tries to do it itself
local collisionChangeBlacklist = {"Handle","Torso","HumanoidRootPart","Head"}
local function ragdoll(char:Model,humanoid:Humanoid)
humanoid.PlatformStand = true
for i,thing in pairs(char:GetDescendants()) do
if typeof(thing) == "Instance" then
if thing:IsA("Motor6D") then
local attach1 = Instance.new("Attachment")
attach1.CFrame = thing.C0
attach1.Parent = thing.Part0
local attach2 = Instance.new("Attachment")
attach2.CFrame = thing.C1
attach2.Parent = thing.Part1
local socket = Instance.new("BallSocketConstraint")
socket.Attachment0 = attach1
socket.Attachment1 = attach2
socket.LimitsEnabled = true
socket.TwistLimitsEnabled = true
socket.Parent = thing.Parent
thing.Enabled = false
elseif thing:IsA("BasePart") and not table.find(collisionChangeBlacklist,thing.Name) then
thing.CanCollide = true
end
end
end
end
local function unragdoll(char:Model,humanoid:Humanoid)
for i,thing in pairs(char:GetDescendants()) do
if typeof(thing) == "Instance" then
if thing:IsA("BallSocketConstraint") then
thing:Destroy()
elseif thing:IsA("Motor6D") then
thing.Enabled = true
elseif thing:IsA("BasePart") and not table.find(collisionChangeBlacklist,thing.Name) then
thing.CanCollide = false
end
end
end
char.HumanoidRootPart.CFrame = (char.HumanoidRootPart.CFrame + Vector3.new(0,2,0)) * CFrame.Angles(math.rad(-90),0,0)
humanoid.PlatformStand = false
--humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
end
sir yes sir, repeating this for character count but when/if you implement the teleport into standing position function, remember to make it run before you set the PlatformStand variable back to false in the unragdoll function or else the Humanoid will ignore the teleport and try to stand up again as soon as you change the variable
The teleport-into-standing-position function is already implemented, if you look in the unragdoll function, right before the end, you’ll see the teleport function which is done right before PlatformStand is set to false.