Stopping Animation using ':Wait'?

I’ve been stuck on this problem, left, came back tried to solve it in multiple ways and studied this problem ALOT. Came back to it multiple times and I’ve come to the conclusion that I lack the understanding of something.
I feel like it’s a super simple solution but again something I just don’t know.

I’ll be as descriptive as possible.

I want to play an Animation. In this case an Aiming animation.

This AnimationID changes every time the tool is equipped in another script.

Here are the things to keep in mind that I looked into but didn’t help or Don’t know how it can help?
(-) Avoiding wait() and why
(-) changing priorities ‘this doesn’t fix the problem because it still plays a new animation with every time the function is ran’

What I think might solve this?
(-) Adding some sort of :Wait() on character.Values.Aiming.Changed or AnimationId.Changed inside the function. But not sure how exactly?


My code in steps
(1) - where the Animations are stored.
(2) - where Animations are changed depending on the weapon.
^ everything above works perfectly, its just to show everything ^
(3) - where Animations are played. << (problem)


–/(1)/ Module script with the weapon ;; Where ANIMATION-IDs are stored

local Weapons = 
		["Pistol 1"] = {
				["animations"] = {
					["aiming"] = "rbxassetid://9087186774";
				};
		};
		["Pistol 2"] = {
				["animations"] = {
					["aiming"] = "rbxassetid://9103230309";		
				};
		};
}
return Weapons

–/(2)/ Inside the tool

local ReplicatedStorage = game:WaitForChild("ReplicatedStorage")
local moduleWeapons = require(ReplicatedStorage.Modules.moduleWeapons)

local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")

local tool = script.Parent
local weaponName = tool.Name

--/!!/  TOOL EQUIPPED
tool.Equipped:Connect(function()

    --/!!/  Grabs the full animation link
    local animationID = moduleWeapons[weaponName].animations.aiming 

        --/!!/  I have a Animation instance already in "character.Animations.currentWeapon.aiming."
        character.Animations.currentWeapon.aiming.AnimationId = animationID

end)

–/(3)/ Inside “StarterCharacterScripts” as "Animate"

	local player = game:GetService("Players").LocalPlayer
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoid = character:WaitForChild("Humanoid")
local animationsFolder = character.Animations.currentWeapon

character.Values.Aiming.Changed:Connect(function(result) --/!!/  In another script changes the values to true / false when mouseB2 is up or down

local aiming = humanoid:LoadAnimation(animationsFolder.aiming) --/!!/  Loads a new animation evertime ran

if result == "true" then
	aiming:Play()
else
	aiming:Stop()
end

--/!!/  I want to stop the animation on a :Wait() until result == "false" in this same function.

end)

I know that every time the function is ran, it will run a whole new
local aiming = humanoid:LoadAnimation(animationsFolder.aiming)
so calling aiming:Play() or aiming:Stop() will only play or stop the animation in the same function that was ran again.

Here’s a video

  --  aiming  -  Client - Animate:28
  --  aiming (x2)  -  Client - Animate:28
--.....and so on (+1 every time the animation is played again.)

as you can see in the Output using my debugging to get all playing animations and print them. Aiming is being played over again. Because of defining the LoadAnimation in the function.

and I know I can just do

		for i,Track in pairs(player.Character.Humanoid:GetPlayingAnimationTracks()) do 
			Track.Stop()
		end

and be done with it… but I don’t want to depend on a for loop every time I want to play every animation. This is a bad idea to just have these laying around unless I know for sure there’s no solution.

What I don’t understand exactly is why this doesn’t work, and I also tried::

character.Values.Aiming.Changed:Connect(function(result) 

      aiming:Stop() --/??/  Doesn't work

local aiming = humanoid:LoadAnimation(animationsFolder.aiming)
if result == "true" then
	aiming:Play()
else
	aiming:Stop()
end
end)

and

