How to get the same result as "Tween.Completed:wait()" with "Tween.Completed" function?

I want my script to continue only after a Tween is completed.
For this, I use Tween.Completed:wait().

local TweenService = game:GetService("TweenService")
wait(2)
local Tween = TweenService:Create(
	workspace.Part, 
	TweenInfo.new(3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), 
	{Position = Vector3.new(10, 0.5, 0)} 
)
Tween:Play()
Tween.Completed:wait()
print("After Tween") -- prints only when the Tween is completed

But when I want to run some code inside the Completed function, apparently it doesn’t wait and makes print("After Tween") run immediately after Play:

Tween.Completed:Connect(function(PlaybackState)
	print(PlaybackState)
end)
print("After Tween")

It will run the print("After Tween") before tween completed…

After Tween
Enum.PlaybackState.Completed

How to solve this?

4 Likes

local state = Tween.Completed:Wait() if you need the state while using Wait(). :Wait() functions will pass the same arguments that :Connect() functions do. If there is more than one argument, you can do local arg1, arg2 = x.Y:Wait() and it’ll pass them into their respective variables.

Tween.Completed is an event which is fired whenever the tween is completed. Put the print(“After tween”) inside the tween.Completed function. Lines of code after the tween.Completed function will not wait for the function to be called.

You could try something like this.

local tweenDone = false

Tween.Completed:Connect(function(PlaybackState)
	print(PlaybackState)
	tweenDone = true
end)

repeat
	wait()
until tweenDone = true

--Anything below here will not run until after the tween is done
print("After tween")

All typed on mobile, couldn’t really test or typo check. Hopefully you got the idea though

Try this

Tween.Completed:Connect(function(PlaybackState)
    if PlaybackState == Enum.PlaybackState.Completed then
        print("After Tween")
    end
end)

You should never repeat wait when events exist. It’s much slower.

That’s why you can get arguments passed to :Wait() functions directly.

He said that he is trying to avoid using “Tween.Completed:Wait()” because it’s not delivering what he was aiming for, although it isn’t the most performance-cautious it does work in the end.

Where did they say they were trying to avoid using it? The title says they want the same functionality as wait with tween completed… i.e. yielding with a result. Your code would do the exact same as mine just with more overhead cost.

So

local TweenService = game:GetService("TweenService")
wait(2)
local Tween = TweenService:Create(
	workspace.Part, 
	TweenInfo.new(3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), 
	{Position = Vector3.new(10, 0.5, 0)} 
)
Tween:Play()
local state = Tween.Completed:Wait()
print(state)
print("After Tween")

Would do the exact same thing as repeating wait with a connect function, but it’d be more efficient

1 Like

My bad, I meant it seemed they were trying to avoid using it and instead wanted to use Tween.Completed:Connect(), the reason is unknown to me though.

Alternatively he could just put the "print(“After Tween”) within the Tween.Completed as @bunarion said, but I saw he didn’t and assumed he was trying to avoid that for whatever reason either.

My answer was just made to provide variety and to give my take on his problem with his script and how he could possibly fix it. He doesn’t have to use it exactly but he could definitely learn something off of it or use a similar method as to mine.

Thank you all.
I’ll try to explain better. I want these steps to be executed SEQUENTIALLY:

  1. Play the Tween
  2. Wait until it’s completed
  3. When completed, run some code inside Tween.Completed:Connect(function(PlaybackState)
  4. … and only then, continue with the script sequence (in this case print("After Tween") was just an example, but actually has all the rest of the script after)…

Why don’t you just put the code to continue after the tween inside the Tween.Completed function? There is no difference in having it after the function and inside the function, if anything it’ll be better.

2 Likes

I’ll not put 2000 lines inside Tween.Completed only because there isn’t a better solution…

I agree, you guys are really overcomplicating this. Tween.Completed returns a RBXScriptSignal. These have two functions, “:Wait” and “:Connect”. Instead of waiting for the script signal to be called, and then running code, use the “:Connect” option which literally does that for you. If you only need it once, you can achieve your goal like so to disconnect and GC the connection once your code has ran:

c = tween.Completed:Connect(function()
    --run your code here
    c:Disconnect()
end)

this works because :Connect, returns a “Connection Object”. This object can be disconnected and sent to garbage collection by using the :Disconnect() operator.

1 Like

There is nothing wrong with putting code in the connection function, its actually the right way to do it. Now if your code is 2,000 lines long thats a whole other problem of the way your game is programmed and organized.

Why is that? I stand by my statement. Maybe for a core script that is okay, but if you have like 10 server scripts all with 2,000 lines that is not well written by any means. Functions should be organized in modules and named properly for readability and re-usability. The way I try to keep my code is have the scripts store variables, and the code stored in module scripts make changes to those variables.

In any case, my question was about a simple solution to a simple problem, but this is not always possible.
Anyway, I appreciate everyone’s support. :+1:

1 Like

I want to thank @PersonifiedPizza (which I don’t know why he gave me the solution in PM).

local playbackState = Tween.Completed:Wait()
print(playbackState)
print("After Tween")

It made me realize that the solution was simpler than I thought: if I want to wait for the Tween to complete, I don’t need to run some code inside Tween.Completed:Connect(function(PlaybackState)… In this case, just follow his example above, ie, put all code to continue after :wait()

4 Likes