Emote Not Stopping

I’m creating an emote wheel, and there is currently one emote available. When I use the emote and cancel it using the spacebar the first time, it cancels the animation. But the second time I try to cancel it, the animation doesn’t stop. I’m able to move again, but the animation is still playing.

Here’s the script:

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local animator = hum:WaitForChild("Animator")

local emoteAnim = script.Parent:WaitForChild("EmoteAnim")

local isEmoting = false

local emoteTrack = nil

local function startAnimation(animID: string)
	emoteAnim.AnimationId = animID
	emoteTrack = animator:LoadAnimation(emoteAnim)
	
	ReplicatedStorage.CloseEmoteWheel:Fire()
	
	isEmoting = true
	
	emoteTrack.Looped = true
	emoteTrack:Play()
	
	hum.WalkSpeed =0.0075
	hum.JumpPower = 0
end

ReplicatedStorage.EmoteEvent.Event:Connect(function(anim)
	
	startAnimation(anim)
	
	UserInputService.InputBegan:Connect(function(i, gpe)
		if i.KeyCode == Enum.KeyCode.Space and not gpe and isEmoting == true then
			isEmoting = false
			
			print("Canceled: " .. anim)
			emoteTrack:Stop()
			emoteTrack:Destroy()
			
			emoteAnim.AnimationId = ""
			
			print(tostring(emoteTrack))
			
			hum.WalkSpeed = 16
			hum.JumpPower = 50.145
		end
	end)
end)



1 Like

You are connecting an InputBegan trigger every time the remote event is triggered. If it triggers more than once, you might run into unexpected and unintended behavior. It can also cause serious memory leaks if on the server, but I’m confident this is a Client sided script you’re showing us.
(Edit: Do note that memory leaks on the client are also serious, just less serious than server memory leaks.)

Consider connecting it only once and then structuring your code accordingly, one connection will suffice and will run whenever it triggers..

If that fixes it, then great! However I believe this may not actually be the root of your problem.
Make use of prints to make sure that you are referencing the correct emoteTrack, and not a different or older one.

1 Like

Is this what you meant?

