So I figured it out, it only fires once per keyframe, even if the animation loops. So I have to delete the AnimationTrack and create a new one then play that one for it to loop.
Hey CodeWriter
I ran into this problem myself. The event doesnt fire correctly.
Sometimes I see it fire when the animation is finished, but besides that I only see it working with some of Roblox’s animations.
I was able to work around this by writing a custom animation playback system. (This might help you solve your problem temporarily @Osyris)
local function loadAnimation(anim)
local util = LoadLibrary("RbxUtility")
local kfsProvider = game:GetService("KeyframeSequenceProvider")
local animId = tonumber(anim.AnimationId:match("%d+$"))
local rawAnim = kfsProvider:GetKeyframeSequenceById(animId,true)
local anim = Instance.new("Animation")
anim.AnimationId = "rbxassetid://"..animId
local animTrack = animator:LoadAnimation(anim)
local this = {}
this.Loop = rawAnim.Loop
this.KeyframeReached = util.CreateSignal()
this.Played = util.CreateSignal()
this.Cycled = util.CreateSignal()
this.Stopped = util.CreateSignal()
local keyframePool = {}
local start = 0
local playing = false
local function onKeyframeReached(keyframe)
this.KeyframeReached:fire(keyframe.Name)
table.remove(keyframePool,1)
if #keyframePool == 0 then
this.Cycled:fire()
end
end
local function populatePool(callback,speed)
start = tick()
keyframePool = rawAnim:GetChildren()
table.sort(keyframePool,function(a,b)
return a.Time < b.Time
end)
for _,v in pairs(keyframePool) do
local myStart = start
delay(v.Time / speed,function ()
if playing and start == myStart then
callback(v)
end
end)
end
end
function this:Stop(fadeTime)
playing = false
keyframePool = {}
animTrack:Stop(fadeTime)
this.Stopped:fire()
end
function this:Play(fadeTime,weight,speed)
local fadeTime = fadeTime or 0.1
local weight = weight or 1
local speed = speed or 1
playing = true
this.Played:fire()
animTrack:Play(fadeTime,weight,speed)
spawn(function ()
while playing do
populatePool(onKeyframeReached,speed)
this.Cycled:wait()
if not this.Loop then
this:Stop(1)
break
end
end
end)
end
return this
end
Osyris, I was testing out your code and couldn’t get it to not work. I had to modify it to get it to work with a normal Humanoid rig:
local Workspace = game:GetService("Workspace")
local animationRig = Workspace.Dummy
local animationController = animationRig.Humanoid
local animation = Instance.new("Animation")
animation.AnimationId = "rbxassetid://180435571" -- Looped Idle Animation
animationTrack = animationController:LoadAnimation(animation)
animationTrack.KeyframeReached:connect(function(name)
print("KF", name)
if name == "Hit" then
-- Do Action
end
end)
animationTrack:Play(0.1)
By any chance was the object you were animating have both a Humanoid and an AnimationController in it?
I did test with both Humanoid and AnimationController, but it was at different times. I did not test with both of them in the rig at the same time. Both had the exact same effect.
The test I’ve run displayed all the Keyframes from the looping animations. Can you post a link to a simple place that demonstrates the bug you’re seeing?