KeyframeReached not working

I was reading about KeyframeReached event and decided to test it out.

I copied the code Roblox used as an example, followed the instruction on where to place the local script and then tested the script in my game.

Problem
The script worked until I decided to put my own animationID that I created. In my animation I did create Keyframes, but it won’t print in output, and I don’t know why?

The animation I created is very short since I’m just testing this function. Does anyone know why it’s not working with my own animation even though it does have keyframes?

Local Script

local Players = game:GetService("Players")

local player = Players:GetChildren()[1]
local character = workspace:WaitForChild(player.Name)
local humanoid = character:WaitForChild("Humanoid")

local animation = Instance.new("Animation")
animation.AnimationId = "rbxassetid://14000879233"
local animTrack = humanoid:LoadAnimation(animation)

animTrack.KeyframeReached:Connect(function(keyframeName)
	print("Keyframe reached:" .. keyframeName)
end)
animTrack:Play()


local function listenForAnimationEffects(humanoid) -- would also work for an AnimationController
	-- listen for new animations being played on the Humanoid
	humanoid.AnimationPlayed:Connect(function(animationTrack)
	
		local keyframeConnection = nil
		-- listen for the 'Effect' keyframe being reached
		keyframeConnection = animationTrack.KeyframeReached:Connect(function(keyframeName)
	
			if keyframeName == "Effect" then

				-- make sure the Humanoid RootPart exists
				if humanoid.RootPart then
					-- create a basic particle effect
					local particles = Instance.new("ParticleEmitter")
					particles.Parent = humanoid.RootPart
					particles.Rate = 0
					particles:Emit(10)
					task.delay(2, function()
						if particles then
							particles:Destroy()
						end
					end)
				end
			end
		end)
		local stoppedConnection = nil
		stoppedConnection = animationTrack.Stopped:Connect(function()
			-- clean up old connections to stop memory leaks
			keyframeConnection:Disconnect()
			stoppedConnection:Disconnect()
		end)
	end)
end

local humanoid = script.Parent:WaitForChild("Humanoid")

listenForAnimationEffects(humanoid)

I just ran into this too. I figured out what was going on though. According to the documentation, it will only fire if it encounters a keyframe that is named other than “Keyframe”. So in the animation editor, DO NOT USE Add Animation Event Here.
Use Rename Key Keyframe instead. If the keyframe icon changes from a diamond to a square, then you got it right. After that it should work.

I have no idea what animation events does, but it’s in the menu and it’s misleading.

3 Likes

In my case I ended up using the animation events which gives the option to create an event with a parameter value, which could be more useful in scripts.

Example:

AnimationTrack:GetMarkerReachedSignal(Event):Connect(function(value)
particleEmitter:Emit(value)
end)

If you don’t see the marker with the plus sign go into the animation editor, click on the gear, then click on “Show Animation
Events”. You should then have the option to create animation events with parameters.

I got confused because I thought keyframe events and animation events were the same.
Nevertheless, thank you for your reply and I hope this could help out anyone else who got confused. :grin:

Both methods have their strengths and weaknesses. For AnimationTrack.KeyframeReached you only need one event but you have to name the keyframes, which means that you cannot change the order. With AnimationTrack:GetMarkerReachedSignal(), it requires an event handler for each event, but in the animation editor, you can place them anywhere and move them around.

Right tool for the job.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.