How to fix glitch (Animation Idle Staying even after I unequip the tool)

Local Script inside the Tool

local tool = script.Parent – our combat tool in a variable
local remote = script:WaitForChild(“Combat”) – our combat remote
local enabled = false – a variable which we’ll use for cooldown

tool.Equipped:Connect(function() – equipped the tool
print(“Equipped”) – print the stuff between " " inside the output
remote:FireServer(“EquipCombat”) – we fireserver the remote, with the argument to equip the combat in order for the serverscript to do that
end)

tool.Activated:Connect(function() – performed a left mouse button click on the tool
if enabled == false then – if the variable is false then, this check will fail if the value is true
enabled = true – we turn it to true
print(“LMB Click”) – print the stuff between " " inside the output
remote:FireServer(“UseCombat”) – we fireserver the remote, with the argument to use the combat in order for the serverscript to do that
wait(0.4) – we wait 0.65 seconds
enabled = false – we turn it to false again
end
end)

tool.Unequipped:Connect(function() – unequipped the tool
print(“Unequipped”) – print the stuff between " " inside the output
remote:FireServer(“UnequipCombat”) – we fireserver the remote, with the argument to unequip the combat in order for the serverscript to do that
end)

server script inside the local script

local remote = script.Parent:WaitForChild(“Combat”) – our combat remote

