How to detect if a character animation is playing?

I want to detect trough scripting when a character animation is currently playing, I don’t know how to do that.
I wrote this pseudocode so you can understand my question.


RunService.RenderStepped:Connect(function()
       if (the character's running animation is currently playing) then --This is where I need help.
              print("You're running!")
       else
             print("You're not running!")
       end
end)

NOTE: I also wrote the following script but I don’t get why it’s not working.


 local Char = script.Parent
 local Humanoid = Char.Humanoid
 local Anim = Char:WaitForChild("Animate").run.RunAnim
 local RunAnim = Humanoid:LoadAnimation(Anim)
 local RunService = game:GetService("RunService")

 RunService.RenderStepped:Connect(function()
       if RunAnim.IsPlaying == true then
             print("IsPlaying!")
       end
end)

15 Likes

You don’t need that there is a stopped event for aniamtion tracks not the actual animation more details can be found here:

4 Likes

to get a table of the currently running animations in a humanoid you would run

local animtracks = player.Character.Humanoid:GetPlayingAnimationTracks()

and to check for a specific animation you would loop through the table and find it as such

for i,v in pairs(animtracks) do
    if v.Name == "RunAnim" then
          --stuff here
    end
end
10 Likes

I just discovered a way to detect the animation currently played by the character simply by messing around with the Animate local script.

But thank you anyways for the help! :smile:

1 Like

Sorry to bump, but please explain what you did! I’m wondering too!

3 Likes

@AbsurdBartholomew Alright, I’ll explain!

Before starting, you need to know my method only detects normal character animations (for example: the run animation, the jump animation, the fall animation, etc.). If you need to detect when a custom animation is playing, then you should instead use the IsPlaying property of animation tracks like this:

 RunService.RenderStepped:Connect(function()
    if yourAnimationTrack.IsPlaying == true then
       print("Your custom animation is currently playing!")
    end
 end)

But if you need, just like me, to detect when a normal character animation is playing, you’ll have to follow the next steps:

  1. Playtest the game.

  2. Find your character inside the workspace, using the explorer tab.

  3. Under your character, there is a local script called Animate. Copy it.

  4. Stop the playtest.

  5. Paste Animate inside StarterCharacterScripts.

  6. Paste the following loop inside Animate between lines 755 and 757:

    game:GetService("RunService").RenderStepped:Connect(function()
     if pose == "Standing" then
     	print("You're idle!")
     end
     		
     if pose == "Jumping" then
        print("You're jumping!")
     end	
     		
     if pose == "FreeFall" then
         print("You're falling!")	
     end	
     
     if pose == "Walking" then
     	print("You're walking!")
     end
     
     if pose == "Running" then
     	print("You're running!")
     end
     
     if pose == "Climbing" then
     	print("You're climbing!")
     end
     
     if pose == "Swimming" then
     	print("You're swimming!")
     end
    end)
    

I hope this will help you! :wink:

19 Likes

Since this is currently my most popular topic on the DevForum, I think I need to make some clarifications…

I was very new to scripting when I wrote the code above, and it contains a few problems:

  • It is R15-specific (it won’t work with R6)
  • It requires forking the Animate script, which is not a recommended practice, since it prevents automatic updates.
  • RenderStepped if used for the loop, even if Heartbeat would’ve been enough.
  • The RenderStepped loop is never disconnected; this will result in errors when the character dies and in-game lag.

Here is a better version of the code, that fixes all of the problems above:

-- Place inside StarterCharacterScripts. Code written by Venonum.

-- Constants
local RUN_SERVICE = game:GetService("RunService")
local CHARACTER = script.Parent
local HUMANOID = CHARACTER:WaitForChild("Humanoid")

-- Code
local check
check = RUN_SERVICE.Heartbeat:Connect(function()
	if not CHARACTER:FindFirstChild("Humanoid") or HUMANOID.Health == 0 then
		check:Disconnect()
	end
	
	for _, animation in pairs(HUMANOID:GetPlayingAnimationTracks()) do
		local track
		
		if HUMANOID.RigType == Enum.HumanoidRigType.R15 then
			if animation.Animation.Parent and animation.Animation.Parent:IsA("StringValue") then
				track = animation.Animation.Parent.Name
			else
				track = animation.Animation.Name
			end
		else -- For R6
			if animation.Name == "idle" or animation.Name == "Animation1" or animation.Name == "Animation2" then
				track = "idle"
			elseif animation.Name == "WalkAnim" then
				track = "run"
			elseif animation.Name == "JumpAnim" then
				track = "jump"
			elseif animation.Name == "FallAnim" then
				track = "fall"
			elseif animation.Name == "ClimbAnim" then
				track = "climb"
			elseif animation.Name == "SitAnim" then
				track = "sit"
			elseif animation.Name == "dance1" then
				track = "dance"
			elseif animation.Name == "ToolNoneAnim" then
				track = "toolnone"
			elseif animation.Name == "dance2" or animation.Name == "dance3" or animation.Name == "point" or animation.Name == "wave" or animation.Name == "laugh" or animation.Name == "cheer" or animation.Name == "toolslash" or animation.Name == "toollunge" then
				track = animation.Name
			end
		end
		
       if track ~= nil then
		  print(track)
       end
	end
end)

However, you need to be warned that:

  • The R6 swim and run animations are identical, so the code above can’t distinguish them.
  • For some reason, the “walk” and “run” animations aren’t distinguished, so you’ll have to add a walkspeed verification if you want to check for them separately.
8 Likes

For anyone still searching for this answer:

Animator:GetPlayingAnimationTracks

This function Animator:GetPlayingAnimationTracks() returns a Table (Array).

This only works on the Animator object.

Use: for i, v in ipairs() do … end

In case you have no idea where to start, use this code:

local PlayerService = game:GetService("PlayerService")
local Player = PlayerService.LocalPlayer

repeat task.wait() until Player.Character

local Character = Player.Character

local Humanoid = Character:WaitForChild("Humanoid")

local Animator = Humanoid:WaitForChild("Animator")

while task.wait(1) do

	for AnimationTag, AnimationName in ipairs(Animator:GetPlayingAnimationTracks()) do

		print(AnimationTag,AnimationName)

	end

end

Have a nice day’

8 Likes

Incredibly usless for my usecase, and saying I dont need it is just unconsiderate