Handling client animations in a moveset system?

I’m trying to make a system that’s flexible, simple, and sequence-able..

Currently I’m stumped on the best way to handle animations in a moveset system, I’ve tried a couple methods, but they’ve got some fatal flaws.

Example 1:Starting Animation (Can't sequence, Plays one animation, not flexible)

Module

local Moveset = {
	[Enum.KeyCode.Q] = {
		["Name"] = "Placeholder1",
		["Input"] = Enum.KeyCode.Q,
		["Animation"] = game.ReplicatedStorage.Animations.Base.Anim1,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()

		end,
	},
	[Enum.KeyCode.E] = {
		["Name"] = "Placeholder2",
		["Input"] = Enum.KeyCode.E,
		["Animation"] = game.ReplicatedStorage.Animations.Base.Anim2,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()

		end,
	},
	[Enum.KeyCode.R] = {
		["Name"] = "Placeholder3",
		["Input"] = Enum.KeyCode.R,
		["Animation"] = game.ReplicatedStorage.Animations.Base.Anim3,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()

		end,
	},
	[Enum.KeyCode.F] = {
		["Name"] = "Placeholder4",
		["Input"] = Enum.KeyCode.F,
		["Animation"] = game.ReplicatedStorage.Animations.Base.Anim4,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()

		end,
	},
}

Client

UIS.InputBegan:Connect(function(Input, Proc)
	if Proc then return end
	local Input = {["KeyCode"] = Input.KeyCode, ["UserInputType"] = Input.UserInputType}
	local Move = Moveset[Input.KeyCode or Input.UserInputType]
	local Anim = Animator:LoadAnimation(Move.Animation)
	
	if Move and Move.Cooldown == false then
		Anim:Play()
		InputEvent:FireServer(Move.Input, Move.Name)
	end
end)
Example2:P2P (Sequenceable, Flexible, Unoptimal on slower devices)

Module

local Moveset = {
	[Enum.KeyCode.Q] = {
		["Name"] = "Placeholder1",
		["Input"] = Enum.KeyCode.Q,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()
			ClientAnim:Fire(Player, "Anim1")
			task.wait(1)
			ClientAnim:Fire(Player, "Anim2")
		end,
	},
	[Enum.KeyCode.E] = {
		["Name"] = "Placeholder2",
		["Input"] = Enum.KeyCode.E,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()
			ClientAnim:Fire(Player, "Anim1")
			task.wait(1)
			ClientAnim:Fire(Player, "Anim2")
		end,
	},
	[Enum.KeyCode.R] = {
		["Name"] = "Placeholder3",
		["Input"] = Enum.KeyCode.R,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()
			ClientAnim:Fire(Player, "Anim1")
			task.wait(1)
			ClientAnim:Fire(Player, "Anim2")
		end,
	},
	[Enum.KeyCode.F] = {
		["Name"] = "Placeholder4",
		["Input"] = Enum.KeyCode.F,
		["Cooldown"] = false,
		["CooldownTimer"] = 0,
		["Function"] = function()
			ClientAnim:Fire(Player, "Anim1")
			task.wait(1)
			ClientAnim:Fire(Player, "Anim2")
		end,
	},
}

Client

UIS.InputBegan:Connect(function(Input, Proc)
	if Proc then return end
	local Input = {["KeyCode"] = Input.KeyCode, ["UserInputType"] = Input.UserInputType}
	local Move = Moveset[Input.KeyCode or Input.UserInputType]
	
	if Move and Move.Cooldown == false then
		InputEvent:FireServer(Move.Input, Move.Name)
	end
end)

Is there a better way to handle this, if not which of the 2 examples should I go for?

3 Likes

Script two seems better as it allows you more customisation over animations, which is better long term when you want to vary them by having pauses and multiple animations or variants