Hello,
I’m actually having issues with rag dolls for my game. I am trying to make so that when someone dies, it goes in rag doll. But they are actually floating 1/4 times. It is like the health is equal to zero but the humanoid is still alive. I am forced to clone the rag doll to make a different instance. But when they are created, there is 25 percent of chances to have floating rag dolls.
I have tried many things so far… Creating a loop to set health to 1 and then back to 0 to try to kill the humanoid… I tried to ChangeState instead of changing the Health… I even did both… I even tried to SetNetworkOwner of all the base parts to the server… It reduced the chances of the bug to happen.
Here are two photos of the bug:
Here is problematic piece of code.
function pnil(player : Player)
player.TeamColor = BrickColor.new("Institutional white")
if player.Character then
player.Character:Destroy()
player.Character = nil
end
wait(game.Players.RespawnTime)
if not player.Character and player.TeamColor == BrickColor.new("Institutional white") then
game:GetService("ServerStorage"):WaitForChild("BindEvents"):WaitForChild("Reseti"):Invoke(player, true)
end
end
-- Many things between this but I won't post all the code.
RagDollFunc.OnInvoke = function(plr)
if not isAllowed(plr) then
return
end
if plr.Character == nil then
return
end
plr.Character.Archivable = true
local Char = plr.Character:Clone()
plr.Character.Archivable = false
plr.Character.Parent = nil
if Char:FindFirstChild("CrouchValue") then
Char:FindFirstChild("CrouchValue"):Destroy()
end
if Char:FindFirstChild("Fax") then
Char:FindFirstChild("Fax"):Destroy()
end
if Char:FindFirstChild("C4Back") then
Char:FindFirstChild("C4Back"):Destroy()
end
for i,v in pairs(Char.Humanoid:FindFirstChildWhichIsA("Animator"):GetPlayingAnimationTracks()) do
v:Stop()
v:Destroy()
end
local h2 = Instance.new("Humanoid")
h2.Name = "Ragdoll"
h2.NameOcclusion = Enum.NameOcclusion.NoOcclusion
h2.BreakJointsOnDeath = false
local gvelo = Char.Torso.AssemblyLinearVelocity
Char.Humanoid:Destroy()
for _, v in pairs(Char:GetDescendants()) do
if v:IsA("Motor6D") then
local Att0, Att1 = Instance.new("Attachment"), Instance.new("Attachment")
Att0.CFrame = v.C0
Att1.CFrame = v.C1
Att0.Parent = v.Part0
Att1.Parent = v.Part1
local BSC = Instance.new("BallSocketConstraint")
BSC.LimitsEnabled = true
BSC.TwistLimitsEnabled = true
BSC.TwistLowerAngle = -20
BSC.TwistUpperAngle = 20
BSC.Attachment0 = Att0
BSC.Attachment1 = Att1
BSC.Name = v.Name
BSC.Parent = v.Part0
v:Destroy()
end
end
for _, v in pairs(Char:GetDescendants()) do
if v:IsA("BaseScript") then
v:Destroy()
end
end
Char.Parent = workspace.Debris
wait()
h2.Parent = Char
--[[
for _, v in pairs(Char:GetDescendants()) do
if v:IsA("BasePart") then
if v:CanSetNetworkOwnership() then
v:SetNetworkOwner(nil)
end
end
end
]]
--Char.Humanoid.PlatformStand = true
--Char.Humanoid:ChangeState(Enum.HumanoidStateType.Dead)
--Char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.)
--[[
Char.Ragdoll.Health = 0
Char.Ragdoll:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
Char.Ragdoll:ChangeState(Enum.HumanoidStateType.Ragdoll)
]]
h2:ChangeState(Enum.HumanoidStateType.Dead)
if gvelo.Magnitude > 1 then
Char.Torso:ApplyImpulse(gvelo * Vector3.new(100, 0, 100))
else
print("not using gvelo")
Char.Torso:ApplyImpulse(Char.Torso.CFrame.LookVector * -(Vector3.new(100, 0, 100).Magnitude))
end
--Char.Humanoid.PlatformStand = true
--[[
coroutine.resume(coroutine.create(function()
while Char.Parent and Char:FindFirstChild("Ragdoll") do
Char.Ragdoll.Health = 1
Char.Ragdoll:ChangeState(Enum.HumanoidStateType.Dead)
wait()
if not Char:FindFirstChild("Ragdoll") then
return
end
Char.Ragdoll.Health = 0
wait()
end
end))
]]
pnil(plr)
end
This is a really annoying issue that happens with a lot of ragdoll modules. The humanoid just doesn’t want to die, which is annoying. I’ve tried to figure it out before, but the best solution I found was to quickly set the Head’s parent to nil, then set it back to whatever it was.
Again, this probably isn’t the best solution, it’s just what worked for me.
Example:
local Head = --Replace this with the head
local oldParent = Head.Parent
Head.Parent = nil
task.defer(function()
task.wait()
-- Even more annoying, the time between deferring the function and it running
-- Isn't enough for it to kill the humanoid, so I had to put the task.wait()
Head.Parent = oldParent
end)
It didn’t worked. But I suspect it’s because the Humanoid is already considered dead. So I modified the code a bit to set humanoid’s health 100 before removing the head and replacing it. Still observing behaviour.
Hey,
Your solution works !
I just had to modify it a bit.
Here is the working code:
RagDollFunc.OnInvoke = function(plr)
plr.TeamColor = BrickColor.new("Institutional white")
if not isAllowed(plr) then
return
end
if plr.Character == nil then
return
end
plr.Character.Archivable = true
local Char = plr.Character:Clone()
plr.Character.Archivable = false
plr.Character.Parent = nil
--Char.Humanoid.Health = 100
--Char.Humanoid:ChangeState(Enum.HumanoidStateType.Running)
if Char:FindFirstChild("CrouchValue") then
Char:FindFirstChild("CrouchValue"):Destroy()
end
if Char:FindFirstChild("Fax") then
Char:FindFirstChild("Fax"):Destroy()
end
if Char:FindFirstChild("C4Back") then
Char:FindFirstChild("C4Back"):Destroy()
end
for i,v in pairs(Char.Humanoid:FindFirstChildWhichIsA("Animator"):GetPlayingAnimationTracks()) do
v:Stop()
v:Destroy()
end
local h2 = Instance.new("Humanoid")
h2.Name = "Ragdoll"
h2.NameOcclusion = Enum.NameOcclusion.NoOcclusion
h2.BreakJointsOnDeath = false
Char.Humanoid:Destroy()
local gvelo = Char.Torso.AssemblyLinearVelocity
for _, v in pairs(Char:GetDescendants()) do
if v:IsA("Motor6D") then
local Att0, Att1 = Instance.new("Attachment"), Instance.new("Attachment")
Att0.CFrame = v.C0
Att1.CFrame = v.C1
Att0.Parent = v.Part0
Att1.Parent = v.Part1
local BSC = Instance.new("BallSocketConstraint")
BSC.LimitsEnabled = true
BSC.TwistLimitsEnabled = true
BSC.TwistLowerAngle = -20
BSC.TwistUpperAngle = 20
BSC.Attachment0 = Att0
BSC.Attachment1 = Att1
BSC.Name = v.Name
BSC.Parent = v.Part0
v:Destroy()
end
end
for _, v in pairs(Char:GetDescendants()) do
if v:IsA("BaseScript") then
v:Destroy()
end
end
h2.Parent = Char
game["Run Service"].Heartbeat:Wait()
Char.Parent = workspace.Debris
--[[
for _, v in pairs(Char:GetDescendants()) do
if v:IsA("BasePart") then
if v:CanSetNetworkOwnership() then
v:SetNetworkOwner(nil)
end
end
end
]]
--Char.Humanoid.PlatformStand = true
--Char.Humanoid:ChangeState(Enum.HumanoidStateType.Dead)
--Char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.)
--[[
Char.Ragdoll.Health = 0
Char.Ragdoll:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
Char.Ragdoll:ChangeState(Enum.HumanoidStateType.Ragdoll)
]]
for i = 1, 5 do
game["Run Service"].Heartbeat:Wait()
end
-- Thanks to Inconcludable for providing the code.
local Head = Char:FindFirstChild("Head")
local oldParent = Head.Parent
Head.Parent = nil
for i = 1, 5 do
game["Run Service"].Heartbeat:Wait()
end
-- Even more annoying, the time between deferring the function and it running
-- Isn't enough for it to kill the humanoid, so I had to put the task.wait()
Head.Parent = oldParent
-- Fix code end
if gvelo.Magnitude > 1 then
Char.Torso:ApplyImpulse(gvelo * Vector3.new(100, 0, 100))
else
print("not using gvelo")
Char.Torso:ApplyImpulse(Char.Torso.CFrame.LookVector * -(Vector3.new(100, 0, 100).Magnitude))
end
--Char.Humanoid.PlatformStand = true
--[[
coroutine.resume(coroutine.create(function()
while Char.Parent and Char:FindFirstChild("Ragdoll") do
Char.Ragdoll.Health = 1
Char.Ragdoll:ChangeState(Enum.HumanoidStateType.Dead)
wait()
if not Char:FindFirstChild("Ragdoll") then
return
end
Char.Ragdoll.Health = 0
wait()
end
end))
]]
if plr.Character then
plr.Character:Destroy()
plr.Character = nil
end
end
After some investigations, the floating ragdolls was caused by Network Ownership going crazy, letting client simulates a floating ragdoll, the solution is to set the ownership of each parts to the server.