Hello, i noticed my animation have “Shaking” Issue
local PoseToLib = {
Head = "Neck", ["Left Arm"] = "Left Shoulder", ["Right Arm"] = "Right Shoulder",
["Left Leg"] = "Left Hip", ["Right Leg"] = "Right Hip", Torso = "RootJoint"
}
local RS, TS = game:GetService("RunService"), game:GetService("TweenService")
local isServer = RS:IsServer()
return {
LoadAnimation = function(KeyframeSequence, Rig)
local AllKeyFrames, KeyFramePoses, OriginalPoses = {}, {}, {}
local TimePassed, Running, Paused, ForceStopped, connection = 0, false, false, false,nil
local lastUpdateTime, targetFPS, frameTime = 0, 30, 1/30
for i, kf in pairs(KeyframeSequence:GetKeyframes()) do
AllKeyFrames[#AllKeyFrames+1] = {Time = kf.Time, Keyframe = kf}
end
table.sort(AllKeyFrames, function(a, b) return a.Time < b.Time end)
local function GetMotor6D(poseName)
local motorName = PoseToLib[poseName]
if motorName then
for _, v in pairs(Rig:GetDescendants()) do
if v:IsA("Motor6D") and v.Name == motorName then return v end
end
end
end
for _, kfData in pairs(AllKeyFrames) do
for _, pose in pairs(kfData.Keyframe:GetDescendants()) do
if pose:IsA("Pose") then
if not KeyFramePoses[pose.Name] then
KeyFramePoses[pose.Name] = {Motor6D = nil, Poses = {}}
OriginalPoses[pose.Name] = {}
end
local motor = KeyFramePoses[pose.Name].Motor6D or GetMotor6D(pose.Name)
KeyFramePoses[pose.Name].Motor6D = KeyFramePoses[pose.Name].Motor6D or motor
if motor then
local poseData = {Time = kfData.Time, Motor6D = motor, Pose = pose}
table.insert(KeyFramePoses[pose.Name].Poses, poseData)
table.insert(OriginalPoses[pose.Name], poseData)
end
end
end
end
local function resetAnimation()
TimePassed = 0
for name, ptb in pairs(KeyFramePoses) do
ptb.Poses = {}
for _, poseData in pairs(OriginalPoses[name]) do
ptb.Poses[#ptb.Poses+1] = {Time = poseData.Time, Motor6D = poseData.Motor6D, Pose = poseData.Pose}
end
end
end
local function updateMotor(motor, cframe)
local basicC0 = game.ReplicatedStorage.BasicC0[motor.Name == "RootJoint" and "HumanoidRootPart" or "Torso"][motor.Name].C0
if isServer then
game.ReplicatedStorage.RemoteEvent:FireAllClients(motor, basicC0 * cframe)
else
motor.C0 = motor.C0:Lerp(basicC0 * cframe, 0.3)
end
end
local function updateAnimation()
if ForceStopped or Paused then return end
local currentTime = tick()
if currentTime - lastUpdateTime < frameTime then return end
lastUpdateTime = currentTime
Running = false
for _, ptb in pairs(KeyFramePoses) do
local poses = ptb.Poses
if #poses >= 2 then
local prev, next = poses[1], poses[2]
if next and next.Time < TimePassed then
repeat
table.remove(poses, 1)
prev, next = poses[1], poses[2]
until not next or next.Time > TimePassed
end
if next and ptb.Motor6D then
local alpha = (TimePassed - prev.Time) / (next.Time - prev.Time)
updateMotor(ptb.Motor6D, prev.Pose.CFrame:Lerp(next.Pose.CFrame, alpha))
Running = true
end
elseif #poses == 1 and ptb.Motor6D then
updateMotor(ptb.Motor6D, poses[1].Pose.CFrame)
Running = true
end
end
TimePassed = TimePassed + frameTime
local totalDuration = AllKeyFrames[#AllKeyFrames] and AllKeyFrames[#AllKeyFrames].Time or 0
if TimePassed >= totalDuration then
if KeyframeSequence.Loop then
resetAnimation()
Running = true
else
Running, ForceStopped = false, true
end
end
end
local A = {
Stop = function()
ForceStopped, Running = true, false
if connection then connection:Disconnect(); connection = nil end
end,
Play = function()
if not connection then
ForceStopped = false
resetAnimation()
connection = RS.Heartbeat:Connect(updateAnimation)
end
end,
GetTimePosition = function() return TimePassed end
}
return setmetatable(A, {
__index = function(t, key)
return key == "IsPlaying" and (connection ~= nil and not ForceStopped and not Paused) or
key == "TimePosition" and TimePassed or rawget(t, key)
end
})
end
}