I think you guys might be misunderstanding what I am saying, what I mean is interpolating the joints is something I thought would work, but doesn’t as seen here:
you can tell that there is still jitter to it.
It wasn’t until I was messing around, attaching things to the character with ballsockets that I realized when you have an attachment on the humanoidrootpart it doesn’t look laggy, compared to having it on the attachment torso. Below are 2 examples of what I’m talking about
EXAMPLE 1 (NO PERCEIVED DELAY):
The attachment is parented to the humanoidrootpart (and the other one to the part)
EXAMPLE 2 (PERCEIVED DELAY):
The attachment is parented to the torso (and the other one to the part)
So the solution is not to create an over-the-top interpolation method, nor is it to clone the character. When you make the ragdoll just parent the attachment that is connected to the torso to the humanoidrootpart instead. If you’re doing everything correct, it should be that simple.
If you’re really confused, look at my code
function RagdollService:RagdollCharacter(char: Model, duration: number?)
local StateService = Knit.GetService("StateService")
if StateService:GetState(char) == "Ragdoll" then return end
--BEGIN IMPORTANT PART
local plr = Players:GetPlayerFromCharacter(char) -- variable declaration stuff
local hum = char:FindFirstChildOfClass("Humanoid")
local hrp = char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
RagdollService:EnableMotor6D(char, false) -- we just disable the motors
RagdollService:BuildJoints(char) -- the important function
RagdollService:EnableCollisionParts(char, true) -- just for looks
hrp.CanCollide = false -- prevents ragdoll from spazing out
if plr then
self.Client.Ragdoll:Fire(plr) -- this does what the else statement does on the client
else
hrp:SetNetworkOwner(nil)
hum.AutoRotate = false
hum.PlatformStand = true
end
--END IMPORTANT PART
if not duration then return end
if self._RagdollTimers[char] then coroutine.close(self._RagdollTimers[char]) end
self._RagdollTimers[char] = coroutine.create(function()
task.wait(duration)
self:UnragdollCharacter(char)
end)
coroutine.resume(self._RagdollTimers[char])
end
here is the function RagdollService:BuildJoints()
function RagdollService:BuildJoints(char: Model)
local hrp = char:FindFirstChild("HumanoidRootPart")
for _,v in pairs(char:GetDescendants()) do
if not v:IsA("BasePart") or v:FindFirstAncestorOfClass("Accessory") or v.Name == "Handle" or v.Name == "Torso" or v.Name == "HumanoidRootPart" then continue end
if not RagdollData[v.Name] then continue end
local a0: Attachment, a1: Attachment = Instance.new("Attachment"), Instance.new("Attachment")
local joint: Constraint = ReplicatedStorage.RagdollJoints:FindFirstChild(RagdollData[v.Name].Joint):Clone()
a0.Name = "RAGDOLL_ATTACHMENT"
a0.Parent = v -- the other part
a0.CFrame = RagdollData[v.Name].CFrame[2] -- cframe offset
a1.Name = "RAGDOLL_ATTACHMENT"
a1.Parent = hrp -- the literal most important part
a1.CFrame = RagdollData[v.Name].CFrame[1] -- cframe offset
joint.Name = "RAGDOLL_CONSTRAINT"
joint.Parent = v
joint.Attachment0 = a0
joint.Attachment1 = a1
v.Massless = true
end
end
I hope this helps.