local UserInputService = game:GetService("UserInputService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local animator = hum:WaitForChild("Animator")

local emoteAnim = script.Parent:WaitForChild("EmoteAnim")

local isEmoting = false

local emoteTrack = nil

local function startAnimation(animID: string)
	emoteAnim.AnimationId = animID
	emoteTrack = animator:LoadAnimation(emoteAnim)
	
	ReplicatedStorage.CloseEmoteWheel:Fire()
	
	isEmoting = true
	
	emoteTrack.Looped = true
	emoteTrack:Play()
	
	hum.WalkSpeed = 0.0075
	hum.JumpPower = 0
end

local connection

ReplicatedStorage.EmoteEvent.Event:Connect(function(anim)
	startAnimation(anim)
	
	connection = UserInputService.InputBegan:Connect(function(i, gpe)
		if i.KeyCode == Enum.KeyCode.Space and not gpe and isEmoting == true then
			isEmoting = false
			
			emoteTrack:Stop()
			emoteTrack:Destroy()
			
			emoteAnim.AnimationId = ""
			
			print(tostring(emoteTrack))
			
			hum.WalkSpeed = 16
			hum.JumpPower = 50.145
			
			connection:Disconnect()
		end
	end)
end)

you can use :Once to replace :Connect and you won’t need to disconnect it manually(:Once is only connect once). I don’t sure if it help the animation stop cuz it just a performance manage thing. So I need to know if it printing anything, i feeling you need to check gpe cuz Space key is for jump and it might block the input by the gpe

Using :Once would work, yes indeed, although do note;
Given the fact that you can simply make a much better structured close to identical connection outside of the event trigger, it becomes clear that using “:Once” is a hacky solution for a problem that shouldn’t exist!

Not at all!
This is what I mean:

ReplicatedStorage.EmoteEvent.Event:Connect(function(anim)
		--Your code here
end)

UserInputService.InputBegan:Connect(function(input, gameProcessed)
		--Your connection here
end)

Connecting just once will suffice for such a case! It will run whenever it is triggered.

See, a connection is something that you establish to tell your code:

“whenever this triggers, do this”

If you connect it more than once, you will be telling your code the same thing, but multiple times!

Example, if the event fires 5 times:
“whenever this triggers, do this” x5

And code does not have the ability that humans do to understand context, therefore what LUA will interpret is that each time you told it to do what I just said, you told it a completely different command, and so it will treat each one of those commands separately.
In the example I provided, it will run the same thing 5 times, because you told it “if this happens, do this” 5 times.

What that means is, each time that “this event triggers” it will “do that thing” once for every single order you gave it. Get what I mean?
This may result in undesired behavior.

Edit: Given that you run this code:

connection:Disconnect()

at the end of your connection, it may prevent the issue I described in this reply, however do note that said measure is unnecessary, since you can simply structure the function outside as I showed.

yeah I’m glad when you figure out something. btw does the initial problem still there

I’m not sure. I just sent OP a new code snippet with examples of what I mean. That may or may not fix their issue. We’ll see if we get a reply, I suppose!
I’d recommend you read it as well if you have any questions about what I replied to your suggestion.
Feel free to ask too!

I only have one question (I hope): What would the connection look like? Like a little snippet should be all I need to figure out what the connection would be (I have a feeling I’m being dumb and it’s simple).

It should pretty much be exactly the same thing as what you already did, except outside of the remote trigger.
Having in mind that the connection runs the exact same whenever said input is detected, you’d probably do something such as:

UserInputService.InputBegan:Connect(function(input, gameProcessed)
		isEmoting = false
		
		emoteTrack:Stop()
		emoteTrack:Destroy()
		
		emoteAnim.AnimationId = ""
		
		print(tostring(emoteTrack))
		
		hum.WalkSpeed = 16
		hum.JumpPower = 50.145
		
		connection:Disconnect()
end)

The only real difference is, as I said, you won’t be telling the code to add 1 new connection every time the remote is triggered.

Like this?

local connection

ReplicatedStorage.EmoteEvent.Event:Connect(function(anim)
	startEmote(anim)
end)

connection = UserInputService.InputBegan:Connect(function(input, gpe)
	if input.KeyCode == Enum.KeyCode.Space and not gpe and isEmoting == true then
		hum.WalkSpeed = 16
		hum.JumpPower = 50.145
		
		emoteTrack:Stop()
		emoteTrack:Destroy()
		
		emoteAnim.AnimationId = ""
		emoteTrack = nil
		connection:Disconnect()
	end
end)

I suppose so. Test it and do some debugging. As much as I’d like to help, you won’t get very far copy pasting code without understanding what it is doing!

By the way, why are you storing the connection? That is unnecessary. You don’t need to store it, or disconnect it every time it finishes running. Other than that it should be good.

If I didn’t have to store the connection, then why is this here?

I understand the confusion.
In the snippet I provided to you, I simply copied and pasted the function you wrote yourself, and implemented it inside the new function which is outside of the event trigger, in order to provide the example you asked for.

The existence of connection:Disconnect() therefore comes from your original code, although its presence is not necessary in the new code. This stems from the fact that I assumed you wanted to store it for some purpose of your own, which led me to ask “why are you storing the connection?”.
However if you don’t have a specific purpose for it, then it should not be there.

In most cases, no need to disconnect functions that are created with the purpose of running continuously during the game unless you want to clean them up after not needing them anymore.

I didn’t show this code earlier, but this was the emoteButton GUI script:

UserInputService.InputBegan:Connect(function(input, gpe)
	if input.KeyCode == Enum.KeyCode.G and not gpe and openedWheel == false then
		OpenEMOTE()
		
		emote1.MouseButton1Click:Connect(function()
			ReplicatedStorage.EmoteEvent:Fire(emote1.One.Value)
			return
		end)
		
	elseif input.KeyCode == Enum.KeyCode.G and not gpe and openedWheel == true then
		CloseEMOTE()
	end
end)

All I did was change the Connect() for the emote1.MouseButton1Click to a Once() connection. So technically, @hakhoito’s suggestion worked, since they suggested it first. Unless what @ReyReno777 said was what @hakhoito was getting at.

It does work. I never said that it does not work. :Once is valid a method that you utilize in order to establish a one-time-use connection.
What you have to understand is that your case does not require a one-time-use connection. Creating a new connection every time you get an input is problematic and can be done in a much simpler and better maintainable manner, which is creating an external function just once.

Creating an external function once when the script loads and using that instead is the standard for a reason and should only be deviated from when you have a specific reason to create connections dynamically.

Your behavior is identical for every time the trigger is fired. One singular function will suffice.

Here is an example of what I mean:

You have a company, and in it there is an employee that was hired to sorts papers for you in a company where papers arrive every few minutes.

What you are doing in your code is basically the following:
Every time new papers arrive, you walk up to that employee’s desk and tell them: “Hey, sort these papers for me, but only once, then never do it again!”
And then, when new papers arrive, you walk up to their desk one more time and give them new orders, telling them the exact same thing.
“Hey, sort these papers for me, but only once, then never do it again!”
And so you repeat, and tell them the exact same thing every time new papers arrive.

Does that work? Absolutely. Will the paper be sorted? Yes, it will indeed, and every time without fail.
However, a much better way would be simply walking up to them one singular time and saying “Every time papers arrive, sort them.” and never having to ask them again. Get it?

This is why it’s much more common to establish one external connection once when the script loads, for most scenarios.

So a local function? If so, for the

	UserInputService.InputBegan:Connect(function(input, gpe)
		
	end)

or the

emote1.MouseButton1Click:Connect(function()
	
end)

?
(I feel like a kid trying to do his math homework with his dad rn bro.).

Don’t worry. We all start somewhere. I was a noob at some point in order to get where I am today.
This is how I would set up the function you showed me:

local EmoteEvent = ReplicatedStorage:WaitForChild("EmoteEvent")
--[[Using WaitForChild because the game is not entirely and immediately available when the client
joins it, and some things need time to load, such as the content inside of "ReplicatedStorage"]]

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then
	--[[If nothing in this function runs with gameProcessed as true, then no reason to
	even try the other checks if gameProcessed is true, so it returns]]
		return
	end

	if input.KeyCode == Enum.KeyCode.G then
		if OpenedWheel == false then
			OpenEmote()
		else
			CloseEmote()
		end
	end
end)

Emote1.Activated:Connect(function()
--[[Creates only one connection when script loads.
Will run once every time the button "Emote1" is activated.]]
	EmoteEvent:Fire(Emote1.One.Value)
end)
--[[Since this is a function that is connected to a trigger, a return in its last line
will make no difference, and is therefore not necessary.]]

Edit: Fixed last explanation.

1 Like

THE FUNCTION WORKS!!

I’m happy to help. Feel free to ask any questions you might have. Godspeed.