Ragdoll not working on NPCs, works perfectly fine on players

The script works fine in the player version, but after a random amount of time for NPCs it causes their torso to kinda not move or whatever. I even tried using the player version on the NPCs instead and it just had the same issues.

And I know in the video the ragdoll bugs out after I use my grab, but that was just inconvenient timing. I tried without using the grab and it still has the same issue.

--> Perfect R6 Ragdoll (NPC Version) by CompletedLoop
--> June 11, 2023

--> Make sure this script is located under the Character Model
local Character: Model = script.Parent
local Torso: BasePart = Character:WaitForChild("Torso")
local Humanoid: Humanoid = Character:FindFirstChildOfClass("Humanoid")

--> Necessary for Ragdolling to function properly
Character.Humanoid.BreakJointsOnDeath = false
Character.Humanoid.RequiresNeck = false

--> Specific CFrame's I made for the best looking Ragdoll
local attachmentCFrames = {
	["Neck"] = {CFrame.new(0, 1, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1), CFrame.new(0, -0.5, 0, 0, -1, 0, 1, 0, -0, 0, 0, 1)},
	["Left Shoulder"] = {CFrame.new(-1.3, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1), CFrame.new(0.2, 0.75, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1)},
	["Right Shoulder"] = {CFrame.new(1.3, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CFrame.new(-0.2, 0.75, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)},
	["Left Hip"] = {CFrame.new(-0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1), CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)},
	["Right Hip"] = {CFrame.new(0.5, -1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1), CFrame.new(0, 1, 0, 0, 1, -0, -1, 0, 0, 0, 0, 1)},
}

local ragdollInstanceNames = {
	["RagdollAttachment"] = true,
	["RagdollConstraint"] = true,
	["ColliderPart"] = true,
}

--> Used to trigger Ragdoll
local RagdollValue = Character.Values.Status.Ragdolled
-------------------------------------------------------------------------------------------------

--> push :)
local function push()
	Torso:ApplyImpulse(Torso.CFrame.LookVector * 100)
end

--> Allows for proper limb collisions
local function createColliderPart(part: BasePart)
	if not part then return end
	local rp = Instance.new("Part")
	rp.Name = "ColliderPart"
	rp.Size = part.Size/1.7
	rp.Massless = true			
	rp.CFrame = part.CFrame
	rp.Transparency = 1

	local wc = Instance.new("WeldConstraint")
	wc.Part0 = rp
	wc.Part1 = part

	wc.Parent = rp
	rp.Parent = part
end

--> Converts Motor6D's into BallSocketConstraints
function replaceJoints()
	for _, motor: Motor6D in pairs(Character:GetDescendants()) do
		if motor:IsA("Motor6D") then
			if not attachmentCFrames[motor.Name] then return end
			motor.Enabled = false;
			local a0, a1 = Instance.new("Attachment"), Instance.new("Attachment")
			a0.CFrame = attachmentCFrames[motor.Name][1]
			a1.CFrame = attachmentCFrames[motor.Name][2]

			a0.Name = "RagdollAttachment"
			a1.Name = "RagdollAttachment"

			createColliderPart(motor.Part1)

			local b = Instance.new("BallSocketConstraint")
			b.Attachment0 = a0
			b.Attachment1 = a1
			b.Name = "RagdollConstraint"

			b.Radius = 0.15
			b.LimitsEnabled = true
			b.TwistLimitsEnabled = false
			b.MaxFrictionTorque = 0
			b.Restitution = 0
			b.UpperAngle = 90
			b.TwistLowerAngle = -45
			b.TwistUpperAngle = 45

			if motor.Name == "Neck" then
				b.TwistLimitsEnabled = true
				b.UpperAngle = 45
				b.TwistLowerAngle = -70
				b.TwistUpperAngle = 70
			end

			a0.Parent = motor.Part0
			a1.Parent = motor.Part1
			b.Parent = motor.Parent
		end
	end
	
	
end

--> Destroys all Ragdoll made instances and re-enables the Motor6D's
function resetJoints()
	if Humanoid.Health < 1 then return end
	for _, instance in pairs(Character:GetDescendants()) do
		if ragdollInstanceNames[instance.Name] then
			instance:Destroy()
		end

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

function Ragdoll(value: boolean)
	if value then
		Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
		replaceJoints()
		push()
	else 
		resetJoints()
		Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
end

-------------------------------------------------------------------------------------------------
--> Connect the Events
RagdollValue.Changed:Connect(Ragdoll)
Humanoid.Died:Once(function()
	RagdollValue.Value = true
	push()
end)
1 Like

Nevermind you actually do remove it

I know you add them in your script but check to see if the BallSocketConstr. etc are in the character after you notice the issue.

Cant seem to find any other probable cause