local aiming = humanoid:LoadAnimation(animationsFolder.aiming) --/!!/  animation

character.Values.Aiming.Changed:Connect(function(result) 
--/!!/  aiming never changes to the new animationID because its outside above this function
--/!!/  so the one above the function will be the only one thats going to be played
if result == "true" then
	aiming:Play()
else
	aiming:Stop()
end
end)

More laying it out exactly what I think a solution would be?..

character.Values.Aiming.Changed:Connect(function(result) --/!!/  ok playing function
local aiming = humanoid:LoadAnimation(animationsFolder.aiming) --/!!/  loading animation
if result == "true" then --/!!/  result is true lets play the animation
	aiming:Play() --/??/  okay we are playing the animation, but... when do you want this to stop?
else
	aiming:Stop()
end

--/!!/  I want this to stop if AnimationId changes, OR...result of the function / function is ran again. Stopping this animation.
--/!!/  Maybe using :Wait() somehow on AnimationId changed?

end)

or

character.Values.Aiming.Changed:Connect(function(result)

--/!!/  Something here to stop the last animation:: that was declared from the last time this function ran

local aiming = humanoid:LoadAnimation(animationsFolder.aiming) 
if result == "true" then
	aiming:Play() 
else
	aiming:Stop()
end
end)

Any suggestions are very helpful!

4 Likes

Sorry it took me a while to think this through and decipher exactly how you have everything set up. You’re using LoadAnimation on the Humanoid which is deprecated. The new way to play an animation is to load an Animation onto the already provided Animator which is a descendant of Humanoid. Instead of the system you have for changing that StringValue to the animation ID each time the tool is equipped, you would just place an Animation inside each weapon with the corresponding ID already there. This way, you won’t have to reload the animation to the character each time the player aims in. Instead, you load the animation one time. I’m honestly not sure if loading the animation before the player equips the weapon is the best idea, but you can play around with it and load it once they equip the tool if you want. The way I have it set up, the script only listens for the Aiming value to be changed if the tool is equipped. When the tool is unequipped, it disconnects the connection which is defined outside of the function. The script below will be a LocalScript inside the tool.

EDIT: Changed “true” to true

local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local Animator = humanoid:WaitForChild("Animator")
local Tool = script.Parent
local Animation = Tool.AimAnimation
local anim = Animator:LoadAnimation(Animation)


local connection = nil

local function DisconnectConnections()
	if connection then
		connection:Disconnect()
	end
end

script.Parent.Equipped:Connect(function()
	DisconnectConnections()
	connection = character.Values.Aiming.Changed:Connect(function(result)
		if result == true then
			anim:Play()
		else
			anim:Stop()
		end
	end)
end)

script.Parent.Unequipped:Connect(function()
	DisconnectConnections()
	anim:Stop()
end)
3 Likes

Spot on. Highly noted on Humanoid:LoadAnimation is deprecated, didn’t know that!

So commonly everyone would be to put animations inside the tool itself?

This would work better I believe, I’ll have to start implementing this. I got most of it in I haven’t gotten to test it yet but reading through I can tell this would be a proper solution.

I know there are so many ways to do one thing. I ended up figuring out another solution BUT what you said
(“This way, you won’t have to reload the animation to the character each time the player aims in.” )
^ That is a very good point ^

I don’t have enough time to test atm, so I will come back possibly in the next 24 hours.

Thanks again!

The solution I figured out:
I was missing the idea of something like character.Values.Aiming.Changed:Wait() would work.

--/!!/  AIMING ANIMATION
character.Values.Aiming.Changed:Connect(function(result)
local aiming = humanoid:LoadAnimation(animationsFolder.aiming)
	if result == "true" then
		aiming:Play()
	else
		aiming:Stop()
	end

character.Values.Aiming.Changed:Wait() --/!!/  waits until the aiming.AnimationId changes. 
aiming:Stop() --/!!/  after the wait is done then

end)
1 Like