- This is similar implementation to Roblox's Tween Service with the addition of more aspects of control, and is also compatible with older versions of the Roblox Client. The earliest tested version is as far back as 2014 Studio.
- I plan to have a general implementation intended for general Lua usage and not Roblox-specific.
- In its simplest form, Tweening is an animation, or the process of moving one number from one value to another in different “styles”. A style is how fast this number moves between these two values.
- This can get more complicated as you introduce different types of values, such as Positions, Rotations, CFrames (Model matrices), and more.
- The Roblox variant of the module is titled as
Tween_Roblox.lua
in the repo. You can either copy the code into aModuleScript
located ingame.ReplicatedStorage
, or download theTween_Place.rbxl
file and execute it.
- To use the Roblox variant of the module, create a new
Script
orLocalScript
and include the module:
--# Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--# Include
local Tween = require(:WaitForChild("Tween"))
- To create a new
Tween
instance using the Roblox variant of the module, type:
local newTween = Tween:new()
- There’s tons of properties that your Tween can have, all of them are explained in the Tween module!
duration = 1, -- The time in seconds that the Tween will last.
increment = 0.036, -- The rate of change for the Tweenable property. (Might need to change this depending on your FPS)
easingFunction = "easeInSine", -- The direction and style of the Tween.
delay = 0, -- How many seconds to wait before playing the animation.
isReversed = false, -- Whether the Tween plays in reverse or not.
loopCount = 0, -- How many times the Tween is repeated after playing once.
maxIncrement = nil, -- (If nil, this property is disabled!) The time of the Tween goes from 0 - 1, this will end the Tween if the current time of the Tween is this value.
snapAtEnd = true, -- Whether the Tweenable property will snap to it's goal value once the maxIncrement is met.
- Here is an example of a few properties you can set for your Tween:
- Hint - Check https://easings.net/ to see the different easing functions you can use.
newTween.easingFunction = "easeInOutElastic"
newTween.duration = 3
newTween.isReversed = false
newTween.loopCount = 0
- Practically any property of an Instance is Tweenable. Though there are a few parameters I’ll have to cover before you can start Tweening!
- When Tweening, you’ll need two tables to represent the Instances you want to Tween.
- The first Table is called
tweenObjects
, which includes the Instance you want to Tween, and theProperty
of that Instance that will be modified.
local tweenObjects = {
-- This will tween the CFrame of a Part.
{instance = workspace.Part,
property = "CFrame"},
}
- You can also animate multiple properties at the same time by simply adding another table to the
tweenObjects
table. - Here’s an example of Tweening both the
CFrame
of a Part, and theTransparency
of another Part.
local tweenObjects = {
-- This will tween the CFrame of a Part.
{instance = workspace.Part,
property = "CFrame"},
-- This will tween the Transparency of another Part in workspace named "BasePlate".
{instance = workspace.BasePlate,
property = "Transparency"}
}
- The second Table is called
tweenGoals
, which includes the beginning and end parameters of your Tween. In this case, it’s the starting and endCFrame
. - Hint - if you set start to
nil
, it will just default to the initialCFrame
of the Part!
local tweenGoals = {
-- The Part's CFrame will start from it's current value, to the position (-6, 0.5, -14)
{start = nil,
goal = CFrame.new(-26, 0.5, -14)},
}
- If you have multiple properties in
tweenObjects
, keep in mind you’ll have to add more tables to thetweenGoals
table. - Here’s a continuation of the multi-properties example I provided for
tweenObjects
:
local tweenGoals = {
-- The Part's CFrame will start from it's current value, to the position (-6, 0.5, -14)
{start = nil,
goal = CFrame.new(-26, 0.5, -14)},
-- The Part named "BasePlate" will have it's Transparency start from it's current value, 0, to the 1.
{start = nil,
goal = 1.0},
}
- Finally, you can play the Tween you created using:
newTween:play(tweenObjects, tweenGoals, "Server")
- The third parameter is where the Tween was fired from. If you’re using a regular
Script
, then you would type“Server”
, if you’re using aLocalScript
, type“Client”
. This is simply used to determine the update execution time that will be used when tweening the object. - Hint - If you want code ahead of the Tween to still process despite the Tween still running, use:
spawn(function() -- spawn might be written as Spawn depending on the version of studio you're using:
newTween:play(tweenObjects, tweenGoals, "Server")
end)
-- The code below will run even if the Tween is still playing now.
- Hint - You can also check if a Tween is playing using
Tween.isPlaying
. More properties can be found inside of the module itself.
- You can easily stop your Tween any time using:
newTween:stop(false)
- You can also use the parameters
canSnap
andresetTime
to end your Tween. canSnap
, when set totrue
means that the Tween will automatically snap to the ending value when stopped.resetTime
will wait a specified amount of seconds before ending the Tween.
newTween:stop(true, 1) -- Wait one second, then snap the property to the end point.
- Hint - If you have
isReversed
set totrue
in your Tween and you have a number higher than 0 forloopCount
, you may need to reset it's value after theTween:stop()
function is exececuted to ensure that if the Tween is played again, it reverses properly.
newTween:stop(false)
newTween.isReversed = false -- Since the tween is repeated, It reversed after the second loop, so it must be set back at the end to not start from the opposite position.
--# Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--# Include
local Tween = require(ReplicatedStorage:WaitForChild("Tween"))
--# Execution
local newTween = Tween:new()
newTween.easingFunction = "easeOutBounce"
newTween.duration = 3
newTween.isReversed = false
newTween.loopCount = 1
local tweenObjects = {
{instance = workspace.Part,
property = "CFrame"},
{instance = workspace.BasePlate,
property = "Transparency"},
}
local tweenGoals = {
{start = nil,
goal = CFrame.new(-26, 0.5, -14)},
{start = nil,
goal = 1.0},
}
newTween:play(tweenObjects, tweenGoals, "Server")
newTween.isReversed = false -- Since the tween is repeated once, It reverses after the second loop, so I just set reversed to false at the end.
A Tween that loops one time and manipulates multiple properties.
--# Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--# Include
local Tween = require(ReplicatedStorage:WaitForChild("Tween"))
--# Execution
local newTween = Tween:new()
newTween.easingFunction = "easeOutBounce"
newTween.duration = 2
newTween.isReversed = false
newTween.loopCount = 999999
local tweenObjects = {
{instance = script.Parent.ScreenGui.Frame,
property = "Position"},
{instance = script.Parent.ScreenGui.Frame,
property = "Rotation"},
}
local tweenGoals = {
{start = nil,
goal = UDim2.new(1, -100, 0.5, -50)},
{start = nil,
goal = 90},
}
newTween:play(tweenObjects, tweenGoals, "Server")
newTween.isReversed = false -- Since the tween is repeated, It reversed after the second loop, so I just set it back at the end.