SuperTween - Tween ANYTHING

I have a problem: you can’t tween the color of a Beam. This simply won’t do.

SUPERTWEEN

THAT’S RIGHT, NOW YOU CAN EVEN TWEEN TEXT!!!
SuperTween - Creator Store (roblox.com)

SuperTween is a utility for tweening anything you want. You can create your own rules for any data type or instance property. It’s compatible with the usual TweenService code, so you can swap it in and out effortlessly. It is fully open source and actively tested in my projects.

Here’s an example of tweening various particle properties:

local tweenInfo = TweenInfo.new(3, Enum.EasingStyle.Elastic)

local properties = {
	Size = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 5)
	}),
	Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 0.5),
		NumberSequenceKeypoint.new(1, 0)
	}),
	Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, Color3.fromRGB(255, 0, 0)),
		ColorSequenceKeypoint.new(1, Color3.fromRGB(255, 0, 255))
	})
}

local tween = SuperTween.new(script.Parent.ParticleEmitter, tweenInfo, properties)
tween:Play()

Here’s an example of tweening a beam:

local tweenInfo = TweenInfo.new(5, Enum.EasingStyle.Linear)

local properties = {
	Transparency = NumberSequence.new({
		NumberSequenceKeypoint.new(0, 1),
		NumberSequenceKeypoint.new(1, 0)
	}),
	Color = ColorSequence.new({
		ColorSequenceKeypoint.new(0, Color3.fromRGB(255, 0, 0)),
		ColorSequenceKeypoint.new(1, Color3.fromRGB(255, 0, 255))
	})
}

local tween = SuperTween.new(script.Parent.Beam, tweenInfo, properties)
tween:Play()


Here’s an example of tweening text:

local tweenInfo = TweenInfo.new(5, Enum.EasingStyle.Sine)
local properties = {Text = "This is SUPER TEXT"}
local tween = SuperTween.new(script.Parent.TextLabel, tweenInfo, properties)

tween:Play()

Example of tweening a model’s scale:

local tweenInfo = TweenInfo.new(5, Enum.EasingStyle.Elastic)
local properties = {Scale = 0.5}
local tween = SuperTween.new(workspace.Chrythm, tweenInfo, properties)

tween:Play()

Here’s an example of tweening a model’s pivot:

local tweenInfo = TweenInfo.new(self.MoveTime, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, -1, true)
local properties = {Pivot = self.EndCFrame}
local tween = SuperTween.new(self.Instance, tweenInfo, properties)

tween:Play()


These floating flower platforms are made up of parts, and use SuperTween to get around.

You may notice that while they are moving back and forth, they are also hovering up and down. This is possible through the Updated event.

Events

Along with the typical Completed event, SuperTween gives you an Updated event. This event passes the current alpha of the tween, which is a value from 0 to 1 used for lerping.

In the case of the flowers, the Update event is simply used to apply an additional vertical offset.

tween.Updated:Connect(function()
	local timeNow = tick() % 10000
	local height = math.sin(timeNow * MovingFlower.OscillateSpeed) * MovingFlower.OscillateHeight
	local rotation = timeNow * MovingFlower.SpinSpeed

	local cframe = self.Instance:GetPivot()
	cframe += Vector3.yAxis * height
	cframe *= CFrame.Angles(0, rotation, 0)

	self.Instance:PivotTo(cframe)
end)

This is my implementation of a spinning, oscillating movement. What’s nice is that because this event is fired after SuperTween modifies the Pivot, we can assume the flower is horizontally positioned correctly. And from here, we just apply some offsets using math to get the desired motion.

And as an added bonus, we can move any players standing on the platform after every update for a precise physics feel.

Note: The Completed event does not pass an Enum.PlaybackState like TweenService. Instead, it is an event that fires when the tween is over. This is because multiple SuperTweens can overlap, and do not cause the other to cancel playback. This behavior deviates from TweenService and may need to be taken into consideration if something unexpected occurs.

Data Types

In the DataTypes module, you will find all of my current implementations of tweening data types. Some of these, like ColorSequence and NumberSequence, are only possible through SuperTween or another custom utility. The nice thing here is that you can control how ANY data type is tweened!

For example, here is how tweening a Vector3 is implemented:

function DataTypes.Vector3(a, b, t)
	return a:Lerp(b, t)
end

Other than dealing with TweenInfo, this is pretty much built-in for us. Lerp is a function of Vector3s and some other data types, so we can use the same code for them as well.

function DataTypes.Vector2(...)
	return DataTypes.Vector3(...)
end

function DataTypes.CFrame(...)
	return DataTypes.Vector3(...)
end

function DataTypes.Color3(...)
	return DataTypes.Vector3(...)
end

In this module, the data types are implemented by name. For example, if you run this code in the command bar:

print(typeof(Color3.fromRGB(255, 170, 120)))

The console prints out a string that says “Color3” — names are interpreted from the typeof function. So, if you want to tween the number 5 for example, find out what typeof(5) is, then use the result as the name of the function. (It’s “number”)

Speaking of numbers, do you recognize what I did for tweening the number data type?

function DataTypes.number(a, b, t)
	return a + ((b - a) * t)
end

This is the classic lerp formula! My understanding of this is that we:

  • Take the starting point
  • Find the space between the points
  • Add a percentage of that space

This is essentially the definition of a lerp, and it works with most data types based on numbers. So if we use an alpha of 0.5, that would represent 50% of the way from point A to B. The result would be halfway between the two points. (I used the letter “t” for “time” to represent alpha in this implementation)

Custom Properties

In the Customs module, you will find an implementation of tweening pivots.

Customs.Pivot = {
	Whitelist = {"PVInstance"},
	Set = function(instance, a, b, t)
		local cframe = DataTypes.CFrame(a, b, t)
		instance:PivotTo(cframe)
	end,
	Get = function(instance)
		return instance:GetPivot()
	end
}

