Animating a Character Effienctly

Hello Developers!

I have recently ran into a problem animating a character, I’m using ImageRectOffsets on an image to move it frame by frame when a key is pressed, it works.

However, the character image im using has an idle animation. 5 frames which take ~0.3 seconds to complete. its a character for a rhythm game,
basically, there are notes, and as the character hits these notes, it does either an up/down/left/right animation, each 5 frames, and again ~0.3 sec to complete each.

the problem im encountering is that i have a value which is “currentpose” which changes when the player enters an input. if the player presses “W” the value gets set to “Up” which then moves the character accordingly, and then after, switch to the idle pose, however, when there are many inputs at once, the character switches between idle too many times

what i need, is a way to detect when there is no player input for at least 1 second to then switch to the idle animation.

here is my current script.

-- This script animates the image of the character
--// "Local Script" is the idle animation script.

script.Parent.CurrentPose.Changed:Connect(function()
	local CurrentPose = script.Parent.CurrentPose.Value
	local imglabel  = script.Parent.Bot
	local waitTime = 0.1 --//bye eye
	
	if CurrentPose == "Right" then
        script.LocalScript.Disabled = true
		imglabel.ImageRectOffset = Vector2.new(0,212)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(170.7,212)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(341.3,212)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(512,212)
	    wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(682.6,212)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(853.3,212)


	elseif CurrentPose == "Left" then
		script.LocalScript.Disabled = true

		imglabel.ImageRectOffset = Vector2.new(0,578)
		wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(170.7,578)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(341.3,578)
		wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(512,578)
			wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(682.6,578)
			wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(853.3,578)	

	elseif CurrentPose == "Up" then
		script.LocalScript.Disabled = true

		imglabel.ImageRectOffset = Vector2.new(0,395)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(170.7,395)
			wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(341.3,395)
			wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(512,395)
			wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(682.6,395)
			wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(853.3,395)

	elseif CurrentPose == "Down" then
		script.LocalScript.Disabled = true


		imglabel.ImageRectOffset = Vector2.new(0,761)
		wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(170.7,761)
			wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(341.3,761)
			wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(512,761)
			wait(waitTime)
			imglabel.ImageRectOffset = Vector2.new(682.6,761)
			wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(853.3,761)	

	elseif CurrentPose == "Idle" then
		script.LocalScript.Disabled = false

	
	
	end
end)
--// this is the local script for the idle animation.
while wait() do
	
		local waitTime = 0.1 --//bye eye
		local imglabel = script.Parent.Parent.Bot
		

		imglabel.ImageRectOffset = Vector2.new(0,30)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(170.7,30)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(341.3,30)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(512,30)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(682.6,30)
		wait(waitTime)
		imglabel.ImageRectOffset = Vector2.new(853.3,30)
end

TL;DR
i need the idle animation to loop forever until an input is pressed, and i need the character to not constantly switch to the idle pose. so how can i detect when no inputs are pressed for 0.5 seconds?,

Any Help would be much appreciated!

How are you detecting the input right now for the different poses?

I’m using another local script, which just changes the value, it uses userinputservice,

I’ll post the script in a bit.

here is the input script

local function onclosesthit(input,direction)
local CurrentPose = script.Parent.CurrentPose

if direction == "Right" then
	CurrentPose.Value = "Right" --//this changes the pose value
	script.Parent.Input.D.TextColor3 = Color3.fromRGB(38, 255, 0)
elseif direction == "Left" then
	CurrentPose.Value = "Left" --//this changes the pose value
	script.Parent.Input.A.TextColor3 = Color3.fromRGB(255, 226, 0)
elseif direction == "Up" then
	CurrentPose.Value = "Up" --//this changes the pose value
	script.Parent.Input.W.TextColor3 = Color3.fromRGB(255, 0, 0)
elseif direction == "Down" then
	CurrentPose.Value = "Down"--//this changes the pose value
	script.Parent.Input.S.TextColor3 = Color3.fromRGB(0, 136, 255)
