Buggy Ragdoll Script

So, I’m making a game similar to slap battles, but my ragdoll script isn’t turning out how I want it to. All it does is makes the dummy flop on the floor then stand back up.

Currently:

What I want to achieve: (older build that got deleted due to other studio members)

My module script:

local ragdoll = {}

function ragdoll.Start(character)
	if character.Name == (nil or "Workspace") then return end
	if character.Values.Ragdoll.Value == true then return end

	local realrARM = character["Right Arm"]
	local reallARM = character["Left Arm"]

	local realrLEG = character["Right Leg"]
	local reallLEG = character["Left Leg"]

	character.Values.Ragdoll.Value = true

	character.Values.CanBeAttacked.Value = false

	character["Right Arm"].CanCollide = true
	character["Left Arm"].CanCollide = true

	character["Right Leg"].CanCollide = true
	character["Left Leg"].CanCollide = true

	local rARM = character["Right Arm"]:Clone()
	rARM.CollisionGroup = "Ragdoll"
	local lARM = character["Left Arm"]:Clone()
	lARM.CollisionGroup = "Ragdoll"

	local rLEG = character["Right Leg"]:Clone()
	rLEG.CollisionGroup = "Ragdoll"
	local lLEG = character["Left Leg"]:Clone()
	lLEG.CollisionGroup = "Ragdoll"

	--[[character["Right Arm"].CanCollide = false
	character["Left Arm"].CanCollide = false

	character["Right Leg"].CanCollide = false
	character["Left Leg"].CanCollide = false]]

--[[rARM.Name = "Ragdoll-RA"
	lARM.Name = "Ragdoll-LA"
	rLEG.Name = "Ragdoll-RL"
	lLEG.Name = "Ragdoll-LL"]]

	rARM.Parent = character
	lARM.Parent = character
	rLEG.Parent = character
	lLEG.Parent = character

	rARM.CFrame = character["Right Arm"].CFrame
	lARM.CFrame = character["Left Arm"].CFrame
	rLEG.CFrame = character["Right Leg"].CFrame
	lLEG.CFrame = character["Left Leg"].CFrame

	character.Torso["Right Shoulder"].Part1 = rARM
	character.Torso["Left Shoulder"].Part1 = lARM
	character.Torso["Right Hip"].Part1 = rLEG
	character.Torso["Left Hip"].Part1 = lLEG

	character["Right Arm"].Anchored = true
	character["Left Arm"].Anchored = true
	character["Right Leg"].Anchored = true
	character["Left Leg"].Anchored = true

	character["Right Arm"].Transparency = 1
	character["Left Arm"].Transparency = 1
	character["Right Leg"].Transparency = 1
	character["Left Leg"].Transparency = 1

	character["Right Arm"].CastShadow = false
	character["Left Arm"].CastShadow = false
	character["Right Leg"].CastShadow = false
	character["Left Leg"].CastShadow = false

	character["Right Arm"].CanTouch = false
	character["Left Arm"].CanTouch = false
	character["Right Leg"].CanTouch = false
	character["Left Leg"].CanTouch = false

	rARM.Anchored = false
	lARM.Anchored = false
	rLEG.Anchored = false
	lLEG.Anchored = false

	for i, joint in pairs(character:GetDescendants()) do
		if joint:IsA("Motor6D") then
			local socket = Instance.new("BallSocketConstraint")
			local a0 = Instance.new("Attachment")
			local a1 = Instance.new("Attachment")
			a0.Parent = joint.Part0
			a1.Parent = joint.Part1
			socket.Parent = joint.Parent
			socket.Attachment0 = a0
			socket.Attachment1 = a1
			a0.CFrame = joint.C0
			a1.CFrame = joint.C1
			socket.LimitsEnabled = true
			socket.TwistLimitsEnabled = true

			joint.Enabled = false
		end
	end

	character.Humanoid.WalkSpeed = 0
	character.Humanoid.JumpPower = 0

	character.Humanoid.PlatformStand = true

	character.Humanoid.AutoRotate = false
	character.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)

	local collisions = coroutine.create(function()
		while character and character.Values.Ragdoll.Value do
			rARM.CanCollide = true
			lARM.CanCollide = true

			rLEG.CanCollide = true
			lLEG.CanCollide = true
			wait(0.1)
		end
	end)

	coroutine.resume(collisions)

	character.Humanoid.Died:Connect(function()
		wait(0.5)
		realrARM:Destroy()
		reallARM:Destroy()

		realrLEG:Destroy()
		reallLEG:Destroy()
	end)
