Issues with NPC Ragdolling

I have a ragdoll script that I’ve been using, however it’s had varying degrees of success. The script only triggers when an NPC reaches 1 HP, and will work fine in the first 30 or so seconds of the game like this:
image
However after those first 30 or so seconds, regardless of whether it’s the same NPC or not, instead of dropping to the ground, they’ll sort of hang suspended in place like this:
image
Any help on fixing this issue would be greatly appreciated. I’ll also attach the script below:

local Modules = game.ServerScriptService.Modules
local NPCHandler = require(Modules.NPCHandler)



local Character: Model = script.Parent
local Torso: BasePart = Character:WaitForChild("Torso")
local Humanoid: Humanoid = Character:FindFirstChildOfClass("Humanoid")

local NPCID = Character.NPCID.Value
local NPCData = NPCHandler[NPCID]
local Size = NPCData.Appearance.Size



Character.Humanoid.BreakJointsOnDeath = false
Character.Humanoid.RequiresNeck = true 



local attachmentCFrames = {
	["Neck"] = {CFrame.new(0, Size * 1, 0, 0,Size * -1, 0,Size * 1, 0, -0, 0, 0,Size * 1), CFrame.new(0,Size * -0.5, 0, 0,Size * -1, 0,Size * 1, 0, -0, 0, 0,Size * 1)},
	["Left Shoulder"] = {CFrame.new(Size * -1.3,Size * 0.75, 0,Size * -1, 0, 0, 0,Size * -1, 0, 0, 0,Size * 1), CFrame.new(Size * 0.2,Size * 0.75, 0,Size * -1, 0, 0, 0,Size * -1, 0, 0, 0,Size * 1)},
	["Right Shoulder"] = {CFrame.new(Size * 1.3,Size * 0.75, 0,Size * 1, 0, 0, 0,Size * 1, 0, 0, 0,Size * 1), CFrame.new(Size * -0.2,Size * 0.75, 0,Size * 1, 0, 0, 0,Size * 1, 0, 0, 0,Size * 1)},
	["Left Hip"] = {CFrame.new(Size * -0.5,Size * -1, 0, 0,Size * 1, -0,Size * -1, 0, 0, 0, 0,Size * 1), CFrame.new(0,Size * 1, 0, 0,Size * 1, -0,Size * -1, 0, 0, 0, 0,Size * 1)},
	["Right Hip"] = {CFrame.new(Size * 0.5,Size * -1, 0, 0,Size * 1, -0,Size * -1, 0, 0, 0, 0,Size * 1), CFrame.new(0,Size * 1, 0, 0,Size * 1, -0,Size * -1, 0, 0, 0, 0,Size * 1)},
}

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


local RagdollValue = Instance.new("BoolValue")
RagdollValue.Name = "IsRagdoll"
RagdollValue.Parent = Character



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


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


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


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.Physics)
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
		replaceJoints()
		push()
	else 
		resetJoints()
		Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
	end
end

RagdollValue.Changed:Connect(Ragdoll)



game.ReplicatedStorage.Remotes.NPCRagdoll.Event:Connect(function(NPCIDSent)
	if NPCID ~= NPCIDSent then return end
	print("NPCRagdoll")
	RagdollValue.Value = true

end)

game.ReplicatedStorage.Remotes.NPCUnRagdoll.Event:Connect(function(NPCIDSent)
	if NPCID ~= NPCIDSent then return end
	print("NPCGetup")
	RagdollValue.Value = false
	
end)

script.Parent.Humanoid.HealthChanged:Connect(function()
	if script.Parent.Humanoid.Health == 0 then
		wait(5)
		NPCHandler.NPCStates[NPCID] = nil
		NPCHandler[NPCID] = nil
		script.Parent:Destroy()
	end
end)
1 Like