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.