I’m working on a fighting/rpg game and I have this system that lets me use the same module that players use for combat that NPCs also use.
However whenever I ragdoll the NPC with a final M1 hit it seems to break the animations and i’m not sure why. I tried changing up the ragdoll script and making it destroy and recreate the Motor6D joints when they get back up and I made it reload the animations when they get back up but it didn’t seem to help. It also seems to be a client thing also, as when I switch to a server perspective it’s working perfectly fine. Any help would be appreciated.
Here’s a gif of the bug.
https://gyazo.com/9c3d934a7e77c0afce15d3d7242c1a8f
Here’s the ragdoll script code if anyone needs to see it to help.
-- Class
local API = {}
API.__index = API
-- Variables
local CollectionSerivce = game:GetService("CollectionService")
local RagdollTag = "PlayerRagdolled"
-- Constants
local ATTACHMENT_DATA = {
{"LeftCollarRagdoll",Vector3.new(-1, 1, 0)},
{"LeftHipRagdoll",Vector3.new(-1, -1, 0)},
{"RightCollarRagdoll",Vector3.new(1, 1, 0)},
{"RightHipRagdoll",Vector3.new(1, -1, 0)},
{"RootRagdoll",Vector3.new(0, 0, 0)},
}
local ATTACHMENT_DATA2 = {
{"LeftCollarRagdoll",Vector3.new(0.5, 1, 0)},
{"LeftHipRagdoll",Vector3.new(-0.5, 1, 0)},
{"RightCollarRagdoll",Vector3.new(-0.5, 1, 0)},
{"RightHipRagdoll",Vector3.new(0.5, 1, 0)},
{"RootRagdoll",Vector3.new(0, 0, 0)},
}
-- Constuctor
function API.New(Character)
local self = {}
self.Character = Character
self.RagdollAttachments = {}
self.CollisionParts = {}
self.Ragdolled = false
self.Died = false
local Torso = Character:WaitForChild("Torso")
local Humanoid = Character:WaitForChild("Humanoid")
self.Torso = Torso
self.Humanoid = Humanoid
self.Humanoid.BreakJointsOnDeath = false
self.BodyGyro = Instance.new("BodyGyro")
self.BodyGyro.MaxTorque = Vector3.new(0, 40000, 0)
self.BodyGyro.P = 30000
local LeftArm = Character:WaitForChild("Left Arm")
local RightArm = Character:WaitForChild("Right Arm")
local LeftLeg = Character:WaitForChild("Left Leg")
local RightLeg = Character:WaitForChild("Right Leg")
local Torso = Character:WaitForChild("Torso")
local RootPart = Character:WaitForChild("HumanoidRootPart")
local LeftHip = Torso:WaitForChild("Left Hip")
local RightHip = Torso:WaitForChild("Right Hip")
local LeftShoulder = Torso:WaitForChild("Left Shoulder")
local RightShoulder = Torso:WaitForChild("Right Shoulder")
local RootJoint = RootPart:WaitForChild("RootJoint")
self.Motors = {
RootJoint;
LeftHip;
RightHip;
LeftShoulder;
RightShoulder;
};
self.C0s = {}
for _, v in pairs(self.Motors) do
self.C0s[v.Name] = {v.C0,v.C1};
end
self.BodyParts = {
LeftArm;
RightArm;
LeftLeg;
RightLeg;
Torso;
RootPart;
}
setmetatable(self,API)
return self
end
-- Methods
-- Clears any stuff to prevent memory leaks
function API:Clear()
--self.BodyGyro:Destroy()
self.Ragdolled = false
self.Died = false
for _,a in pairs(self.RagdollAttachments) do
a:Destroy()
end
for _,a in pairs(self.CollisionParts) do
a:Destroy()
end
end
-- Setups character everytime they spawn in
function API:Setup(Character)
--self:Clear()
self.Character = Character
local Torso = Character:WaitForChild("Torso")
local Humanoid = Character:WaitForChild("Humanoid")
self.Torso = Torso
self.Humanoid = Humanoid
local LeftArm = Character:WaitForChild("Left Arm")
local RightArm = Character:WaitForChild("Right Arm")
local LeftLeg = Character:WaitForChild("Left Leg")
local RightLeg = Character:WaitForChild("Right Leg")
local Torso = Character:WaitForChild("Torso")
local RootPart = Character:WaitForChild("HumanoidRootPart")
local LeftHip = Torso:WaitForChild("Left Hip")
local RightHip = Torso:WaitForChild("Right Hip")
local LeftShoulder = Torso:WaitForChild("Left Shoulder")
local RightShoulder = Torso:WaitForChild("Right Shoulder")
local RootJoint = RootPart:WaitForChild("RootJoint")
self.Motors = {
RootJoint;
LeftHip;
RightHip;
LeftShoulder;
RightShoulder;
};
self.C0s = {}
for _, v in pairs(self.Motors) do
self.C0s[v.Name] = {v.Parent,v.C0,v.C1,v.Part0,v.Part1};
end
self.BodyParts = {
LeftArm;
RightArm;
LeftLeg;
RightLeg;
Torso;
RootPart;
}
self.BodyGyro = Instance.new("BodyGyro")
self.BodyGyro.MaxTorque = Vector3.new(0, 40000, 0)
self.BodyGyro.P = 30000
end
-- Returns a value that tells if player is ragdolled or not
function API:IsRagdolled()
return self.Ragdolled
end
-- Creates Motor6D welds
function API:CreateWeld(Name,Parent,C0,C1,Part0,Part1)
local Motor = Instance.new("Motor6D")
Motor.Name = Name
Motor.Part0 = Part0
Motor.Part1 = Part1
Motor.C0 = C0
Motor.C1 = C1
Motor.Parent = Parent
return Motor
end
-- Used for limb collisions when ragdolled
function CreateNewCollisionBall()
local Part = Instance.new("Part")
Part.Transparency = 1
Part.CanCollide = true
Part.Anchored = false
Part.Massless = true
Part.Size = Vector3.new(1,1,1)
Part.Shape = Enum.PartType.Ball
local Weld = Instance.new("Weld")
Weld.Part1 = Part
Weld.Parent = Part
return Part,Weld
end
-- Sets ragdoll, second argument sets ragdoll death meaning cant be unragdolled when dead
function API:Ragdoll(TrueOrFalse,Died)
if Died then
self.Died = true
end
if TrueOrFalse and not self.Ragdolled then
self.Ragdolled = true
self.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
self.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
self.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, true)
-- Beginning Attachments
local LeftHipAttachment = Instance.new("Attachment")
LeftHipAttachment.Position = ATTACHMENT_DATA[2][2]
LeftHipAttachment.Parent = self.BodyParts[5]
local RightHipAttachment = Instance.new("Attachment")
RightHipAttachment.Position = ATTACHMENT_DATA[4][2]
RightHipAttachment.Parent = self.BodyParts[5]
local LeftShoulderAttachment = Instance.new("Attachment")
LeftShoulderAttachment.Position = ATTACHMENT_DATA[1][2]
LeftShoulderAttachment.Parent = self.BodyParts[5]
local RightShoulderAttachment = Instance.new("Attachment")
RightShoulderAttachment.Position = ATTACHMENT_DATA[3][2]
RightShoulderAttachment.Parent = self.BodyParts[5]
local RootAttachment = Instance.new("Attachment")
RootAttachment.Position = ATTACHMENT_DATA[5][2]
RootAttachment.Parent = self.BodyParts[5]
-- Ending Attachments
local LeftHipAttachment2 = Instance.new("Attachment")
LeftHipAttachment2.Position = ATTACHMENT_DATA2[2][2]
LeftHipAttachment2.Parent = self.BodyParts[3]
local RightHipAttachment2 = Instance.new("Attachment")
RightHipAttachment2.Position = ATTACHMENT_DATA2[4][2]
RightHipAttachment2.Parent = self.BodyParts[4]
local LeftShoulderAttachment2 = Instance.new("Attachment")
LeftShoulderAttachment2.Position = ATTACHMENT_DATA2[1][2]
LeftShoulderAttachment2.Parent = self.BodyParts[1]
local RightShoulderAttachment2 = Instance.new("Attachment")
RightShoulderAttachment2.Position = ATTACHMENT_DATA2[3][2]
RightShoulderAttachment2.Parent = self.BodyParts[2]
local RootAttachment2 = Instance.new("Attachment")
RootAttachment2.Position = ATTACHMENT_DATA2[5][2]
RootAttachment2.Parent = self.BodyParts[6]
-- Ballsocket joints
local RightHipSocket = Instance.new("BallSocketConstraint")
RightHipSocket.Parent = RightHipAttachment
RightHipSocket.Attachment0 = RightHipAttachment
RightHipSocket.Attachment1 = RightHipAttachment2
local LeftHipSocket = Instance.new("BallSocketConstraint")
LeftHipSocket.Parent = LeftHipAttachment
LeftHipSocket.Attachment0 = LeftHipAttachment
LeftHipSocket.Attachment1 = LeftHipAttachment2
local RightShoulderSocket = Instance.new("BallSocketConstraint")
RightShoulderSocket.Parent = RightShoulderAttachment
RightShoulderSocket.Attachment0 = RightShoulderAttachment
RightShoulderSocket.Attachment1 = RightShoulderAttachment2
local LeftShoulderSocket = Instance.new("BallSocketConstraint")
LeftShoulderSocket.Parent = LeftShoulderAttachment
LeftShoulderSocket.Attachment0 = LeftShoulderAttachment
LeftShoulderSocket.Attachment1 = LeftShoulderAttachment2
local RootSocket = Instance.new("BallSocketConstraint")
RootSocket.Parent = RootAttachment
RootSocket.Attachment0 = RootAttachment
RootSocket.Attachment1 = RootAttachment2
-- Adding attachments to table
table.insert(self.RagdollAttachments,LeftHipAttachment)
table.insert(self.RagdollAttachments,RightHipAttachment)
table.insert(self.RagdollAttachments,LeftShoulderAttachment)
table.insert(self.RagdollAttachments,RightShoulderAttachment)
table.insert(self.RagdollAttachments,RootAttachment)
table.insert(self.RagdollAttachments,LeftHipAttachment2)
table.insert(self.RagdollAttachments,RightHipAttachment2)
table.insert(self.RagdollAttachments,LeftShoulderAttachment2)
table.insert(self.RagdollAttachments,RightShoulderAttachment2)
table.insert(self.RagdollAttachments,RootAttachment2)
local CollisionBallLeftArm,W1 = CreateNewCollisionBall()
CollisionBallLeftArm.Parent = self.BodyParts[1]
W1.Part0 = self.BodyParts[1]
local CollisionBallRightArm,W2 = CreateNewCollisionBall()
CollisionBallRightArm.Parent = self.BodyParts[2]
W2.Part0 = self.BodyParts[2]
local CollisionBallLeftLeg,W3 = CreateNewCollisionBall()
CollisionBallLeftLeg.Parent = self.BodyParts[3]
W3.Part0 = self.BodyParts[3]
local CollisionBallRightLeg,W4 = CreateNewCollisionBall()
CollisionBallRightLeg.Parent = self.BodyParts[4]
W4.Part0 = self.BodyParts[4]
local IsPlayer = game.Players:GetPlayerFromCharacter(self.Character)
if not IsPlayer then
self.Humanoid.PlatformStand = true
end
table.insert(self.CollisionParts,CollisionBallLeftArm)
table.insert(self.CollisionParts,CollisionBallRightArm)
table.insert(self.CollisionParts,CollisionBallLeftLeg)
table.insert(self.CollisionParts,CollisionBallRightLeg)
for _,a in pairs(self.Motors) do
a:Destroy()
end
self.BodyGyro.Parent = self.BodyParts[6]
if not CollectionSerivce:HasTag(self.Character,RagdollTag) then
CollectionSerivce:AddTag(self.Character,RagdollTag)
end
elseif not TrueOrFalse and self.Ragdolled and not self.Died then
self.Ragdolled = false
self.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
self.Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
self.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)
local IsPlayer = game.Players:GetPlayerFromCharacter(self.Character)
if not IsPlayer then
while self.Humanoid.PlatformStand do
self.Humanoid.PlatformStand = false
wait()
end
end
-- Removing attachments
for _,a in pairs(self.RagdollAttachments) do
a:Destroy()
end
for _,a in pairs(self.CollisionParts) do
a:Destroy()
end
self.Motors = {}
for Name, Data in pairs(self.C0s) do
local NM = self:CreateWeld(Name,Data[1],Data[2],Data[3],Data[4],Data[5])
table.insert(self.Motors,NM)
end
self.BodyGyro.Parent = nil
if CollectionSerivce:HasTag(self.Character,RagdollTag) then
CollectionSerivce:RemoveTag(self.Character,RagdollTag)
end
end
end
return API