end

function ragdoll.Stop(character)
	if character.Humanoid:GetState() == Enum.HumanoidStateType.Dead then return end

	--character.HumanoidRootPart.Anchored = true
	--wait()
	--character.HumanoidRootPart.Anchored = false

	character.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)

	local hrp = character:FindFirstChild("HumanoidRootPart")
	local hum = character:FindFirstChild("Humanoid")
	for i,part in pairs(character:GetChildren()) do
		if part:IsA("Part") then
			if part.CollisionGroup == "Ragdoll" then
				part:Destroy()
			end
		end
	end

	character["Right Arm"].Anchored = false
	character["Left Arm"].Anchored = false
	character["Right Leg"].Anchored = false
	character["Left Leg"].Anchored = false

	character["Right Arm"].CanTouch = true
	character["Left Arm"].CanTouch = true
	character["Right Leg"].CanTouch = true
	character["Left Leg"].CanTouch = true

	character.Torso["Right Shoulder"].Part1 = character["Right Arm"]
	character.Torso["Left Shoulder"].Part1 = character["Left Arm"]
	character.Torso["Right Hip"].Part1 = character["Right Leg"]
	character.Torso["Left Hip"].Part1 = character["Left Leg"]

	character["Right Arm"].Transparency = 0
	character["Left Arm"].Transparency = 0
	character["Right Leg"].Transparency = 0
	character["Left Leg"].Transparency = 0

	character["Right Arm"].CastShadow = true
	character["Left Arm"].CastShadow = true
	character["Right Leg"].CastShadow = true
	character["Left Leg"].CastShadow = true

	for i, joint in pairs(character:GetDescendants()) do
		if joint:IsA("BallSocketConstraint") then
			joint:Destroy()
		end

		if joint:IsA("Motor6D") then
			joint.Enabled = true
		end
	end

	character.Values.Ragdoll.Value = false

	character.Values.CanBeAttacked.Value = true

	hum.WalkSpeed = 22
	hum.JumpPower = 42

	hum.AutoRotate = true
	hum.PlatformStand = false

	character.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)

	hum.Sit = true

	wait(0.1)

	hum.Sit = false
end

return ragdoll

P.S: What’s weird is, when I wait a few minutes, it suddenly works no problem.

1 Like

I might not be right, but i think it’s to do with network ownership

2 Likes

If you’re doing the ragdolling on the client, then it’ll require you to have network ownership of the other character (which is impossible on other players)
What you can do is a remote event that when the local script clicks, the remote event fires, and the server handles the cooldowns (to prevent exploiters firing the remote event constantly), the damage, and the ragdolling

Also just a quick tip:
Instead of

rARM.Parent = character
lARM.Parent = character
rLEG.Parent = character
lLEG.Parent = character

you can do

for _, arm in {rARM, lARM, rLEG, lLEG} do
 arm.Parent = character
end

and for other parts, you could use a table
:wink:
(i’m just assuming the ragdolling is handled on the client)

1 Like

Can you try this script and tell me if it works out? If not can you show the output given

local ragdoll = {}

