LitMotion - Lightning-fast and Zero Allocation Tween Library

I’m excited to release my new tween library, LitMotion.


LitMotion is my second tween library after MagicTween, and its DOTS-based design allows for zero allocation and extremely high performance. You can animate just about anything, and the IntelliSense-friendly API with method chaining allows you to implement complex animations while maintaining beautiful code.

LitMotion is completely open source and released on Github under the MIT license.
https://github.com/AnnulusGames/LitMotion

The full version of the documentation can be found here.
https://annulusgames.github.io/LitMotion/

Have fun!

11 Likes

The benchmark results are as follows. You can check the source code used in this repository.

LitMotion is up to 5x faster than DOTween/LeanTween, 3x faster than PrimeTween, and 1.5x faster than MagicTween. Of course there is no runtime memory allocation in any case. Completely zero allocation.

- Tween 64,000 float properties



- Tween 50,000 transform.position


- GC Allocation

4 Likes

WOW

LitMotion 1.0.1 has been released. Performance is further improved by removing unnecessary bounds checks.

2 Likes

We welcomes any contributions. If you find a bug or have a suggestion for improvement, please add an issue or pull request. Also, if you have any feature requests or questions, please feel free to contact us through this forum or Discussions on Github.

2 Likes

I wrote an article detailing the design and implementation of LitMotion. Please be sure to read this as well!

“LitMotion — High-performance tween implementation with data-oriented design in Unity.”

2 Likes

LitMotion 1.1.0 has been released. In addition to several fixes and optimizations, ManualMotionDispatcher and MotionScheduler.Manual are added for manual motion updates!

// Specify MotionScheduler.Manual as the scheduler
var handle = LMotion.Create(value, endValue, 2f)
    .WithScheduler(MotionScheduler.Manual)
    .BindToUnityLogger();

while (handle.IsActive())
{
    var deltaTime = 0.1f;
    // Update using ManualMotionDispatcher.Update()
    ManualMotionDispatcher.Update(deltaTime);
}
1 Like

LitMotion 1.2.0 has been released.

From 1.2.0 it is now possible to create string tweens. This uses FixedString internally. And by using BindToText to TMP_Text, it is amazingly possible to animate strings with completely zero allocation!

LMotion.String.Create128Bytes("", "<color=red>Zero</color> Allocation <i>Text</i> Tween! <b>Foooooo!!</b>", 5f)
    .WithRichText()
    .WithScrambleChars(ScrambleMode.Lowercase)
    .BindToText(text);

2 Likes

Looks like performance is very good, but I was used to using dotween before, Is better performance the main goal of litmotion compared to dotween?

Although improved performance is one of LitMotion’s key features, there are several other reasons why I recommend LitMotion over DOTween.

One is that it is designed with a modern approach. While DOTween has a complex and bizarre design due to years of updates, LitMotion has been restructured with a simple and clear architecture and API based on the lessons of all tween libraries.

Another is that it is OSS. DOTween has a paid Pro version, but all of LitMotion’s functions are open source. Also, I have no plans to charge for some features in the future.

2 Likes

LitMotion 1.2.1 has been released.
The WithCancelOnError method has been added to allow motion to be canceled when an exception occurs within Bind.

LMotion.Create(0f, 10f, 2f)
    .WithCancelOnError()
    .Bind(...);

Additionally, I fixed a bug where the await would not complete if you called Cancel while awaiting MotionHandle.

Release note:

2 Likes

wow:)

1 Like

LitMotion 1.3.0 has been released.
Punch and Shake have been added as new features. You can easily create vibration motions with one line of code!

LMotion.Punch.Create(0f, 5f, 2f).BindToPositionX(target1);
LMotion.Shake.Create(0f, 5f, 2f).BindToPositionX(target2);

Release note:

1 Like

If you want extension methods like DOTween, you can add your own with code like this.

public static class TransformExtensions
{
    public static MotionHandle TweenPosition(this Transform transform, Vector3 endValue, float duration)
    {
        return LMotion.Create(transform.position, endValue, duration).BindToPosition(transform);
    }
}

