How to cancel a tween in function?

I’m making a script where if an event fires, it plays a tween, and I want to make it so that if the event fires again, it cancels the tween that’s playing (if one is playing at that time)

Tried a lot of different solutions, but nothing seems to be working. This is my current script (yes I know it’s messy, i will make it better after I fix this)

local tweenservice = game:GetService("TweenService")
local activeTween
game:GetService("ReplicatedStorage").Events.SetAnimals.OnClientEvent:Connect(function(prodtime, amounttonext, creating)
	if activeTween then activeTween:Cancel() end
	if not creating then
		if not amounttonext then
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(prodtime, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Wait()
			script.Parent.Size = UDim2.new(0,0,0.615,0)
			activeTween = nil
		else
			local timecompleted = prodtime-amounttonext
			script.Parent.Size = UDim2.new(timecompleted/prodtime*0.971,0,0.615,0)--5.4/14.4
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(amounttonext, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Wait()
			script.Parent.Size = UDim2.new(0,0,0.615,0)
			activeTween = nil
		end
	else
		if not amounttonext then
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(prodtime, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Wait()
			script.Parent.Size = UDim2.new(0,0,0.615,0)
			activeTween = nil
		else
			local timecompleted = prodtime-amounttonext
			script.Parent.Size = UDim2.new(timecompleted/prodtime*0.971,0,0.615,0)--5.4/14.4
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(amounttonext, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Wait()
			script.Parent.Size = UDim2.new(0,0,0.615,0)
			activeTween = nil
		end
	end
end)
7 Likes

Yes, that’s exactly what I’ve been doing. It doesn’t work. Are you sure you read the post right?

7 Likes

Then I don’t understand your problem. What exactly is not working? I tried the code and it seems to cancel the tween just fine.

I simulated what you’re doing in your code like this with a Frame:

local tweenservice = game:GetService("TweenService")
local activeTween
local func = function(prodtime, amounttonext, creating)
	-- omitted for the sake of brevity
end

task.wait(3)

task.spawn(function ()
	func(10,9,true)
end)

task.delay(1, function ()
	func(5,2,true)
end)

Best regards,
Pinker

6 Likes

What I mean is that if the function connected to an event fires, it plays a tween, and if that same event fires while that tween is running, it would cancel that tween.

I don’t know how to cancel it. I tried making a global variable and assigning it to that, and then running activeTween:Cancel(), but it didn’t work.

4 Likes

Maybe the issue is not in the script you sent?
Could you provide a minimum non-working sample that showcases your problem? That would make it much easier to debug.

7 Likes

This is the only script in my game that is responsible for creating the tween for that gui,
I’ll try to make something that showcases the issue more clearly.

7 Likes

I hope this is easier to understand. I fire this event once, then wait 5 seconds and then fire it again, the duration of the tween is 10 seconds, so it should have stopped the tween.

local activeTween = nil
local tweenservice = game:GetService("TweenService")
game:GetService("ReplicatedStorage").Events.TestEvent.OnClientEvent:Connect(function()
	if activeTween then
		activeTween:Cancel()
        script.Parent.Size = UDim2.new(0,100,0,100)
		activeTween = nil
	end
	activeTween = tweenservice:Create(script.Parent, TweenInfo.new(10, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {Size = UDim2.new(0, 200, 0, 200)})
	activeTween:Play()-- If 'TestEvent' fires again, I want to cancel this, but inside of the same function.
	activeTween.Completed:Connect(function()
		script.Parent.Size = UDim2.new(0,100,0,100)
	end)
	activeTween = nil
end)

The function:

if activeTween then
		activeTween:Cancel()
		activeTween = nil
	end

is not cancelling activeTween.

7 Likes

Is the tween still completing after you call the Cancel() method?

6 Likes

Yes, it scales back to 0,100,0,100 after 10 seconds.

5 Likes

It could be that the script continues to run after the if statement, creating a new Tween and running it. Add a return after activeTween = nil to halt the execution after you cancel the Tween:

if activeTween then
    activeTween:Cancel()
    script.Parent.Size = UDim2.new(0,100,0,100)
    activeTween = nil
    return
end
5 Likes

It still keeps going for 10 seconds, sadly.

4 Likes

Oh, just noticed the issue. You set activeTween to nil at the end of the function so when the event is called once again, activeTween is nil so it never runs the code inside the if statement. Do this instead:

local activeTween = nil
local tweenservice = game:GetService("TweenService")
game:GetService("ReplicatedStorage").Events.TestEvent.OnClientEvent:Connect(function()
	if activeTween then
		activeTween:Cancel()
        script.Parent.Size = UDim2.new(0,100,0,100)
		activeTween = nil
	end
	activeTween = tweenservice:Create(script.Parent, TweenInfo.new(10, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {Size = UDim2.new(0, 200, 0, 200)})
	activeTween:Play()-- If 'TestEvent' fires again, I want to cancel this, but inside of the same function.
	activeTween.Completed:Connect(function()
		script.Parent.Size = UDim2.new(0,100,0,100)
		activeTween = nil
	end)
end)

This is most likely the issue.

6 Likes

This actually fixed it. Thank you so much. I’ll add this to the main script and see if it works.

6 Likes

I’ve adjusted the code a bit, and it is indeed the issue that DevX also noticed.

local tweenservice = game:GetService("TweenService")
local activeTween : Tween

local func = function()
	if activeTween and activeTween.PlaybackState == Enum.PlaybackState.Playing then
		activeTween:Cancel()
		script.Parent.Size = UDim2.new(0,0,0,0)
	end
	
	activeTween = tweenservice:Create(
		script.Parent, 
		TweenInfo.new(10, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), 
		{Size = UDim2.new(1, 0, 1, 0)}
	)
	activeTween:Play()-- If 'TestEvent' fires again, I want to cancel this, but inside of the same function.
	activeTween.Completed:Wait()
	script.Parent.Size = UDim2.new(0,0,0,0)
end

task.wait(3)

task.spawn(func)
task.delay(5, func)
task.delay(10, func)
task.delay(15, func)

I think my solution is a bit cleaner though

5 Likes

I applied it in this, unorganized script (sorry about that.), and it didn’t seem to work. Did I skip a step or something?

local tweenservice = game:GetService("TweenService")
local activeTween
game:GetService("ReplicatedStorage").Events.SetAnimals.OnClientEvent:Connect(function(prodtime, amounttonext, creating)
	if not creating then
		if not amounttonext then
			if activeTween then
				activeTween:Cancel()
				script.Parent.Size = UDim2.new(0,0,0.615,0)
				activeTween = nil
			end
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(prodtime, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Connect(function()
				script.Parent.Size = UDim2.new(0,0,0.615,0)
				activeTween = nil
			end)
		else
			local timecompleted = prodtime-amounttonext
			if activeTween then
				activeTween:Cancel()
				script.Parent.Size = UDim2.new(timecompleted/prodtime*0.971,0,0.615,0)--5.4/14.4
				activeTween = nil
			end
			script.Parent.Size = UDim2.new(timecompleted/prodtime*0.971,0,0.615,0)--5.4/14.4
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(amounttonext, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Connect(function()
				script.Parent.Size = UDim2.new(0,0,0.615,0)
				activeTween = nil
			end)
		end
	else
		if not amounttonext then
			if activeTween then
				activeTween:Cancel()
				script.Parent.Size = UDim2.new(0,0,0.615,0)
				activeTween = nil
			end
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(prodtime, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Connect(function()
				script.Parent.Size = UDim2.new(0,0,0.615,0)
				activeTween = nil
			end)
		else
			local timecompleted = prodtime-amounttonext
			if activeTween then
				activeTween:Cancel()
				script.Parent.Size = UDim2.new(timecompleted/prodtime*0.971,0,0.615,0)
				activeTween = nil
			end
			script.Parent.Size = UDim2.new(timecompleted/prodtime*0.971,0,0.615,0)--5.4/14.4
			activeTween = tweenservice:Create(script.Parent, TweenInfo.new(amounttonext, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = UDim2.new(0.971, 0,0.615, 0)})
			activeTween:Play()
			activeTween.Completed:Connect(function()
				script.Parent.Size = UDim2.new(0,0,0.615,0)
				activeTween = nil
			end)
		end
	end
end)
3 Likes

This code depends on other variables which could be affecting the way it runs. Can I see the script that fires the RemoteEvent?

2 Likes

Also, it’d be easier if the code was refactored into smaller functions.

3 Likes

I’m sorry for not responding, I wasn’t home.

When I test it, the event gets fired with the values

prodtime = 14.4 (in seconds)
amounttonext = nil
creating = game.ReplicatedStorage.Placeables.Other.Egg (this one isn’t really relevant, but it is not nil.)

2 Likes