function ragdoll.Start(character)
    -- Ensure character is valid and not already ragdolling
    if not character or not character:FindFirstChild("Values") then 
        print("Ragdoll Start: Invalid character or missing Values")
        return 
    end
    
    if character.Values.Ragdoll.Value then 
        print("Ragdoll Start: Already in ragdoll state for character:", character.Name)
        return 
    end
    
    -- Debugging information
    print("Ragdoll Start: Beginning ragdoll for character:", character.Name)

    local realRightArm = character:FindFirstChild("Right Arm")
    local realLeftArm = character:FindFirstChild("Left Arm")
    local realRightLeg = character:FindFirstChild("Right Leg")
    local realLeftLeg = character:FindFirstChild("Left Leg")
    local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")

    -- Check if critical parts exist
    if not humanoidRootPart then
        print("Ragdoll Start: HumanoidRootPart not found for character:", character.Name)
        return
    end

    -- Set the ragdoll flag to true
    character.Values.Ragdoll.Value = true
    character.Values.CanBeAttacked.Value = false

    -- Clone limbs for ragdolling
    local clonedRightArm = realRightArm:Clone()
    local clonedLeftArm = realLeftArm:Clone()
    local clonedRightLeg = realRightLeg:Clone()
    local clonedLeftLeg = realLeftLeg:Clone()

    -- Set collision group for cloned limbs
    clonedRightArm.CollisionGroup = "Ragdoll"
    clonedLeftArm.CollisionGroup = "Ragdoll"
    clonedRightLeg.CollisionGroup = "Ragdoll"
    clonedLeftLeg.CollisionGroup = "Ragdoll"

    -- Parent the cloned limbs to the character
    clonedRightArm.Parent = character
    clonedLeftArm.Parent = character
    clonedRightLeg.Parent = character
    clonedLeftLeg.Parent = character

    -- Set cloned limbs to the original part CFrames
    clonedRightArm.CFrame = realRightArm.CFrame
    clonedLeftArm.CFrame = realLeftArm.CFrame
    clonedRightLeg.CFrame = realRightLeg.CFrame
    clonedLeftLeg.CFrame = realLeftLeg.CFrame

    -- Replace motor parts with cloned limbs
    character.Torso["Right Shoulder"].Part1 = clonedRightArm
    character.Torso["Left Shoulder"].Part1 = clonedLeftArm
    character.Torso["Right Hip"].Part1 = clonedRightLeg
    character.Torso["Left Hip"].Part1 = clonedLeftLeg

    -- Hide original parts and make them uncollidable
    for _, part in pairs({realRightArm, realLeftArm, realRightLeg, realLeftLeg}) do
        part.Anchored = true
        part.Transparency = 1
        part.CanCollide = false
        part.CastShadow = false
    end

    -- Disable touch detection on original parts
    for _, part in pairs({realRightArm, realLeftArm, realRightLeg, realLeftLeg}) do
        part.CanTouch = false
    end

    -- Un-anchor cloned limbs
    for _, limb in pairs({clonedRightArm, clonedLeftArm, clonedRightLeg, clonedLeftLeg}) do
        limb.Anchored = false
    end

    -- Add BallSocketConstraints to replace Motor6D joints
    for _, joint in pairs(character:GetDescendants()) do
        if joint:IsA("Motor6D") then
            local socket = Instance.new("BallSocketConstraint")
            local attach0 = Instance.new("Attachment", joint.Part0)
            local attach1 = Instance.new("Attachment", joint.Part1)

            socket.Parent = joint.Parent
            socket.Attachment0 = attach0
            socket.Attachment1 = attach1
            socket.LimitsEnabled = true
            socket.TwistLimitsEnabled = true

            -- Set attachment CFrames based on the motor's C0 and C1
            attach0.CFrame = joint.C0
            attach1.CFrame = joint.C1

            joint.Enabled = false
        end
    end

    -- Disable humanoid movement
    character.Humanoid.WalkSpeed = 0
    character.Humanoid.JumpPower = 0
    character.Humanoid.PlatformStand = true -- Prevents standing back up
    character.Humanoid:ChangeState(Enum.HumanoidStateType.Physics) -- Forces ragdoll physics mode

    -- Apply knockback force (about 15 studs)
    local knockbackForce = 1500 -- Adjust based on desired force
    local bodyVelocity = Instance.new("BodyVelocity")
    bodyVelocity.Velocity = humanoidRootPart.CFrame.LookVector * -knockbackForce -- Knockback direction
    bodyVelocity.MaxForce = Vector3.new(5000, 5000, 5000) -- Adjust based on how strong you want the knockback to be
    bodyVelocity.Parent = humanoidRootPart

    -- Remove the knockback force after a short delay
    game.Debris:AddItem(bodyVelocity, 0.2)

    -- Debugging information
    print("Ragdoll Start: Applied knockback force")

    -- Coroutine to manage ragdoll collisions
    coroutine.wrap(function()
        while character and character.Values.Ragdoll.Value do
            clonedRightArm.CanCollide = true
            clonedLeftArm.CanCollide = true
            clonedRightLeg.CanCollide = true
            clonedLeftLeg.CanCollide = true
            wait(0.1)
        end
    end)()

    -- Timer to get up after 2 seconds
    wait(2)
    ragdoll.Stop(character)