Although I recommend using LMotion class to maintain high readability, extension methods like this are useful if you want to reduce the amount of writing.

2 Likes

LitMotion 1.3.1 has been released.
This release fixes several bugs. Please see the release note below for details.

Release note:

LitMotion 1.3.2 has been released.
This release fixes an issue that caused compilation errors when used with Collections 1.5.1.

Release note:

3 Likes

LitMotion 1.4.0 has been released.
This release adds extension methods to support UIToolkit and VFX Graph (VisualEffect)!

var progressBar = root.Q<ProgressBar>();
LMotion.Create(progressBar.lowValue, progressBar.highValue, 2f)
    .BindToProgressBar(progressBar);

var image = root.Q<VisualElement>("Image");
LMotion.Create(Color.white, Color.red, 2f)
    .BindToStyleBackgroundColor(image);

var label = root.Q<Label>("Label");
LMotion.String.Create64Bytes("", "Hello, UI ToolKit!", 2f)
    .WithScrambleChars(ScrambleMode.All)
    .BindToText(label);

9561373--1351993--ezgif.com-optimize.gif

Release note:

3 Likes

LitMotion 1.5.0 has been released. This release includes several feature additions.

OnCancel
First, I added OnCancel callback. You can add a callback when canceling using WithOnCancel().

LMotion.Create(0, 10, 2)
    .WithOnCancel(() => ...)
    .BindToUnityLogger();

Bind with multiple states
Also, BindWithState() now supports multiple states (up to 3). You can avoid closures and reduce allocation by passing objects as arguments.

LMotion.Create(0f, 1f, 2f)
    .BindWithState(state1, state2, state3, (x, state1, state2, state3) => {
        ...
    });

Animating text numbers
Additionally, it is now possible to bind motions with numeric values to Text! This makes it easier to perform processes like DOTween’s DOCounter(), and when the target is TMP_Text, it is written directly to the char[ ] buffer, allowing animation with zero allocation!

TMP_Text text;
LMotion.Create(0, 100, 2f)
    .BindToText(text);

If you want to set formats such as comma separation and number of digits, you can do so by passing a format string.

TMP_Text text;
LMotion.Create(0f, 100000f, 2f)
    .BindToText(text, "{0:N2}");


Unfortunately, this feature uses string.Format() and therefore incurs GC allocation. To get around this, LitMotion added support for ZString. Introducing ZString into your project automatically replaces these processes and achieves complete zero allocation.

Release note:

5 Likes

LitMotion 1.6.0 has been released. This release contains some breaking changes, so be careful when migrating.

Migration to PlayerLoop
In previous versions, motion update processing was performed on MonoBehaviour, but from v1.6 it is now performed on PlayerLoop. Along with this, many MotionSchedulers have been added. MotionScheduler.LateUpdate has been removed and PreLateUpdate and PostLateUpdate can be used instead.

Also, WithIgnoreTimeScale() has been removed and Schedulers such as MotionScheduler.UpdateIgnoreTimeScale have been added as alternatives. As of v1.6, use WithScheduler() instead.

RegisterUnhandledExceptionHandler
Added MotionDispatcher.RegisterUnhandledExceptionHandler(). You can use this to configure handling of unhandled exceptions that occur within Bind() or WithOnComplete().

// Change to display a warning using LogWarning instead of LogException
MotionDispatcher.RegisterUnhandledExceptionHandler(ex => Debug.LogWarning(ex));

Remove null check
Removed null check in Bind extension methods. This improves performance significantly since checking UnityEngine.Object was a performance bottleneck.
However, this change now causes an exception to occur when an object is destroyed during playback. This can be avoided by using AddTo() to associate the cancellation process with the GameObject.

LMotion.Create(0f, 10f, 2f)
    .Bind(x => ...)
    .AddTo(this.gameObject);

Release Note:

2 Likes

Sorry, v1.6.0 contained some major bugs. The stable version is v1.6.3. Please use this.

2 Likes