[V2] Tween+ | Advanced & performant tweening

Logo

An open-source tweening library for Roblox, featuring advanced
datatypes, customization, interpolation, and optimization.

ModuleGitHubGitBook




:glowing_star: Like never before!

Experience tweening on Roblox like never before.

With all the features of TweenService,
and many new amazing additions:

  • Advanced networking for efficient global tweening.
  • Native Bézier curves support.
  • Attributes support.
  • Support for advanced data types:
    • Sequences.
    • Ranges.
    • Strings.
  • Support for method-based properties:
    • Pivot.
    • Scale.
  • Custom easing functions.
  • Accurate color interpolation (Oklab).
  • Framerate limit control.
  • Beautiful, intuitive syntax.
  • And much more!

It’s safe to say that Tween+ does it all, without compromise!

:high_voltage: Fast. Stable. Intuitive.

  • Blazingly fast, ultra-optimized, and lag-free.
  • Robust validation, feedback and design.
  • Clean typing, documentation and syntax.

:eyes: Check it out below!

🎬 Showcases

Cool text

A simple text tween, made smooth with Tween+’s custom string interpolation.
It identifies the differences, and interpolates accordingly for a seamless animation.

Video

Low FPS

A basic part movement tween with the FPS option set to 10.
The game still runs smoothly (in this case 144 FPS).

Video

Accurate color

A simple part color tween, made smooth and natural with Tween+’s Oklab interpolation.

Video

:globe_with_meridians: Networking capabilities.

10,000 tweens stress test!

TweenPlus

TweenService

Here’s a table comparing the costs of both libraries:

TweenService Tween+
Network Traffic Expensive constant updates Single cheap events
CPU Usage Server-heavy Client-distributed
Framerate Capped at 60Hz replication Native (Uncapped)

For those who are interested in the specifics of the networking engineering, I wrote about it in detail here, in the documentation.

:bell: Don’t forget to stay up-to-date!

Make sure you always have the latest version of the library,
so you benefit from the newest features, improvements and fixes.

You can see all releases in detail at the GitHub repository.
Major updates will be announced in this topic as well.

:loudspeaker: Share your works and thoughts!

I’d love to see what you build with this library, so please share your creations!

And if you have any questions or stumble upon any issues, please don’t hesitate to open an issue on GitHub or let me know through other means!





Special thanks to:


Like what you see?
Check out my other projects!

∙ ​ Text+ | Custom fonts & advanced control
∙ ​ Signal+ | Super fast & elegant signals
∙ ​ Inxpect | Easy & efficient API maps

Tags

library module api animation tween tweening tweenservice bezier curves attributes support features advanced control properties custom easing functions fps framerate limit control accurate color interpolation oklab open source quality performance optimization efficient server networking

183 Likes

Is there supposed to be example attachments here? They aren’t showing up for me.


Cool module!

2 Likes

Yes, there are supposed to be videos there.
They work perfectly fine for me, so that’s weird.
Which browser are you using?

2 Likes

I’m sorry but… why?

Tween+

local tweenPlus = require(tweenPlusPath)

local tween = tweenPlus(
    workspace.Part
    {
        Position = Vector3.new(0, 10, 0),
        Color = Color3.fromRGB(255, 255, 0)
    },
    { -- Customization (optional).
        Time = 10,
        EasingStyle = "Sine",
        EasingDirection = "InOut"
    }
)

vs

Roblox Tweens

local TweenService = game:GetService("TweenService")

local tweenInfo = TweenInfo.new(
    5,
    Enum.EasingStyle.Sine,
    Enum.EasingDirection.Out
)

local tween = TweenService:Create(workspace.Part, tweenInfo, {
    Position = Vector3.new(0, 10, 0),
    Color = Color3.fromRGB(255, 255, 0)
})

tween:Play()

What’s supposed to make it better?

3 Likes

TweenService enforces an exact order in which you provide the TweenInfo.
Tween+ let’s you provide information in any order you like, while preserving autocompletion.


A case where TweenService would look ugly is if you didn't want to provide all TweenInfo:
TweenInfo.new(2, nil, nil, 3, nil, 1)

Whereas with Tween+, it would look like this:

{
	Time = 2,
	RepeatCount = 3,
	DelayTime = 1
}

Or if you prefer having it in one line:

{Time = 2, RepeatCount = 3, DelayTime = 1}

Additionally, Tween+ gets rid of ugly enums and uses strings instead, while preserving autocompletion.


Another neat feature of Tween+ is that you can replace the defaults with your own custom defaults, which can make it a lot simpler if you create a lot of similar tweens in your game.

Not to mention the many improvements and additional features beyond design and workflow.
Tween+ is objectively significantly better than TweenService — that’s the entire purpose of Tween+.

12 Likes

Did you forget to publicize the videos?

1 Like

Yes, I will have to reupload them publicly, so give me a second.

1 Like

I’m using Opera GX, i see videos now. Is there images aswell?

1 Like

Are the videos visible to you now?

1 Like

Most Developers would use a ModuleScript to get Tween Functions ready for their UI to keep it constant, also you’d rather not have the freedom of putting in strings I’d say, 1 typo and your tween won’t work. Imagine doing this in a global module, obviously it should be tested beforehand, but Enums are logical to use as a DataType to prevent mistakes.

