The "Smart Tween" Library - create, play, and automatically destroy Tweens on command!

Edit 11/28/2021: Updated thread to include StopAll() information.
Edit 01/14/2022: Realized I forgot the API documentation, working on it now :flushed:
Edit 04/16/2022: Wheeee, I still haven’t had time to work on an API doc. I gotta cut down on the number of projects I’m doing. Somebody send help.

Hello TweenService enthusiasts! (Or anti-TweenService enthusiasts.) As some of you may know, Tweens are a great way to smoothly animate properties of any Instance within Roblox experiences, to give a “high quality” appearance at a significantly reduced performance cost when compared to while true do, while wait() do, and for i=420,69,-1 do loops.

However, what not every TweenService user knows is that Tweens do not clean up after themselves when playing. Therefore, creating Tweens that will only be used once can eventually build up useless space on the server, causing cascading lag as the server runs for longer periods of time. This can be easily fixed with a simple code snippet that destroys the Tween upon being completed; I’ll leave it to the Community Tutorials tab to show you how to do this, though.

Typing this call over and over can be quite time-consuming though, so I made a module specifically to save developers many a keystroke and allow Tweens to be used and automatically cleaned up in any script–even LocalScripts if you put the module in ReplicatedStorage!–known simply as “Smart Tween”.

The module has three functions, those being “Tween”, “TweenModel”, and “StopAll”. An API documentation is included within the module so that you can understand what both of these even do. If you’re confused, please contact me with your questions! I’m pretty sure that people have made this module for their own games many times before, but if not, I’ll consider that quite the surprise.

Here’s the module link on the Library!
https://www.roblox.com/library/7925918452/Smart-Tween
Hope this helps you protect your wrists while developing that new banger of a game–I mean, “experience” that you’re working on! All I ask is that you credit me if you use this. I eventually plan to add features to tween ColorSequence and NumberRange objects, though that’ll come at a later time when I can work on this module more actively.

Anyway, cheers!
– Catz.

NOTE: TWEENMODEL() ONLY WORKS ON MODELS WITH A PRIMARY PART, AND ONLY WORKS ON CFRAME AT THE MOMENT
Edit: Darn typos.

10 Likes

I’ve recently added a new StopAll() function to the module that cancels (and destroys) all currently-running Smart Tweens.

Source? Tweens (TweenBases) are just instances, they won’t be garbage collected differently from other instances. When the code block it has been created in finishes running, and there aren’t any references to it further in the script, it will be gc’d.

1 Like

So, Instances have an issue where any connections to it with an reference to the instance will not allow that instance to be GCed. Logically, you would think that wouldn’t be an issue because it’s just a circular reference, but Luau’s GC has no understanding of instances.

local instance = Instance.new("BindableEvent")
instance.Event:Connect(function()
    print(instance)
end)
-- ^ instance is never GCed.

You can read about it here.
PSA: Connections can memory leak Instances!

In order to fix this, you need to disconnect that connection, and destroying does that.
Except for some reason, tweens don’t destroy themselves after played (i guess a back compatibility issue), luckily you are only gonna have issues if you have any connections with a reference to the tween. (rare occasion for me)

So, that means the tween will still get garbage collected even if the code is listening for the .Completed event (with :Wait and not :Connect)?

local Tween = TweenService:Create(...)

Tween.Completed:Wait()

--Does the tween get GC'd in this scenario?

If there’s a reference to the tween on that thread, it can only get GCed when there’s no references left. But since :Wait are temporary connections, then yeah no issues there.

I personally have QuickTween because I always :Play my tweens right away and it also destroys the tween.

1 Like

this seems pretty useless, considering that when creating a tween without declaring it as a variable, it can’t be GC’d anyway

Yeah well it saves you a lot of typing if you’re only gonna play a tween one time in your game and then be done with it.

Instead of typing

local TweenService = game:GetService("TweenService")
local tween = TweenService:Create(Target,TweenInfo,Properties....)

tConnect = tween.Completed:Connect(function()
	tConnect:Disconnect()
	tween:Destroy()
end)
tween:Play()

You’d instead just be doing

local SmartTween = require(game:GetService("ReplicatedStorage"):WaitForChild("SmartTweenModule"))
SmartTween:Tween(Target,Info,Properties)

Situational? Maybe. But conserve your fingers! You don’t want to be having joint pain from typing out the first block of code!

you can do this in one line.

game:GetService("TweenService"):Create(Target, Info, Properties):Play()

it’ll be GC’d immediately after playing, since there’s no declared variable to the tween.

You should meet my friend, @LuaRook. I’m fairly certain that he would love to disagree with you.

Just because something isn’t declared via local (or similar) doesn’t mean it gets GC’d immediately after playing fully.

One of us has a lot to learn from the other person about TweenService, to be honest. I’d go into more detail, but this is Community Resources, not Scripting Feedback. So I won’t.

Very rarely would I see use in procedurally tweening something when you can use the mathematical approach: linear interpolation. That’s how tweens calculate movement anyway. Sure it can be more complex than just making a tween, but if you’re so inclined to preserve system resources, you might as well.

1 Like