hello! I’m trying to make a boolean check for whenever the player performs a trick. the code works mostly as intended, but the boolean returns to false too early after the animation, allowing the player to input another trick if they mash a trick key hard enough. how can I optimize this so the player can only input another trick if and only if the animation has finally ended?
I’m also wondering if AnimationTrack.Ended would work, but my script doesn’t have references to AnimationTrack. Would using Trick.Animation.Ended work?
Code (see local function doGroundTrick)
local RS = game:GetService("ReplicatedStorage")
local CAS = game:GetService("ContextActionService")
local UIS = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local Animator = Humanoid:WaitForChild("Animator")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local Animations = RS.Assets.Animations
local Tricks = {
["Compasso"] = {["Keybind"] = Enum.KeyCode.R};
["Cartwheel"] = {["Keybind"] = Enum.KeyCode.F};
["HookKick"] = {["Keybind"] = Enum.KeyCode.V};
}
for _, Animation in Animations:GetChildren() do
local FoundAnimation = Tricks[Animation.Name]
Tricks[Animation.Name] = {
["Keybind"] = FoundAnimation and FoundAnimation.Keybind or false,
["Animation"] = Animator:LoadAnimation(Animation)
}
end
isTricking = false
local function doGroundTrick(TrickName, State)
if State ~= Enum.UserInputState.Begin then return end
if isTricking == false then
isTricking = true
local Trick = Tricks[TrickName]
assert(Trick.Animation, TrickName .. " has no animation") -- Check if the trick has an animation (assert isn't nessecary)
Trick.Animation:Play()
elseif isTricking == true then
isTricking = false
end
end
for Trick, Info in Tricks do
if not Info.Keybind then continue end
CAS:BindAction(Trick, doGroundTrick, true, Info.Keybind)
end
Didn’t work sadly. I can still mash and the animation will replay without going through the full duration. I also tried using Trick.Animation.Length but no dice.
Here’s the function right now. Using AnimationTrack yields an error so I had to use Trick.Animation
local function doGroundTrick(TrickName, State)
if State ~= Enum.UserInputState.Begin then return end
local Trick = Tricks[TrickName]
if isTricking == false then
isTricking = true
assert(Trick.Animation, TrickName .. " has no animation") -- Check if the trick has an animation (assert isn't nessecary)
Trick.Animation:Play()
elseif isTricking == true then
Trick.Animation.Ended:Wait(Trick.Animation.Length - 0.25)
isTricking = false
end
end
Note that RBXScriptSignal:Wait() doesn’t accept any arguments.
You mean “how can I fix this”. The word “optimize” isn’t correct here.
I wrote your doGroundTrick function to be correct.
As a bonus, it’s now idiomatic and self-documenting.
local function doGroundTrick(trickName, inputState)
if inputState ~= Enum.UserInputState.Begin or isTricking then
return
end
local trick = Tricks[trickName]
local animTrack = trick.Animation
isTricking = true
animTrack:Play()
animTrack.Stopped:Once(function()
isTricking = false
end)
end
You should have better luck using the Stopped event rather than the Ended event since Ended fires after the animation’s fade-out has ended.
local function doGroundTrick(TrickName, State)
if State ~= Enum.UserInputState.Begin then return end
local Trick = Tricks[TrickName]
if isTricking == false then
isTricking = true
assert(Trick.Animation, TrickName .. " has no animation") -- Check if the trick has an animation (assert isn't nessecary)
Trick.Animation:Play()
elseif isTricking == true then
task.wait(Trick.Animation.Length - 0.25)
isTricking = false
end
end