How can I make a ragdoll script that will not make the limbs of the rig go through floor when ragdoll, rig is not be able to walk while ragdoll, and not flinging when recover from ragdoll??
Script:
local function Ragdoll(Character: Model, RagdollType: string)
assert(typeof(RagdollType) == 'string', `{OutputMark} RagdollType is not a valid string!!`)
assert(typeof(Character) == 'Instance' and Character:IsA('Model') and Character:FindFirstChildWhichIsA('Humanoid'), `{OutputMark} Character is not a valid character!!`)
local Humanoid = Character:WaitForChild('Humanoid')
local HumanoidRootPart = Character:WaitForChild('HumanoidRootPart')
if RagdollType == 'Run' then
Humanoid.PlatformStand = true
HumanoidRootPart.CanCollide = false
for _, Obj in Character:GetDescendants() do
if Obj:IsA('Motor6D') then
local Socket, A1, A2 = Instance.new('BallSocketConstraint', Obj.Parent), Instance.new("Attachment", Obj.Part0), Instance.new("Attachment", Obj.Part1)
Socket:SetAttribute('RagdollAsset', '')
A1:SetAttribute('RagdollAsset', '')
A2:SetAttribute('RagdollAsset', '')
A1.CFrame = Obj.C0
A2.CFrame = Obj.C1
Socket.Attachment0 = A1
Socket.Attachment1 = A2
Socket.LimitsEnabled = true
Socket.TwistLimitsEnabled = true
Obj.Enabled = false
elseif Obj:IsA('BasePart') and Obj.Name ~= 'HumanoidRootPart' and not Obj.CanCollide then
Obj:SetAttribute('RagdollAsset', '')
Obj.CanCollide = true
end
end
elseif RagdollType == 'Recover' then
for _, Obj in Character:GetDescendants() do
if Obj:IsA('Motor6D') then
Obj.Enabled = true
elseif Obj:GetAttribute('RagdollAsset') then
if Obj:IsA('BasePart') then
if Obj.CanCollide then
Obj.CanCollide = false
end
else
Obj:Destroy()
end
end
end
Humanoid.PlatformStand = false
HumanoidRootPart.CanCollide = true
else
warn(`{OutputMark} {RagdollType} type is not a valid ragdoll type!!`)
end
end
For this you’d need to weld dummy parts to each of the character’s body parts when ragdolling. Make sure they’re smaller than the actual limbs so they don’t intersect weirdly with the other dummy parts
Try setting Humanoid.PlatformStand to true
Temporarily disable the HumanoidStateType.Ragdoll via humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false), then after some time set it back to true (I think it’s the ragdoll statetype that makes you fling but if this doesn’t make anything better let me know)
local function Ragdoll(Character: Model, RagdollType: string)
assert(typeof(RagdollType) == 'string', `{OutputMark} RagdollType is not a valid string!!`)
assert(typeof(Character) == 'Instance' and Character:IsA('Model') and Character:FindFirstChildWhichIsA('Humanoid'), `{OutputMark} Character is not a valid character!!`)
local Humanoid = Character:WaitForChild('Humanoid')
local HumanoidRootPart = Character:WaitForChild('HumanoidRootPart')
local BlacklistStates = {
Enum.HumanoidStateType.Ragdoll;
Enum.HumanoidStateType.FallingDown;
}
if RagdollType == 'Run' then
for _, State in BlacklistStates do
Humanoid:SetStateEnabled(State, false)
end
Humanoid.PlatformStand = true
HumanoidRootPart.CanCollide = false
for _, Obj in Character:GetDescendants() do
if Obj:IsA('Motor6D') then
local Socket, A1, A2 = Instance.new('BallSocketConstraint', Obj.Parent), Instance.new("Attachment", Obj.Part0), Instance.new("Attachment", Obj.Part1)
Socket:SetAttribute('RagdollAsset', '')
A1:SetAttribute('RagdollAsset', '')
A2:SetAttribute('RagdollAsset', '')
A1.CFrame = Obj.C0
A2.CFrame = Obj.C1
Socket.Attachment0 = A1
Socket.Attachment1 = A2
Socket.LimitsEnabled = true
Socket.TwistLimitsEnabled = true
Obj.Enabled = false
end
end
elseif RagdollType == 'Recover' then
for _, Obj in Character:GetDescendants() do
if Obj:IsA('Motor6D') then
Obj.Enabled = true
elseif Obj:GetAttribute('RagdollAsset') then
Obj:Destroy()
end
end
Humanoid.PlatformStand = false
HumanoidRootPart.CanCollide = true
task.delay(3, function()
print('Resetting state...')
for _, State in BlacklistStates do
Humanoid:SetStateEnabled(State, true)
end
end)
else
warn(`{OutputMark} {RagdollType} type is not a valid ragdoll type!!`)
end
end
I think it could have something to do with you doing it on the server, it doesn’t look like SetStateEnabled replicates to the client (judging by this post). Since players have network ownership of their own character, these states would still be enterable.
Could you try firing a remote to the client telling them to disable these states instead of directly doing it on the server?
local function Ragdoll(Character: Model, RagdollType: string)
assert(typeof(RagdollType) == 'string', `{OutputMark} RagdollType is not a valid string!!`)
assert(typeof(Character) == 'Instance' and Character:IsA('Model') and Character:FindFirstChildWhichIsA('Humanoid'), `{OutputMark} Character is not a valid character!!`)
local Humanoid: Humanoid = Character:WaitForChild('Humanoid')
local HumanoidRootPart: BasePart = Character:WaitForChild('HumanoidRootPart')
local BlacklistStates = {
Enum.HumanoidStateType.Ragdoll;
Enum.HumanoidStateType.FallingDown;
Enum.HumanoidStateType.PlatformStanding;
}
if RagdollType == 'Run' then
for _, State in BlacklistStates do
Humanoid:SetStateEnabled(State, false)
end
Humanoid.PlatformStand = true
HumanoidRootPart.CanCollide = false
for _, Obj in Character:GetDescendants() do
if Obj:IsA('Motor6D') then
local Socket, A1, A2 = Instance.new('BallSocketConstraint', Obj.Parent), Instance.new("Attachment", Obj.Part0), Instance.new("Attachment", Obj.Part1)
Socket:SetAttribute('RagdollAsset', '')
A1:SetAttribute('RagdollAsset', '')
A2:SetAttribute('RagdollAsset', '')
A1.CFrame = Obj.C0
A2.CFrame = Obj.C1
Socket.Attachment0 = A1
Socket.Attachment1 = A2
Socket.LimitsEnabled = true
Socket.TwistLimitsEnabled = true
Obj.Enabled = false
elseif Obj:IsA('BasePart') then
local NewObj = Instance.new('Part')
NewObj.CFrame = Obj.CFrame
NewObj.Size = Vector3.new(Obj.Size.X - 1, Obj.Size.Y - 1, Obj.Size.Z - 1)
NewObj.CanCollide = true
NewObj.Anchored = false
NewObj.Transparency = 1
NewObj.Name = 'CollisionPart'
NewObj.Parent = Obj
local NewWeld = Instance.new('WeldConstraint')
NewWeld.Parent = NewObj
NewWeld.Part0 = NewObj
NewWeld.Part1 = Obj
NewObj:SetAttribute('RagdollAsset', '')
end
end
print(Humanoid:GetState())
elseif RagdollType == 'Recover' then
for _, Obj in Character:GetDescendants() do
if Obj:IsA('Motor6D') then
Obj.Enabled = true
elseif Obj:GetAttribute('RagdollAsset') then
Obj:Destroy()
end
end
Humanoid.PlatformStand = false
HumanoidRootPart.CanCollide = true
print(Humanoid:GetState())
task.delay(3, function()
print('Resetting state...')
for _, State in BlacklistStates do
Humanoid:SetStateEnabled(State, true)
end
end)
else
warn(`{OutputMark} {RagdollType} type is not a valid ragdoll type!!`)
end
end
Roblox is notorious for making changing collisions on body parts really difficult.
The way I fixed this is by going through each limb in the character and creating a smaller replica and welding it to its corresponding body part and using that as the collider instead of the actual limb. It’s a little jank but so far is the only way I’ve seen to do limb physics properly.
for _,v in pairs(char:GetChildren()) do --For i,v loop to go through all the objects in the char
if v:IsA("MeshPart") then --Find all parts which are limbs since all limbs are meshes
print(v) --Debugging
--Create the part
local CollisionPart = Instance.new("Part")
CollisionPart.Parent = v
CollisionPart.CFrame = v.CFrame
CollisionPart.Size = v.Size/2 --Setting the size smaller because if they're too big it acts buggy
CollisionPart.Massless = true --Making sure we arent adding any extra weight to the character
CollisionPart.Transparency = 0
CollisionPart.Name = "COLLISION_PART"
CollisionPart.CanCollide = false --Set to false when create, find all parts named Collision part and set collision to true when ragdoll happens
--weld part to the corresponding body part
local Weld = Instance.new("WeldConstraint",CollisionPart)
Weld.Part0 = CollisionPart
Weld.Part1 = v
end
end
That’s very odd. I’m wondering if you could limit the character’s velocity for about a second while they get up. See if adding this gives you any better results while getting up:
local now = os.clock()
while os.clock() - now < 1 do
local velocity = HumanoidRootPart.AssemblyLinearVelocity
if velocity.Magnitude > 15 then -- let's say they're moving at more than 15 studs per second,
HumanoidRootPart.AssemblyLinearVelocity = velocity.Unit * 15
end
end
Thank you for helping. I fixed it by disabling the states on client-side instead on server-side for player and for npc I set state on server.
local function Ragdoll(Character: Model, RagdollType: string)
assert(typeof(RagdollType) == 'string', `{OutputMark} RagdollType is not a valid string!!`)
assert(typeof(Character) == 'Instance' and Character:IsA('Model') and Character:FindFirstChildWhichIsA('Humanoid'), `{OutputMark} Character is not a valid character!!`)
local Player = Players:GetPlayerFromCharacter(Character)
local Humanoid: Humanoid = Character:WaitForChild('Humanoid')
local HumanoidRootPart: BasePart = Character:WaitForChild('HumanoidRootPart')
local BlacklistStates = {
Enum.HumanoidStateType.FallingDown;
Enum.HumanoidStateType.Ragdoll;
}
if RagdollType == 'Run' then
if StateThread then
task.cancel(StateThread)
end
HumanoidRootPart.CanCollide = false
Humanoid.PlatformStand = true
if Player then
print('Fire to client')
Replicator:FireClient(Player, 'SetClientHumanoidState', {
States = {'FallingDown','Ragdoll'};
SetType = false
})
else
for _, State in BlacklistStates do
Humanoid:SetStateEnabled(State, false)
end
end
for _, Obj in Character:GetDescendants() do
if Obj:IsA('Motor6D') then
local Socket, A1, A2 = Instance.new('BallSocketConstraint', Obj.Parent), Instance.new("Attachment", Obj.Part0), Instance.new("Attachment", Obj.Part1)
Socket:SetAttribute('RagdollAsset', '')
A1:SetAttribute('RagdollAsset', '')
A2:SetAttribute('RagdollAsset', '')
A1.CFrame = Obj.C0
A2.CFrame = Obj.C1
Socket.Attachment0 = A1
Socket.Attachment1 = A2
Socket.LimitsEnabled = true
Socket.TwistLimitsEnabled = true
Obj.Enabled = false
elseif Obj:IsA('BasePart') then
local NewObj = Instance.new('Part')
NewObj.CFrame = Obj.CFrame
NewObj.Size = Vector3.new(Obj.Size.X - 1, Obj.Size.Y - 1, Obj.Size.Z - 1)
NewObj.CanCollide = true
NewObj.Anchored = false
NewObj.Transparency = 1
NewObj.Name = 'CollisionPart'
NewObj.Parent = Obj
local NewWeld = Instance.new('WeldConstraint')
NewWeld.Parent = NewObj
NewWeld.Part0 = NewObj
NewWeld.Part1 = Obj
NewObj:SetAttribute('RagdollAsset', '')
end
end
elseif RagdollType == 'Recover' then
for _, Obj in Character:GetDescendants() do
if Obj:GetAttribute('RagdollAsset') then
Obj:Destroy()
elseif Obj:IsA('Motor6D') then
Obj.Enabled = true
end
end
HumanoidRootPart.CanCollide = true
Humanoid.PlatformStand = false
StateThread = task.delay(1, function()
if Player then
Replicator:FireClient(Player, 'SetClientHumanoidState', {
States = {'FallingDown','Ragdoll'};
SetType = true
})
else
for _, State in BlacklistStates do
Humanoid:SetStateEnabled(State, true)
end
end
end)
else
warn(`{OutputMark} {RagdollType} type is not a valid ragdoll type!!`)
end
end