remote.OnServerEvent:Connect(function(Player, Val) – once the remote was fireservered
local character = workspace:WaitForChild(Player.Name) – gets the player’s character

local function CreateTag(humanoid: Humanoid)
	local ov = Instance.new("ObjectValue")
	ov.Name = "creator"
	ov.Value = Player
	ov.Parent = humanoid

	coroutine.wrap(function()
		wait(1)
		ov:Destroy() -- so that the tags don't start piling up
	end)()
end

if Val == "EquipCombat" then -- if the given argument tells us to equip the combat
	local findExistingAnimation = character:FindFirstChild("EquippedCombat") -- looks for something in the player's character called "EquippedCombat", in this case this will be our equipped animation which we'll store inside the player's character
	if findExistingAnimation then -- if it was found then
		local loader = character:WaitForChild("Humanoid"):LoadAnimation(findExistingAnimation)
		loader:Stop()
		findExistingAnimation:Destroy() -- we destroy it
	end

	local animation = Instance.new("Animation", character) -- creates an animation inside the character
	animation.Name = "EquippedCombat" -- calls it "EquippedCombat"
	animation.AnimationId = "rbxassetid://6472260755" -- sets the animation id
	local loader = character:WaitForChild("Humanoid"):LoadAnimation(animation) -- loads the animation
	loader:Play() -- plays the animation

elseif Val == "UseCombat" then -- if the given argument tells us to use the combat

	local avaibleAnimationIds = {"6470733550", "6470740709", "6470760625"}
	local randomNumber = math.random(1, #avaibleAnimationIds) -- a random number which decides on which animation we choose

	local animation = Instance.new("Animation", character) -- creates an animation inside the character
	animation.Name = "Combat" -- calls it "Combat"
	animation.AnimationId = "rbxassetid://"..avaibleAnimationIds[randomNumber] -- sets the animation id by choosing a value from the avaibleanimationids table randomly
	local loader = character:WaitForChild("Humanoid"):LoadAnimation(animation) -- loads the animation
	loader:Play() -- plays the animation

	local alreadyHitObjects = {} -- a table in which we collect what we have already hit, to prevent double hitting
	character.RightHand.Touched:Connect(function(hit) -- once the player's right hand was touched
		if randomNumber == 1 then -- if we have the random number 1, means the right punch animation is played
			if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= Player.Name then -- we check if we hit a dummy or player and if that dummy or player doenst have the same name as our player
				for _, v in pairs(alreadyHitObjects)do -- we loop through the table
					if v == hit.Parent.Name then -- if we have found the dummy or player's name inside of it, we wont hit it again
						loader:Stop() -- we stop our animation
						animation:Destroy() -- we destroy our animation so it doesn't stack inside our character
						return
					end
				end
				alreadyHitObjects[#alreadyHitObjects + 1] = hit.Parent.Name -- we add the hit object's name inside the table so it wont get hit again
				hit.Parent.Humanoid:TakeDamage(10 + Player.Data.SwordP.Value) -- we make the object's health go lower by 10
				CreateTag(hit.Parent.Humanoid)
			end
		end
	end)

	character.LeftHand.Touched:Connect(function(hit) -- once the player's right hand was touched
		if randomNumber == 2 then -- if we have the random number 1, means the right punch animation is played
			if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= Player.Name then -- we check if we hit a dummy or player and if that dummy or player doenst have the same name as our player
				for _, v in pairs(alreadyHitObjects)do -- we loop through the table
					if v == hit.Parent.Name then -- if we have found the dummy or player's name inside of it, we wont hit it again
						loader:Stop() -- we stop our animation
						animation:Destroy() -- we destroy our animation so it doesn't stack inside our character
						return
					end
				end
				alreadyHitObjects[#alreadyHitObjects + 1] = hit.Parent.Name -- we add the hit object's name inside the table so it wont get hit again
				hit.Parent.Humanoid:TakeDamage(10 + Player.Data.SwordP.Value) -- we make the object's health go lower by 10
				CreateTag(hit.Parent.Humanoid)
			end
		end
	end)
	character.RightFoot.Touched:Connect(function(hit) -- once the player's right hand was touched
		if randomNumber == 3 then -- if we have the random number 1, means the right punch animation is played
			if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= Player.Name then -- we check if we hit a dummy or player and if that dummy or player doenst have the same name as our player
				for _, v in pairs(alreadyHitObjects)do -- we loop through the table
					if v == hit.Parent.Name then -- if we have found the dummy or player's name inside of it, we wont hit it again
						loader:Stop() -- we stop our animation
						animation:Destroy() -- we destroy our animation so it doesn't stack inside our character
						return
					end
				end
				alreadyHitObjects[#alreadyHitObjects + 1] = hit.Parent.Name -- we add the hit object's name inside the table so it wont get hit again
				hit.Parent.Humanoid:TakeDamage(10 + Player.Data.SwordP.Value) -- we make the object's health go lower by 10
				CreateTag(hit.Parent.Humanoid)
			end
		end
	end)
	wait(0.5) -- we wait 0.5 seconds

	loader:Stop() -- we stop the animation
	animation:Destroy() -- we destroy it
elseif Val == "UnequipCombat" then -- if the given argument tells us to unequip the combat

	local findExistingAnimation = character:FindFirstChild("EquippedCombat") -- looks for something in the player's character called "EquippedCombat", in this case this will be our equipped animation which we'll store inside the player's character
	if findExistingAnimation then -- if it was found then
		local loader = character:WaitForChild("Humanoid"):LoadAnimation(findExistingAnimation)
		loader:Stop()
		findExistingAnimation:Destroy() -- we destroy it
	end
end

end)

well idk the issue, but maybe a solution would be to look at this My animation won’t stop? - Help and Feedback / Scripting Support - DevForum | Roblox.

Can you provide a script? There isn’t much to work or figure out with here.

Since I don’t have any script to work with, I’m guessing you should probably do something like this.

Tool.Equipped:Connect(function()
     local AnimTrack = script.Parent.Humanoid:LoadAnimation(script:WaitForChild("Animation"))
     AnimTrack:Play()

     -- Code here

     Tool.Unequipped:Connect(function()
                AnimTrack:Stop()
         end)
end)
1 Like

Local Script

local tool = script.Parent – our combat tool in a variable
local remote = script:WaitForChild(“Combat”) – our combat remote
local enabled = false – a variable which we’ll use for cooldown

tool.Equipped:Connect(function() – equipped the tool
print(“Equipped”) – print the stuff between " " inside the output
remote:FireServer(“EquipCombat”) – we fireserver the remote, with the argument to equip the combat in order for the serverscript to do that
end)

tool.Activated:Connect(function() – performed a left mouse button click on the tool
if enabled == false then – if the variable is false then, this check will fail if the value is true
enabled = true – we turn it to true
print(“LMB Click”) – print the stuff between " " inside the output
remote:FireServer(“UseCombat”) – we fireserver the remote, with the argument to use the combat in order for the serverscript to do that
wait(0.4) – we wait 0.65 seconds
enabled = false – we turn it to false again
end
end)

tool.Unequipped:Connect(function() – unequipped the tool
print(“Unequipped”) – print the stuff between " " inside the output
remote:FireServer(“UnequipCombat”) – we fireserver the remote, with the argument to unequip the combat in order for the serverscript to do that
end)

server script inside the local script

local remote = script.Parent:WaitForChild(“Combat”) – our combat remote

remote.OnServerEvent:Connect(function(Player, Val) – once the remote was fireservered
local character = workspace:WaitForChild(Player.Name) – gets the player’s character

local function CreateTag(humanoid: Humanoid)
	local ov = Instance.new("ObjectValue")
	ov.Name = "creator"
	ov.Value = Player
	ov.Parent = humanoid

	coroutine.wrap(function()
		wait(1)
		ov:Destroy() -- so that the tags don't start piling up
	end)()
end

if Val == "EquipCombat" then -- if the given argument tells us to equip the combat
	local findExistingAnimation = character:FindFirstChild("EquippedCombat") -- looks for something in the player's character called "EquippedCombat", in this case this will be our equipped animation which we'll store inside the player's character
	if findExistingAnimation then -- if it was found then
		local loader = character:WaitForChild("Humanoid"):LoadAnimation(findExistingAnimation)
		loader:Stop()
		findExistingAnimation:Destroy() -- we destroy it
	end

	local animation = Instance.new("Animation", character) -- creates an animation inside the character
	animation.Name = "EquippedCombat" -- calls it "EquippedCombat"
	animation.AnimationId = "rbxassetid://6472260755" -- sets the animation id
	local loader = character:WaitForChild("Humanoid"):LoadAnimation(animation) -- loads the animation
	loader:Play() -- plays the animation

elseif Val == "UseCombat" then -- if the given argument tells us to use the combat

	local avaibleAnimationIds = {"6470733550", "6470740709", "6470760625"}
	local randomNumber = math.random(1, #avaibleAnimationIds) -- a random number which decides on which animation we choose

	local animation = Instance.new("Animation", character) -- creates an animation inside the character
	animation.Name = "Combat" -- calls it "Combat"
	animation.AnimationId = "rbxassetid://"..avaibleAnimationIds[randomNumber] -- sets the animation id by choosing a value from the avaibleanimationids table randomly
	local loader = character:WaitForChild("Humanoid"):LoadAnimation(animation) -- loads the animation
	loader:Play() -- plays the animation

	local alreadyHitObjects = {} -- a table in which we collect what we have already hit, to prevent double hitting
	character.RightHand.Touched:Connect(function(hit) -- once the player's right hand was touched
		if randomNumber == 1 then -- if we have the random number 1, means the right punch animation is played
			if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= Player.Name then -- we check if we hit a dummy or player and if that dummy or player doenst have the same name as our player
				for _, v in pairs(alreadyHitObjects)do -- we loop through the table
					if v == hit.Parent.Name then -- if we have found the dummy or player's name inside of it, we wont hit it again
						loader:Stop() -- we stop our animation
						animation:Destroy() -- we destroy our animation so it doesn't stack inside our character
						return
					end
				end
				alreadyHitObjects[#alreadyHitObjects + 1] = hit.Parent.Name -- we add the hit object's name inside the table so it wont get hit again
				hit.Parent.Humanoid:TakeDamage(10 + Player.Data.SwordP.Value) -- we make the object's health go lower by 10
				CreateTag(hit.Parent.Humanoid)
			end
		end
	end)

	character.LeftHand.Touched:Connect(function(hit) -- once the player's right hand was touched
		if randomNumber == 2 then -- if we have the random number 1, means the right punch animation is played
			if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= Player.Name then -- we check if we hit a dummy or player and if that dummy or player doenst have the same name as our player
				for _, v in pairs(alreadyHitObjects)do -- we loop through the table
					if v == hit.Parent.Name then -- if we have found the dummy or player's name inside of it, we wont hit it again
						loader:Stop() -- we stop our animation
						animation:Destroy() -- we destroy our animation so it doesn't stack inside our character
						return
					end
				end
				alreadyHitObjects[#alreadyHitObjects + 1] = hit.Parent.Name -- we add the hit object's name inside the table so it wont get hit again
				hit.Parent.Humanoid:TakeDamage(10 + Player.Data.SwordP.Value) -- we make the object's health go lower by 10
				CreateTag(hit.Parent.Humanoid)
			end
		end
	end)
	character.RightFoot.Touched:Connect(function(hit) -- once the player's right hand was touched
		if randomNumber == 3 then -- if we have the random number 1, means the right punch animation is played
			if hit.Parent:FindFirstChild("Humanoid") and hit.Parent.Name ~= Player.Name then -- we check if we hit a dummy or player and if that dummy or player doenst have the same name as our player
				for _, v in pairs(alreadyHitObjects)do -- we loop through the table
					if v == hit.Parent.Name then -- if we have found the dummy or player's name inside of it, we wont hit it again
						loader:Stop() -- we stop our animation
						animation:Destroy() -- we destroy our animation so it doesn't stack inside our character
						return
					end
				end
				alreadyHitObjects[#alreadyHitObjects + 1] = hit.Parent.Name -- we add the hit object's name inside the table so it wont get hit again
				hit.Parent.Humanoid:TakeDamage(10 + Player.Data.SwordP.Value) -- we make the object's health go lower by 10
				CreateTag(hit.Parent.Humanoid)
			end
		end
	end)
	wait(0.5) -- we wait 0.5 seconds

	loader:Stop() -- we stop the animation
	animation:Destroy() -- we destroy it
elseif Val == "UnequipCombat" then -- if the given argument tells us to unequip the combat

	local findExistingAnimation = character:FindFirstChild("EquippedCombat") -- looks for something in the player's character called "EquippedCombat", in this case this will be our equipped animation which we'll store inside the player's character
	if findExistingAnimation then -- if it was found then
		local loader = character:WaitForChild("Humanoid"):LoadAnimation(findExistingAnimation)
		loader:Stop()
		findExistingAnimation:Destroy() -- we destroy it
	end
end

end)

I see the problem I think. You have 2 different variables for the LoadAnimation. You need to refer only to one. Basically this is what your doing:

Tool.Equipped:Connect(function()
       local anim = Humanoid:LoadAnimation(Animation)
       anim:Play()
end)

Tool.Unequipped:Connect(function()
       local anim = Humanoid:LoadAnimation(Animation)
       anim:Stop()
end)

What you need to do is something like I said, refer to using one animation:

Tool.Equipped:Connect(function()
     local AnimTrack = script.Parent.Humanoid:LoadAnimation(script:WaitForChild("Animation"))
     AnimTrack:Play()

     -- Code here

     Tool.Unequipped:Connect(function()
                AnimTrack:Stop()
         end)
end)

NOTE: You can also play the animation client sided! I also don’t recommend you using Instance.new(“Animation”) and then destroying it. Just put an animation inside the script that stays.