NPC Ragdoll Floating In Air

I am trying to make a ragdolling system for both NPC’s and players. When ragdolled, I apply the following instance to the target’s HRP:

local bv = Instance.new("BodyVelocity")
bv.Parent = humanoid.Parent.HumanoidRootPart
bv.Name = tag
bv.MaxForce = Vector3.new(5e4,5e4,5e4)
bv.Velocity = direction*speed
bv = nil

Of course, I apply all of this after I change the Humanoid’s state type to Enum.HumanoidStateType.Physics. For what ever reason though, the NPCs occasionally exhibit the following behavior:


What is especially odd is that the force I set on the NPC should not be lasting that long. The force only lasts for about 0.3 seconds then it is destroyed. While the NPC is floating up, the BodyVelocity instance does not exist, so it is continuing to float for no reason.

This happens solely for the NPC, and never for the player. Below are the important parts of my NPC ragdoll script:

--> 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*0.9
	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

function Ragdoll(value: boolean)
	if value then
		Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
		replaceJoints() -- sets ragdoll state.
	else
		local currentTime = time()
		if Character:HasTag("Ragdoll") then
			-- Theoretically should never run. Precaution in case ragdoll is not removed when it should be.
			while Character:HasTag("Ragdoll") and time() - currentTime <= 4 do
				task.wait()
				print("waiting")
			end
		end
		
		resetJoints() -- returns ragdoll to normal.
		Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
		task.wait(0.2)
		Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp) -- this is just to have the dummy try and get up a second time
	end
end

The player’s server-sided ragdoll script functions almost exactly the same as the NPC ragdoll script, except it disables the player’s AutoRotate.

There is a client-sided ragdoll script for players which may or may not be the reason for this discrepancy – however, I don’t think so. Below is the client-sided script for the ragdoll anyway:

local function endAnims()
	for _, v in animator:GetPlayingAnimationTracks() do
		v:Stop()
	end
end

RagdollValue:GetPropertyChangedSignal("Value"):Connect(function()
	if (Humanoid.Health == 0) then
		endAnims()
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
		return
	end

	if RagdollValue.Value then
		endAnims() -- end animations to prevent player from flopping around
		Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
		Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
	elseif not RagdollValue.Value then
		Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
		animator:LoadAnimation(script.Idle)
	end
end)

Now, let me reiterate that I use the exact same knockback system for both the player and NPC ragdolls so I don’t think that is the issue (~70% sure that’s not the issue).

I have tried setting NetworkOwnership of the dummy to both the player and the server, however, this had no effect.

I believe this may be caused by glitchy collisions between the ragdoll joint colliders, but this doesn’t really make sense to me since this problem does not happen for players.

1 Like

I’d like to also point out that this is not my ragdoll script. I am using the Perfect R6 Ragdoll by @CompletedLoop.

On line 116 of the RagdollR6NPC script replace the Ragdoll() function with this:

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

This may or may not fix it.

1 Like

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