end

function ragdoll.Stop(character)
    if not character or not character:FindFirstChild("Humanoid") then
        print("Ragdoll Stop: Invalid character or missing Humanoid")
        return 
    end
    
    if character.Humanoid:GetState() == Enum.HumanoidStateType.Dead then 
        print("Ragdoll Stop: Character is dead, cannot stop ragdoll")
        return 
    end

    -- Debugging information
    print("Ragdoll Stop: Stopping ragdoll for character:", character.Name)

    -- Reset the humanoid to normal state
    character.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)

    -- Restore original parts
    for _, part in pairs(character:GetChildren()) do
        if part:IsA("Part") and part.CollisionGroup == "Ragdoll" then
            part:Destroy()
        end
    end

    for _, part in pairs({character["Right Arm"], character["Left Arm"], character["Right Leg"], character["Left Leg"]}) do
        part.Anchored = false
        part.CanTouch = true
        part.Transparency = 0
        part.CastShadow = true
        part.CanCollide = true
    end

    -- Restore Motor6D joints
    character.Torso["Right Shoulder"].Part1 = character["Right Arm"]
    character.Torso["Left Shoulder"].Part1 = character["Left Arm"]
    character.Torso["Right Hip"].Part1 = character["Right Leg"]
    character.Torso["Left Hip"].Part1 = character["Left Leg"]

    for _, joint in pairs(character:GetDescendants()) do
        if joint:IsA("BallSocketConstraint") then
            joint:Destroy()
        end

        if joint:IsA("Motor6D") then
            joint.Enabled = true
        end
    end

    -- Reset the ragdoll flags and restore humanoid properties
    character.Values.Ragdoll.Value = false
    character.Values.CanBeAttacked.Value = true

    character.Humanoid.WalkSpeed = 22
    character.Humanoid.JumpPower = 42
    character.Humanoid.PlatformStand = false
    character.Humanoid.AutoRotate = true

    -- Debugging information
    print("Ragdoll Stop: Ragdoll ended, character restored")
end

return ragdoll
1 Like

Yeah, it didn’t work, and it outputted this btw,

Can you try this instead?

local ragdoll = {}

function ragdoll.Start(character)
    if character.Name == (nil or "Workspace") then return end
    if character.Values.Ragdoll.Value == true then return end

    local realrARM = character["Right Arm"]
    local reallARM = character["Left Arm"]
    local realrLEG = character["Right Leg"]
    local reallLEG = character["Left Leg"]

    character.Values.Ragdoll.Value = true
    character.Values.CanBeAttacked.Value = false

    -- Set collision
    character["Right Arm"].CanCollide = true
    character["Left Arm"].CanCollide = true
    character["Right Leg"].CanCollide = true
    character["Left Leg"].CanCollide = true

    local rARM = character["Right Arm"]:Clone()
    local lARM = character["Left Arm"]:Clone()
    local rLEG = character["Right Leg"]:Clone()
    local lLEG = character["Left Leg"]:Clone()

    rARM.Parent = character
    lARM.Parent = character
    rLEG.Parent = character
    lLEG.Parent = character

    rARM.CFrame = character["Right Arm"].CFrame
    lARM.CFrame = character["Left Arm"].CFrame
    rLEG.CFrame = character["Right Leg"].CFrame
    lLEG.CFrame = character["Left Leg"].CFrame

    -- Disable original joints
    character["Right Arm"].Anchored = true
    character["Left Arm"].Anchored = true
    character["Right Leg"].Anchored = true
    character["Left Leg"].Anchored = true

    character["Right Arm"].Transparency = 1
    character["Left Arm"].Transparency = 1
    character["Right Leg"].Transparency = 1
    character["Left Leg"].Transparency = 1

    -- Create joints
    for _, joint in pairs(character:GetDescendants()) do
        if joint:IsA("Motor6D") then
            joint.Enabled = false
            local socket = Instance.new("BallSocketConstraint")
            local a0 = Instance.new("Attachment")
            local a1 = Instance.new("Attachment")
            a0.Parent = joint.Part0
            a1.Parent = joint.Part1
            socket.Parent = joint.Parent
            socket.Attachment0 = a0
            socket.Attachment1 = a1
            a0.CFrame = joint.C0
            a1.CFrame = joint.C1
            socket.LimitsEnabled = true
            socket.TwistLimitsEnabled = true
        end
    end

    character.Humanoid.WalkSpeed = 0
    character.Humanoid.JumpPower = 0
    character.Humanoid.PlatformStand = true
    character.Humanoid.AutoRotate = false
    character.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)

    -- Apply knockback
    local knockbackDirection = (character.HumanoidRootPart.Position - Vector3.new(0, 0, 15)).unit * 15
    character.HumanoidRootPart.Velocity = knockbackDirection

    wait(2) -- Wait for 2 seconds before getting up

    ragdoll.Stop(character)
