AnimationTrack.KeyframeReached not firing correctly

I can’t seem to get this to work at all. Anyone have better luck?

This is in Server/Client Studio, Play Solo, and In-Game.

The best I can do is if I delay the AnimationTrack:Play() by any amount of time after the game starts, the first keyframe will work.

1 Like

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.

This seems a little weird.

That sounds like a bug. I’ll try to reproduce the issue here.

Can you post the script that you were using and that might help as well?

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

I also ran into another bug with animations:
http://developer.roblox.com/forum/client-bug-reports/15731-animator-object-replication-bug

I expected this code to work with a LOOPING animation:
http://hastebin.com/hinahisupu.lua

Instead I had to make the animation NOT LOOP and use this code
http://hastebin.com/emuhotuluk.lua

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?