Not sure if you have but I’d recommend the possibility of using the Enums themselves too if you can’t already.

Aside from that, for Developers to actually use your Module I would recommend doing it for things that are more valuable, look at for example ProfileService/ProfileStore, Maid and Admin Modules, those may be very useful. This on the other hand is just “learning” a new module to not follow Roblox’s Guidelines on how they’ve implemented it. Which in my eyes, is not a useful module. That’s like making your own custom Integer DataType instead of using the default. :sweat_smile:

What do you mean, aren’t videos enough?

There’s autocompletion, so it’s extremely hard to mess up.

1 Like

Sorry, when i last checked there was a blank space above the videos as if there was another attachment.

They’re visible, thanks for re-publicizing!

3 Likes

There are countless differences between Tween+ and TweenService that make Tween+ far superior objectively. I’d recommend reading the post.

5 Likes

I cannot see them either. I am on Safari.

It might be your browser not supporting AV1.

The previous issue was just that the videos were private, which is now fixed and most users are able to see them.

1 Like

Any performance changes? What about replication and server handling?

Creation is much faster, but unfortunately starting playback of tweens is slower because of all of the additional features it provides.

I haven’t benchmarked CPU usage when tweening, but I can assure you that it has been optimized.
Feel free to benchmark yourself, and don’t forget to share it if you do so!

Also, the UpdateEvent feature allows for significant performance improvements in certain scenarios. Of course TweenService does not have such a feature.

I thought about this, but this module’s purpose might not quite be that.
I want it to be usable for anybody and in any environment — it’s a replacement for TweenService.

2 Likes

Okay, actually I was making a similar system for animations from keyframeSequence, so I know a little bit about this topic.

Personally, I love it when people write me a lot of constructive criticism. so now I’m going to ruthlessly evaluate your code :slight_smile:

  • Well, reading your code, I still involuntarily think that there are advantages here too, so let’s write down why your code is not bad:

The documentation is right in the code before the functions, so we see hints, not bad.
Typing is definitely very good, but with the caveats that it was worth putting them in a separate module. They were made purely for “beauty” (hints), although it was possible to work hard and do it in --!strict mode. Yes, it’s difficult for not the most experienced, but still
Also, I note that the code is well organized. Although I just poke my finger into any part of the code and immediately see how to improve readability, and so on, it’s still a difficult job, so I forgive
using your own SignalPlus is good! Judging by the code, they are faster than BindableEvent.

  • What I’m not sure about
    UpdateEvent: Providing a choice between PostSimulation, prestimulation, and PreRender for UpdateEvent gives flexibility, but it can also lead to problems. I’m not sure if it’s worth giving this choice, or if it’s better to limit yourself to one, the most appropriate option.
    table.freeze also seems to be meaningless in your code. No one in an adequate state will change a table from another code. Well, I’m not at liberty to say whether it’s bad or not.
    The native directive looks meaningless in untyped code. If the code had been typed correctly, --!strict would have been enabled, which would have added 20-30% of the code speed, but here the typing was done so that there would be no eye gouging, so this is not only pointless, but even a small anti-pattern is possible.

minuses:
The main problem: Why? The most important question that arises when viewing this code is: why create your own TweenService system? TweenService is an optimized, reliable, and supported Roblox component that provides a wide range of animation features. If there are no very good reasons to create your own system, then it is better to use TweenService. I mean, unlike your code, it’s much more type-safe, probably more convenient, and so on. Just create a wrapper for it that adds functionality.
The propertyExists function uses pcall, which is quite expensive. It is better to use smg like “offline API” and check OflflineAPI[object][property] == nil (or API[object][property] if u can)
The code is quite complex to understand and debug.
I didn’t notice any logic processing when we try to run two twins of the same property for an object. it would be nice to have a weigh system
I also didn’t notice the logic processing when the instance was destroyed. It will most likely give an error, but I think many people would like to be warned so that their myservergamainbestsuperpuper does not turn off due to a destroyed DataStorePartAttributetagImACollectionService (just joking)
also, the structure is not very good in my opinion.
In the current implementation, each tween creates its own separate connection to the RunService.Prestimulation (or another selected UpdateEvent). This can lead to significant overhead costs, especially with a large number of simultaneously running twins.
Ideally, we strive to ensure that all active tweens are handled within a single connection to the RunService.PreSimulation. This will significantly reduce the load on the CPU and improve performance.

Consider using a centralized scheduler that will iterate through all active tines and update their values within a single RunService cycle.PreSimulation. This will require a more complex architecture, but will eventually lead to more efficient operation.
instanceTweens using Instance as a key is a problem. Use Weak Tables.
Or use a unique ID, although I find it pointless.

looked into easing WTHELL MAN THERE ARE SO MANY REPETITIVE LINES OF CODE! “Magic numbers” are bad

(Im used google translator, Im sorry if my text is “unreadable”)

AW:
and I would also say that instead of string … string, you should definitely do `{string1} {string2}(``), except for the moments with tables.
There’s a lot of duplicate code here
To configure it, consider the builder pattern, for example, in roblox it is a separate “TweenInfo” object

1 Like