I’m trying to create a simple hold and release animation in a tool. So when the player holds F, the hold animation will freeze until the player releases which’ll play the release animation. Everything works except the hold animation occasionally doesn’t freeze and resets. I tried remaking the animation, messing with its priority, and asking in discord servers but I can’t seem to find a solution.
The animation event “End” is on the second-to-last frame of the animation, and both animations have their priority set to Action with Looping disabled
local UIS = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Tool = script.Parent
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local Mouse = Player:GetMouse()
local Equipped = false
local Debounce = false
local Charged = false
local COOLDOWN = 2
local Animator = Character.Humanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator", Character.Humanoid)
local HoldAnimation = Animator:LoadAnimation(script.hold)
local ReleaseAnimation = Animator:LoadAnimation(script.release)
Tool.Equipped:Connect(function()
Equipped = true
end)
Tool.Unequipped:Connect(function()
Equipped = false
end)
UIS.InputBegan:Connect(function(input, processed)
if processed or input.KeyCode ~= Enum.KeyCode.F or not Equipped then
return
end
if input.UserInputType == Enum.UserInputType.Keyboard and not processed and not Debounce then
Debounce = true
Charged = true
HoldAnimation:Play()
HoldAnimation:GetMarkerReachedSignal("End"):Connect(function()
task.wait() --added this because i didn't know what else to do
HoldAnimation:AdjustSpeed(0)
print("Hold animation frozen")
end)
local BG = Instance.new("BodyGyro", Character.HumanoidRootPart)
BG.CFrame = CFrame.new(Character.HumanoidRootPart.Position, Mouse.Hit.Position)
BG.MaxTorque = Vector3.new(0, 99999, 0)
BG.P = 3000
BG.D = 100
BG.Name = "Align"
local BP = Instance.new("BodyPosition", Character.HumanoidRootPart)
BP.Position = Character.HumanoidRootPart.Position
BP.MaxForce = Vector3.one * 99999
BP.P = 3000
BP.D = 100
BP.Name = "Position"
Humanoid.WalkSpeed = 0
Humanoid.JumpHeight = 0
repeat
BG.CFrame = CFrame.new(Character.HumanoidRootPart.Position, Mouse.Hit.Position)
task.wait()
until not Charged or not Equipped
Humanoid.WalkSpeed = 16
Humanoid.JumpHeight = 7.2
BG:Destroy()
BP:Destroy()
--if Animator then (commenented this out to see if it was the cause but it wasn't)
-- for _, track in pairs(Animator:GetPlayingAnimationTracks()) do
-- track:Stop()
-- end
--end
--print("ANIMATION")
--ReleaseAnimation:Play()
task.wait(COOLDOWN)
Debounce = false
end
end)
UIS.InputEnded:Connect(function(input, processed)
if Equipped and input.KeyCode == Enum.KeyCode.F then
Charged = false
end
end)
I suspect that the issue is happening due to the fact that you’re creating a new connection each time the player presses their F key, without disconnecting the previous ones
Replacing :Connect with once :Once may potentially solve the problem, as long as it’s guaranteed that the AnimationTrack will always reach the End marker
Try using this script instead:
local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ACTION_NAME = "HoldAction"
local COOLDOWN = 2
local player = Players.LocalPlayer
local mouse = player:GetMouse()
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid"):: Humanoid
local rootPart = character.PrimaryPart or character:WaitForChild("HumanoidRootPart"):: BasePart
local animator = humanoid:WaitForChild("Animator"):: Animator
local holdAnimation = animator:LoadAnimation(script:WaitForChild("hold"))
local releaseAnimation = animator:LoadAnimation(script:WaitForChild("release"))
local tool = script.Parent
local connections = {}:: {RBXScriptConnection}
local debounce = false
local instances = {}:: {Instance}
local function onHoldBegan()
local attachment = Instance.new("Attachment")
attachment.CFrame = CFrame.fromEulerAnglesYXZ(0, math.rad(90), 0)
attachment.Parent = rootPart
table.insert(instances, attachment)
local alignOrientation = Instance.new("AlignOrientation") -- Replaces BodyGyro
alignOrientation.Mode = Enum.OrientationAlignmentMode.OneAttachment
alignOrientation.AlignType = Enum.AlignType.PrimaryAxisLookAt
alignOrientation.Attachment0 = attachment
alignOrientation.MaxTorque = 99999
alignOrientation.Parent = rootPart
table.insert(instances, alignOrientation)
local alignPosition = Instance.new("AlignPosition") -- Replaces BodyPosition
alignPosition.Mode = Enum.PositionAlignmentMode.OneAttachment
alignPosition.Position = rootPart.Position
alignPosition.Attachment0 = attachment
alignPosition.MaxForce = 99999
alignPosition.Parent = rootPart
table.insert(instances, alignPosition)
humanoid.WalkSpeed = 0
humanoid.JumpHeight = 0
holdAnimation:Play()
table.insert(connections, holdAnimation:GetMarkerReachedSignal("End"):Once(function()
holdAnimation:AdjustSpeed(0)
print("Hold animation frozen")
end))
table.insert(connections, RunService.PreSimulation:Connect(function()
alignOrientation.LookAtPosition = mouse.Hit.Position
end))
end
local function onHoldEnded()
humanoid.WalkSpeed = 16
humanoid.JumpHeight = 7.2
for i, connection in connections do
connection:Disconnect()
connections[i] = nil
end
for i, instance in instances do
instance:Destroy()
instances[i] = nil
end
end
local function onHoldAction(_, userInputState: Enum.UserInputState)
if userInputState == Enum.UserInputState.Begin then
if debounce then return end
debounce = true
onHoldBegan()
task.wait(COOLDOWN)
debounce = false
elseif userInputState == Enum.UserInputState.End then
holdAnimation:Stop()
releaseAnimation:Play()
onHoldEnded()
end
end
local function onEquipped()
ContextActionService:BindAction(ACTION_NAME, onHoldAction, false, Enum.KeyCode.F)
end
local function onUnequipped()
holdAnimation:Stop()
releaseAnimation:Stop()
ContextActionService:UnbindAction(ACTION_NAME)
onHoldEnded()
end
tool.Equipped:Connect(onEquipped)
tool.Unequipped:Connect(onUnequipped)
It uses AlignOrientation and AlignPosition rather than BodyGyro and BodyPosition (which are deprecated), and properly cleans up the instances and connections
I tried out your code and unfortunately it still occasionally didn’t work, but I found out that it was due to the signal, so simply moving the animation event down a couple frames fixed it. I did apply the changes you’ve given though