end

function ragdoll.Stop(character)
    if character.Humanoid:GetState() == Enum.HumanoidStateType.Dead then return end

    character.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)

    -- Destroy cloned parts
    for _, part in pairs(character:GetChildren()) do
        if part:IsA("Part") and part.Name:match("Ragdoll") then
            part:Destroy()
        end
    end

    character.Values.Ragdoll.Value = false
    character.Values.CanBeAttacked.Value = true

    character.Humanoid.WalkSpeed = 16
    character.Humanoid.JumpPower = 50

    character.Humanoid.AutoRotate = true
    character.Humanoid.PlatformStand = false

    wait(0.1)
end

return ragdoll

nope, it just breaks the dummy’s limbs off.

Give this a try

local ragdoll = {}

function ragdoll.Start(character)
    if character.Name == (nil or "Workspace") then return end
    if character.Values.Ragdoll.Value == true then return end

    character.Values.Ragdoll.Value = true
    character.Values.CanBeAttacked.Value = false

    -- Disable existing joints and create constraints
    for _, part in pairs(character:GetChildren()) do
        if part:IsA("Part") and part.Name ~= "HumanoidRootPart" then
            part.CanCollide = true
            part.Anchored = false

            -- Create a ball socket constraint for ragdoll effect
            local socket = Instance.new("BallSocketConstraint")
            socket.Parent = part
            socket.Attachment0 = Instance.new("Attachment", part)
            socket.Attachment1 = Instance.new("Attachment", character.HumanoidRootPart) -- Attach to root part

            socket.Attachment0.CFrame = part.CFrame
            socket.Attachment1.CFrame = character.HumanoidRootPart.CFrame
            socket.LimitsEnabled = true
            socket.TwistLimitsEnabled = true
        end
    end

    -- Set humanoid properties for ragdoll
    character.Humanoid.WalkSpeed = 0
    character.Humanoid.JumpPower = 0
    character.Humanoid.PlatformStand = true
    character.Humanoid.AutoRotate = false
    character.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)

    -- Apply knockback
    local knockbackDirection = (character.HumanoidRootPart.Position - Vector3.new(0, 0, 15)).unit * 15
    character.HumanoidRootPart.Velocity = knockbackDirection

    wait(2) -- Wait before getting up
    ragdoll.Stop(character)
end

function ragdoll.Stop(character)
    if character.Humanoid:GetState() == Enum.HumanoidStateType.Dead then return end

    character.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)

    -- Destroy constraints and reset properties
    for _, part in pairs(character:GetChildren()) do
        if part:IsA("Part") then
            for _, joint in pairs(part:GetChildren()) do
                if joint:IsA("BallSocketConstraint") then
                    joint:Destroy()
                end
            end
        end
    end

    character.Values.Ragdoll.Value = false
    character.Values.CanBeAttacked.Value = true

    character.Humanoid.WalkSpeed = 16
    character.Humanoid.JumpPower = 50
    character.Humanoid.AutoRotate = true
    character.Humanoid.PlatformStand = false
end

return ragdoll

doesn’t ragdoll at all now, but the issue was the network ownership. Thanks for trying to help out tho!

1 Like

I’m glad you could get it solved, apologies for wasting your time!

1 Like

All good, all good.

character limit lol

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.