1 Like

I tried settings the Humanoid.PlatformStand = true when they are ragdolled and false when they arent but even though it works, it ends up flinging them when they get up sometimes.

function Ragdoll(value: boolean)
	if value then
		Humanoid.PlatformStand = true
		Humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
		replaceJoints()
		push()
	else 
		Humanoid.PlatformStand = false
		resetJoints()
		Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
end

Though the issue barely happens so I’ll just keep it like that. (Nevermind it happens way too often)

heya,I know I’m late but if your still finding a solution,I think I may help!
I use this for a while(you can also check out the old ragdoll but it have the same issue you have too),and the ApplyRagdoll works perfectly fine for npc(the torso won’t float). here’s the script:

–made by the silly noob 2024
local RagdollFunctions = {}
function RagdollFunctions.OldRagdoll(character)-- the first one I made don’t use it
local humanoid = character:FindFirstChild(“Humanoid”)
if humanoid then
humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)

	for _, desc in character:GetDescendants() do
		if desc:IsA("Motor6D") then
			local attachment0 = Instance.new("Attachment")
			attachment0.CFrame = desc.C0
			attachment0.Parent = desc.Part0

			local attachment1 = Instance.new("Attachment")
			attachment1.CFrame = desc.C1
			attachment1.Parent = desc.Part1

			local ballSocket = Instance.new("BallSocketConstraint")
			ballSocket.Attachment0 = attachment0
			ballSocket.Attachment1 = attachment1
			ballSocket.Parent = desc.Part0

			ballSocket.LimitsEnabled = true
			ballSocket.UpperAngle = 45
			ballSocket.TwistLimitsEnabled = true
			ballSocket.TwistLowerAngle = -45
			ballSocket.TwistUpperAngle = 45

			desc.Enabled = false

		end
	end
end

end
function RagdollFunctions.ApplyRagdoll(character)
local humanoid = character:FindFirstChild(“Humanoid”)
if humanoid then
humanoid.HipHeight = 0
humanoid.PlatformStand = true
humanoid:ChangeState(Enum.HumanoidStateType.Ragdoll)
humanoid.PlatformStand = true
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, true)
– Ensure PlatformStand is true to prevent floating
local rightArm = character:FindFirstChild(“Right Arm”)
if rightArm then
print(rightArm.CanCollide)
end
for _, desc in character:GetDescendants() do
if desc:IsA(“Motor6D”) then
local attachment0 = Instance.new(“Attachment”)
attachment0.CFrame = desc.C0
attachment0.Parent = desc.Part0

			local attachment1 = Instance.new("Attachment")
			attachment1.CFrame = desc.C1
			attachment1.Parent = desc.Part1

			local ballSocket = Instance.new("BallSocketConstraint")
			ballSocket.Attachment0 = attachment0
			ballSocket.Attachment1 = attachment1
			ballSocket.Parent = desc.Part0

			ballSocket.LimitsEnabled = true
			ballSocket.UpperAngle = 60 -- Increased angle to allow more flexibility
			ballSocket.TwistLimitsEnabled = true
			ballSocket.TwistLowerAngle = -60 -- Increased angle to allow more flexibility
			ballSocket.TwistUpperAngle = 60 -- Increased angle to allow more flexibility

			desc.Enabled = false
		elseif desc:IsA("BasePart") and desc.Name ~= 'Torso' then
			desc.CanCollide = true -- Reset CanCollide to false when removing ragdoll

		end
	end

	-- Brief delay to allow physics to stabilize
	task.wait(0.1)

	-- Reset character's velocity to prevent bouncing

end

end

function RagdollFunctions.RemoveRagdoll(character)
local humanoid = character:FindFirstChild(“Humanoid”)
if humanoid then
humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
humanoid.PlatformStand = false – Reset PlatformStand to false when removing ragdoll
humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)
humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
for _, desc in character:GetDescendants() do
if desc:IsA(“Motor6D”) then
desc.Enabled = true
elseif desc:IsA(“BallSocketConstraint”) or desc:IsA(“Attachment”) then
desc:Destroy()
elseif desc:IsA(“BasePart”) and desc.Name ~= ‘Torso’ then
desc.CanCollide = false – Reset CanCollide to false when removing ragdoll
end
end

	-- Reset character's velocity to prevent bouncing


	-- Ensure the character is in a stable state
	task.wait(0.1) -- Brief delay to allow physics to stabilize
	humanoid:ChangeState(Enum.HumanoidStateType.Running)
end

end

return RagdollFunctions
also this is the first reply I ever made so I dunno about the rules but I hope this helps!

oh yeah btw if some note in the script is weird,just skip them I removed some useless part and forgor to remove the notes.sorry if that caused inconvenient!