else
	CurrentPose.Value = "Idle"--//this changes the pose value
  	end
wait(0.35)
CurrentPose.Value = "Idle"--//this changes the pose value
script.Parent.Input.W.TextColor3 = Color3.fromRGB(0, 0, 0)
script.Parent.Input.A.TextColor3 = Color3.fromRGB(0, 0, 0)
script.Parent.Input.S.TextColor3 = Color3.fromRGB(0, 0, 0)
script.Parent.Input.D.TextColor3 = Color3.fromRGB(0, 0, 0)
end





local inputconnection

inputconnection = 
game:GetService("UserInputService").InputBegan:Connect(function(input, typing)
 --if typing then return end
--\\ Key (KEYBINDINGS)
local direction
if input.KeyCode == Enum.KeyCode.W or input.KeyCode == Enum.KeyCode.Up or  input.KeyCode == Enum.KeyCode.L then
	direction = "Up"
end
if input.KeyCode == Enum.KeyCode.A or  input.KeyCode == Enum.KeyCode.Left  then
	direction = "Left"
end
if input.KeyCode == Enum.KeyCode.S or  input.KeyCode == Enum.KeyCode.Down  then
	direction = "Down"
end
if input.KeyCode == Enum.KeyCode.D or  input.KeyCode == Enum.KeyCode.Right or  input.KeyCode == Enum.KeyCode.Semicolon then
	direction = "Right" 
end
if direction then
	print(direction)
	onclosesthit(input, direction)
end
end)

sorry, replied to myself, here is the script.

here is the input script

local function onclosesthit(input,direction)
local CurrentPose = script.Parent.CurrentPose

if direction == "Right" then
	CurrentPose.Value = "Right" --//this changes the pose value
	script.Parent.Input.D.TextColor3 = Color3.fromRGB(38, 255, 0)
elseif direction == "Left" then
	CurrentPose.Value = "Left" --//this changes the pose value
	script.Parent.Input.A.TextColor3 = Color3.fromRGB(255, 226, 0)
elseif direction == "Up" then
	CurrentPose.Value = "Up" --//this changes the pose value
	script.Parent.Input.W.TextColor3 = Color3.fromRGB(255, 0, 0)
elseif direction == "Down" then
	CurrentPose.Value = "Down"--//this changes the pose value
	script.Parent.Input.S.TextColor3 = Color3.fromRGB(0, 136, 255)
else
	CurrentPose.Value = "Idle"--//this changes the pose value
  	end
wait(0.35)
CurrentPose.Value = "Idle"--//this changes the pose value
script.Parent.Input.W.TextColor3 = Color3.fromRGB(0, 0, 0)
script.Parent.Input.A.TextColor3 = Color3.fromRGB(0, 0, 0)
script.Parent.Input.S.TextColor3 = Color3.fromRGB(0, 0, 0)
script.Parent.Input.D.TextColor3 = Color3.fromRGB(0, 0, 0)
end





local inputconnection

inputconnection = 
game:GetService("UserInputService").InputBegan:Connect(function(input, typing)
 --if typing then return end
--\\ Key (KEYBINDINGS)
local direction
if input.KeyCode == Enum.KeyCode.W or input.KeyCode == Enum.KeyCode.Up or  input.KeyCode == Enum.KeyCode.L then
	direction = "Up"
end
if input.KeyCode == Enum.KeyCode.A or  input.KeyCode == Enum.KeyCode.Left  then
	direction = "Left"
end
if input.KeyCode == Enum.KeyCode.S or  input.KeyCode == Enum.KeyCode.Down  then
	direction = "Down"
end
if input.KeyCode == Enum.KeyCode.D or  input.KeyCode == Enum.KeyCode.Right or  input.KeyCode == Enum.KeyCode.Semicolon then
	direction = "Right" 
end
if direction then
	print(direction)
	onclosesthit(input, direction)
end
end)

never mind, ive figured it out, i used modules and a animation cancel function to get it working, thanks for trying to help!