There are a few things to talk about here, but let’s start with the whitelist. Pivots exist for any instance that inherits from PVInstance, like a BasePart or Model. (A Part, UnionOperation, and a MeshPart are all BaseParts!)

Because Roblox has a class inheritance structure, we can specify groups of object behavior by name. For example, a Part gets most of its behavior from BasePart. You can see this in the documentation for a Part:

image

This is also the case for MeshParts and UnionOperations. Anyways, only objects that inherit from PVInstance will have Pivots. So, that is exactly what we put in the whitelist.

The Get and Set functions tell SuperTween what to do for each update.

  • Get returns the current value of what is being modified — is passed the instance being tweened.
  • Set applies a modification — is passed the instance being tweened, the starting value, the target value, and the alpha. It is up to you to determine how to implement this lerp. You have the DataTypes module at your disposal for lerping all sorts of data types.

Conclusion

That about covers it! I am continuing to improve this utility as I use it in my projects. It’s open source, so feel free to suggest edits in the replies. The motivation behind developing this was to implement sticking to tweening platforms, but it has since come in handy for many other things, such as getting around the TweenService framerate limit. Let me know what you think. :slight_smile:

Note: TweenService dynamically lowers its animation framerate. SuperTween does not. If you are trying to work around that behavior, this utility will fix that for you. However, because of that, it may be less performant. You may need to use SuperTween sparingly and ensure that you clean up any ongoing tweens that are no longer needed.

SuperTween - Creator Store (roblox.com)

92 Likes

This is insanely useful and looks well made, great job

4 Likes

How do you calculate the AssemblyLinearVelocity and AngularVelocity?

3 Likes

THIS IS AMAZING, let me check if it can tween the scale of a model.

3 Likes

uhh I am sure TweenService already works like that but, you mean, you made it work another way or?

I mean

Doesn’t it already work like

TweenService.new(Target, TweenInfo for time and etc., Target Property [like CFrame or color or GUI Pos])

I am too stupid to understand this, i am sure TweenService already does these

2 Likes

the advantage is that you can tween color and number sequences (probably number ranges aswell), along with some other things a TweenService can’t do.
I was motivated to make something like that but i never got my hands onto making it.
You can define custom tween functions for each type too

6 Likes

holy crap its tween 2.0! This is truly game-changing, i cant believe someone figured out how to make a version 2 to TWEENING!! How did he even make this… absolutely insane. I will definitely be using this in EVERY game i make, thank you.

2 Likes

btw you should make a custom logo for it

3 Likes

im too stupid to understand how this works i really just want tweening text how do i tween the text with this??

3 Likes

Hi, so for tweening text, what are you trying to accomplish? If you want a typewriter effect, I would recommend tweening the MaxVisibleGraphemes property.

3 Likes

i tried tweening the text itself which didnt work (it just waited some time and changed the text itself) i dont know what maxvisiblegraphemes does but ill try tweening that

nvm i know what it does now this seems very useful

3 Likes

it seems like i will have to get how many characters are in the text for it to work so how would i do that

nevermind i figured it out now i am gonna try to tween it thanks

yay it worked!!!

2 Likes

It can! I forgot to include this in the original version, so I have updated it now to include this.

1 Like

I will change the behavior of text tweening to do this as well.
Edit: This has now been added! Check the original post for an example.

2 Likes

The trick is that instead of using velocity, I just update the character’s position. Here’s all of the relevant flower platform code I have for reference:

function MovingFlower:ApplyAdditiveAnimation()
	local timeNow = tick() % 10000
	local height = math.sin(timeNow * MovingFlower.OscillateSpeed) * MovingFlower.OscillateHeight
	local rotation = timeNow * MovingFlower.SpinSpeed
	
	local cframe = self.Instance:GetPivot()
	cframe += Vector3.yAxis * height
	cframe *= CFrame.Angles(0, rotation, 0)
	
	self.Instance:PivotTo(cframe)
	self:MovePlayer(cframe)
	self.LastPivot = cframe
end

function MovingFlower:MovePlayer(cframe)
	local player = MovingFlower.Player.Get()

	if not player.Character.Local.Classes.GroundCheck:IsStandingOn(self.Instance) then
		return
	end
	
	local playerCFrame = player.Character:GetCFrame()
	local playerRelative = self.LastPivot:ToObjectSpace(playerCFrame)
	local playerNew = cframe:ToWorldSpace(playerRelative)
	
	player.Character:SetCFrame(playerNew)
end

I have some classes behind the scenes dealing with the player, but the important part is that the methodology goes like this:

  • SuperTween fires the Updated event
  • After each update, check if the player is standing on the platform
  • If they are, get the last update’s cframe
  • Get the player cframe relative to this last update
  • Apply this relative offset to where the platform currently is

So in short, the platform is keeping track of where the player is relative to itself, then keeping that relative cframe in place for the current update.

2 Likes

Ahh I see. the thing is this would not be viable if we wanted to move let’s say 100 parts on a platform when we tween the platforms position.

I saw this thread:

and I would like to know if it’s possible to do it together using your module. But I’m worried it will not since we would need to change Assembly Linear Vel/Rot at a RenderStepped/Stepped before physics is calculated and as well as relying on its DeltaTime Parameter.

1 Like

If you want parts sitting on top of a platform to move with it, yes that would be a better method. SuperTween uses task.wait() to update instead of RunService events…

1 Like

Absolutely impressive work. This will make workflow way faster and easier.

1 Like

Certainly going to be using this, I had a problem with tweening beam colours yesterday so this is a godsend!

1 Like

This is AMAZING! wonderful job on this! 0_0