Performance
Understand zero-allocation playback, pooling, profiling, and benchmarks
0 GC Alloc Playback
Evo Tween is built for 0 B GC Alloc during steady-state playback. The scheduler advances existing instances, built-in easing evaluates without temporary objects, and prepared sequences reuse their sampling data. Repeated code tweens can also reuse pooled instances once the relevant pools have warmed up.
This describes the tween runtime after setup. Creating the manager, initializing a new tween type, growing storage, rebuilding state data, or allocating inside your own callbacks can still generate garbage. A tween that changes a component may also cause work or allocations in that component.
What Gets Reused
| Area | How it works |
|---|---|
| Code tweens | Runtime instances return to pools and can be rented again for later runs. Pools retain their peak concurrency. |
| Builders and handles | TweenBuilder<T> and TweenHandle are value types. Chained configuration doesn't create a new managed builder object at each step. |
| Tween Animator states | Awake() prepares reusable sampling data for every state. Playback and triggers reuse it. |
| Triggered clips and sequences | Runtime clip and supported module copies are pooled. Sampling lists retain capacity for reuse. |
| Updates | One manager schedules tweens in Update, LateUpdate, or FixedUpdate. Each code tween doesn't need its own MonoBehaviour or coroutine. |
Pooling trades retained memory for fewer later allocations. The pool's capacity is storage it has reserved, not the number of tweens currently playing.
When Allocations Can Happen
- First use or a new concurrency peak. New instances, pool arrays, and scheduler collections may need storage.
- Changing animation definitions.
PrepareStates(), state refreshes, cloning clips, and creating curves are setup work. - Callbacks and setters. Capturing lambdas, string formatting, temporary collections, and logging can allocate in your code.
- Custom modules. Their capture, evaluation, copying, and cleanup code determine their allocation behavior. The default custom-module clone path may allocate.
- Editor tools and diagnostics. Drawing inspectors, recording, and collecting detailed debug information are separate from ordinary player playback.
Some bindings also have their own first-use resources, such as material property blocks. Warm up the bindings your scene actually uses instead of assuming that running one tween initializes every type.
Keep Repeated Animations Cheap
Prepare During Setup
Configure Tween Animator states before play. PrepareStates() runs in Awake; call it again only when you change definitions and need to rebuild them. For your own cached sampler, call Prepare() during initialization.
For code tweens, exercise representative bindings and concurrent counts during a suitable loading or setup phase, then allow those instances to finish and return to their pools. Warming a single instance won't cover a later burst of many simultaneous instances.
Keep Callbacks Simple
Use the built-in BindTo... methods when they fit. For a custom setter, use the target-and-setter overload with a static callback, as shown in Scripting. Cache reusable delegates and AnimationCurves.
Start tweens when an event occurs. Creating a replacement tween every frame does unnecessary setup work even if the pool can supply an instance.
Watch the Animated Component
Zero managed allocations doesn't mean zero CPU or rendering cost. Changing text, layout sizes, or UI geometry can trigger work in those systems. A Canvas Group fade and a text-layout animation can have very different costs even with the same tween duration.
Keep the animated property in mind when profiling. Use a few representative animations on the target device before scaling up the number of concurrent effects.
Benchmarks
These results compare Evo Tween with PrimeTween and LitMotion, two high-performance tween libraries for Unity. Each library animated the same objects with the same values and the OutQuad ease.
| Setting | Value |
|---|---|
| Hardware | AMD Ryzen 9 7950X3D, 64 GB RAM, Windows 11 25H2 |
| Build | Unity 6000.0.84f1, Windows x64 release player, Mono scripting backend |
| Versions | Evo Tween 2.0.0, PrimeTween 1.5.0, LitMotion 2.0.2 with Burst 1.8.30 |
| Test Date | 2026/10/16 |
| Workload | What runs |
|---|---|
| Position | One tween per GameObject on Transform.localPosition. |
| Rotation | One tween per GameObject on Transform.localRotation. |
| Float callback | Float tweens that send their value to a shared, cached callback. No Unity object is involved. |
| 3-step sequence | Position, then scale, then position again, on each GameObject. Evo Tween triggers three sequential clips. PrimeTween and LitMotion chain three tweens. Count is the number of sequences. |
Each library, workload, and count ran in its own player process. A warm-up round ran first, so every library had already grown its pools and storage. Values are the median of three runs. Individual runs were usually within 10% of that median.
Evo Tween is the baseline in each row. The other columns show time relative to it, so ×2.00 takes twice as long. ▲ is slower and ▼ is faster. Doubled arrows mean at least twice as slow or fast. ≈ means within 10%, about the run-to-run variation.
Start
Extra time in the frame that starts every tween, compared with an empty frame. It includes work a library delays until later in that frame. Lower is better.
| Workload | Count | Evo Tween | PrimeTween | LitMotion |
|---|---|---|---|---|
| Position | 1,000 | 0.41 ms baseline | 0.49 ms ▲ ×1.18 | 0.24 ms ▼ ×0.59 |
| Position | 10,000 | 4.05 ms baseline | 4.88 ms ▲ ×1.21 | 2.33 ms ▼ ×0.57 |
| Position | 50,000 | 22.5 ms baseline | 26.5 ms ▲ ×1.18 | 12.1 ms ▼ ×0.54 |
| Rotation | 1,000 | 0.64 ms baseline | 0.62 ms ≈ ×0.96 | 0.28 ms ▼▼ ×0.44 |
| Rotation | 10,000 | 6.67 ms baseline | 6.30 ms ≈ ×0.94 | 3.07 ms ▼▼ ×0.46 |
| Rotation | 50,000 | 35.1 ms baseline | 33.9 ms ≈ ×0.96 | 18.0 ms ▼ ×0.51 |
| Float callback | 1,000 | 0.21 ms baseline | 0.44 ms ▲▲ ×2.07 | 0.18 ms ▼ ×0.83 |
| Float callback | 10,000 | 2.15 ms baseline | 4.45 ms ▲▲ ×2.07 | 1.79 ms ▼ ×0.83 |
| Float callback | 50,000 | 11.4 ms baseline | 25.5 ms ▲▲ ×2.23 | 9.92 ms ▼ ×0.87 |
| 3-step sequence | 1,000 | 1.32 ms baseline | 2.99 ms ▲▲ ×2.27 | 1.88 ms ▲ ×1.43 |
| 3-step sequence | 10,000 | 14.4 ms baseline | 32.8 ms ▲▲ ×2.28 | 24.2 ms ▲ ×1.68 |
The first start in a session costs more, because code is compiled and pools grow. Starting 10,000 position tweens for the first time took 15.8 ms with Evo Tween, 12.4 ms with PrimeTween, and 16.4 ms with LitMotion. To avoid that cost during gameplay, warm up the bindings you use during loading, as described in Prepare During Setup.
Update
Extra main-thread time per frame while every tween plays, measured over 600 frames with a fixed 60 FPS game clock. Lower is better.
| Workload | Count | Evo Tween | PrimeTween | LitMotion |
|---|---|---|---|---|
| Position | 1,000 | 0.11 ms baseline | 0.12 ms ≈ ×1.06 | 0.067 ms ▼ ×0.59 |
| Position | 10,000 | 1.12 ms baseline | 1.20 ms ≈ ×1.07 | 0.31 ms ▼▼ ×0.28 |
| Position | 50,000 | 6.93 ms baseline | 6.31 ms ≈ ×0.91 | 2.28 ms ▼▼ ×0.33 |
| Rotation | 1,000 | 0.15 ms baseline | 0.15 ms ≈ ×0.98 | 0.070 ms ▼▼ ×0.47 |
| Rotation | 10,000 | 1.55 ms baseline | 1.49 ms ≈ ×0.96 | 0.37 ms ▼▼ ×0.24 |
| Rotation | 50,000 | 8.75 ms baseline | 7.70 ms ▼ ×0.88 | 2.37 ms ▼▼ ×0.27 |
| Float callback | 1,000 | 0.068 ms baseline | 0.10 ms ▲ ×1.53 | 0.055 ms ▼ ×0.82 |
| Float callback | 10,000 | 0.68 ms baseline | 1.05 ms ▲ ×1.54 | 0.16 ms ▼▼ ×0.23 |
| Float callback | 50,000 | 3.53 ms baseline | 5.89 ms ▲ ×1.67 | 0.52 ms ▼▼ ×0.15 |
| 3-step sequence | 1,000 | 0.21 ms baseline | 0.37 ms ▲ ×1.82 | 0.60 ms ▲▲ ×2.91 |
| 3-step sequence | 10,000 | 2.34 ms baseline | 4.74 ms ▲▲ ×2.03 | 5.83 ms ▲▲ ×2.49 |
Reading the results
LitMotion calculates values in Burst-compiled jobs on worker threads, then applies them on the main thread. Its update times include waiting for those jobs, but not the time other CPU cores spend on them. Evo Tween and PrimeTween do all their work on the main thread.
Memory
GC allocation after the warm-up round, across every workload and count above.
| Phase | Evo Tween | PrimeTween | LitMotion |
|---|---|---|---|
| Starting tweens | 0 B | 0 B | 0 B |
| Playing tweens, per frame | 0 B | 0 B | 0 B |
This was measured with Unity's GC Allocated In Frame counter in a Development build.
Bottom Line
Evo Tween isn't built to top every benchmark. It's built to make animation work painless, with editor tools like the Timeline Window and the Animator-like Tween Animator, and it works hand in hand with the rest of the Evo ecosystem, such as Evo UI. It isn't the fastest everywhere, but it leads with sequences and holds up well in the rest. I believe it offers the best editor workflow and experience of any tween solution for Unity.