Issues with Charging Up/Throwing Animation

Basically, I’ve created a bomb that allows you to hold left click to “charge up” the bomb in order for a more powerful throw when you let go. While holding, the charging animation will play and then stop once the bomb has been fully charged and ready to be let go.

Problem
It works as intended, but the issue I’ve found with my charge animation is that it sometimes “glitches” by swinging my arm completely clockwise and back to the idle animation instead of freezing on the charge animation.

From this video, the first two attempts show the issue, while the third attempt shows what the animation is intended to do.

"ThrowBomb" Script

--Modules--
local RS = game:GetService("ReplicatedStorage")
local itemModules = RS:WaitForChild("ItemModules")
local bombModule = require(itemModules:WaitForChild("BombModule"))

local SS = game:GetService("ServerStorage")
local shopAssets = SS:WaitForChild("Assets"):WaitForChild("ShopAssets")
local effects = shopAssets:WaitForChild("Effects")
	
local Tool = script.Parent
local bombScript = Tool.Bomb

--Animmations--
local animations = Tool.Animations
local bombIdle = animations.BombIdle
local bombCharge = animations.BombCharge

--Configurations--
local config = Tool.Configuration
local reloadTime = config.ReloadTime
local currentPower = config.CurrentPower
local maxPower = config.MaxPower
local minPower = config.MinPower
local bombFire = Tool.Handle.FireAttachment.Fire
local canThrow = true

local mobileDetected = config.MobileDetected

--Bomb Stats--
local activated = false
local chargeTrack = nil


--Sounds--
local throwSound = Tool:WaitForChild("Handle"):WaitForChild("Throw")
local equipSound = Tool:WaitForChild("Handle"):WaitForChild("Equip")

--Remote Functions--
local remoteFunction = Instance.new("RemoteFunction")
remoteFunction.Parent = script.Parent
remoteFunction.Name = "FetchMousePos"
script.Parent.Equipped:Wait()
local plr = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
local targetpos = function()
	return remoteFunction:InvokeClient(plr)
end

local equippedStats = plr:WaitForChild("EquippedStats")
local equippedEffect = equippedStats:WaitForChild("EquippedEffect")
local effectScript = effects:WaitForChild("Default")

Tool.Enabled = true

--Global Functions--
function onEquipped() --Activates when Equipped
	
	if not Tool.Enabled then
		return
	end
	
	if equipSound then
		equipSound:Play()
	end
	
	if bombIdle then
		local hum = Tool.Parent:FindFirstChild("Humanoid")
		
		if hum then
			local track = hum:LoadAnimation(bombIdle)
			track:Play()
			
			Tool.Unequipped:Connect(function()
				track:Stop()
			end)
			
		end
	end
	
end

function onUnequipped() --Activates when Unequipped
	--Stop charge animation if player holds while they get rid of bomb
	if activated == true and chargeTrack and (chargeTrack.TimePosition ~= 0) then
		chargeTrack:Stop()
	end
end

function onActivated() --Activates when Clicked

	if (Tool.Enabled == false) or (activated == true) or (canThrow == false) then
		return
	end
	
	local character = Tool.Parent;
	local humanoid = character.Humanoid
	if humanoid == nil then
		warn("Humanoid not found")
		return 
	end
	
	activated = true
	Tool.Enabled = false
	canThrow = false
	
	--Initilize bomb charge anim
	if bombCharge then
		chargeTrack = humanoid:LoadAnimation(bombCharge)
	end
	
	--if charge anim loaded
	if chargeTrack then
		chargeTrack:Play()
		chargeTrack:AdjustSpeed(0.5)
	end
	
	chargeTrack.Stopped:Connect(function()
		print("ACTIVATED STOPPED ON ACTIVATED")
		--If the charge is holding
		if (activated == true) and (chargeTrack.TimePosition == chargeTrack.Length) then
			chargeTrack:AdjustSpeed(0)
			chargeTrack.TimePosition = chargeTrack.Length - 0.01
		end
	end)
	
	--Hold to Charge Power
	while activated and currentPower.Value < maxPower.Value do
		currentPower.Value += 2

		if currentPower.Value > maxPower.Value then
			currentPower.Value = maxPower.Value
		end

		wait(0.01)
	end
end

local function onDeactivated()
	
	if (Tool.Enabled == true) or (activated == false) or (canThrow == true) then
		return
	end
	
	local character = Tool.Parent;
	local humanoid = character.Humanoid
	if humanoid == nil then
		warn("Humanoid not found")
		return 
	end
	
	activated = false
	
	print("DEACTIVATED STOPPED")
	chargeTrack:AdjustSpeed(0)
	local prevChargePos = chargeTrack.TimePosition
	print(prevChargePos)
	chargeTrack:Stop()
	
	--Charge arm forward
	chargeTrack:Play(prevChargePos, 1, -2)
	chargeTrack.TimePosition = prevChargePos
	
	chargeTrack.Stopped:Connect(function()
		print("ACTIVATED STOPPED ON DEACTIVATED")
		--If the charge is holding
		if (activated == true) and (chargeTrack.TimePosition == chargeTrack.Length) then
			chargeTrack:AdjustSpeed(0)
			chargeTrack.TimePosition = chargeTrack.Length
		end
	end)
	
	local targetPos = targetpos() --mouse position
	local bombPos = character.HumanoidRootPart.CFrame * Vector3.new(0,2,-2) --CFrame of player rootpart plus (0,2,-2)

	local lookAt = (targetPos - character.Head.Position).unit

	--bombModule.ThrowBomb(CFrame.new(bombPos), Tool, Tool.Parent, bombScript, effectScript, direction)
	bombModule.ThrowBomb(CFrame.new(bombPos), Tool, Tool.Parent, bombScript, effectScript, currentPower.Value, lookAt)
	bombFire.Enabled = false
	throwSound:Play()
	wait(reloadTime.Value)
	Tool.Handle.Transparency = 0
	Tool.Handle.Fuse.Transparency = 0
	Tool.Handle.Plate.Transparency = 0
	
	bombFire.Enabled = true
	
	currentPower.Value = minPower.Value
	
	Tool.Enabled = true
	canThrow = true
	chargeTrack = nil
end


--Instantiate Functions--
Tool.Equipped:Connect(onEquipped)
Tool.Unequipped:Connect(onUnequipped)
Tool.Activated:Connect(onActivated)
Tool.Deactivated:Connect(onDeactivated)

Did you set the AnimationPriority to Action?

Yes, the priority already is Action. I even changed it to the max which was “Action4” and nothing changed.

I haven’t fully digested your code but I imagine that the animation is ending too quickly and is causing your character to return to its initial state (by flipping the arm back).

Rather than firing on Stopped, I would recommend creating an event using the Animation Editor. Place the event close to the end of the animation as you intend. You could name the event “Pause” or something. Then do something like this:
animationTrack:GetMarkerReachedSignal(“Pause”):Connect(…)

Alternatively, you could create another animation that plays after chargeTrack, which is just an idle animation, for however long you need.

2 Likes