t1k:unity:animation:litmotion
| Field | Value |
|---|---|
| Module | animation |
| Version | 2.2.2 |
| Effort | high |
| Tools | — |
Keywords: animation, litmotion, tween, zero-allocation
How to invoke
Section titled “How to invoke”/t1k:unity:animation:litmotionLitMotion — Lightning-Fast Tween Library
Section titled “LitMotion — Lightning-Fast Tween Library”Skill Purpose
Section titled “Skill Purpose”Reference for LitMotion — a zero-allocation, high-performance tween library for Unity. 2-20x faster than DOTween/PrimeTween. Uses DOTS internally (Burst + Jobs) but exposes a MonoBehaviour-friendly API.
Related skills:
dots-ecs-core(if using ECS) ·dots-rpg(if animating RPG entities)
When This Skill Triggers
Section titled “When This Skill Triggers”- Using
LMotion.Create,LMotion.Punch.Create,LMotion.Shake.Create - Using
MotionHandle,.Bind(),.BindToPosition(),.BindToLocalScale() - Configuring
.WithEase(),.WithDelay(),.WithLoops(),.WithOnComplete() - Creating
LSequencefor sequential/parallel motion chains - Animating TextMeshPro characters with
.BindToTMPCharColor() - Writing custom
IMotionAdapterimplementations - Any tween or animation logic in Unity C# code
- Migrating from DOTween Pro — replacing
DOMove,DOScale,DOFade,DOSequence
Quick Reference
Section titled “Quick Reference”| Task | Reference |
|---|---|
| Core API (Create, Bind, Handle) | core-api-guide.md |
| Configuration (Ease, Loops, Delay, Callbacks) | configuration-guide.md |
| Advanced (Sequence, Punch/Shake, TMP, Custom) | advanced-guide.md |
| DOTween Pro → LitMotion Migration | dotween-migration-guide.md |
| Project Utilities (Path, EaseMapper, Callbacks) | project-utilities.md |
Installation
Section titled “Installation”UPM Git URL (add to Packages/manifest.json):
"com.annulusgames.lit-motion": "https://github.com/annulusgames/LitMotion.git?path=src/LitMotion/Assets/LitMotion"Optional packages:
"com.annulusgames.lit-motion.animation": "https://github.com/annulusgames/LitMotion.git?path=src/LitMotion.Animation/Assets/LitMotion.Animation","com.annulusgames.lit-motion.unitask": "https://github.com/annulusgames/LitMotion.git?path=src/LitMotion.UniTask/Assets/LitMotion.UniTask"Requirements: Unity 2021.3+, Burst 1.6.0+, Collections 1.5.1+, Mathematics 1.0.0+
Core Pattern
Section titled “Core Pattern”// Animate a float from 0 to 10 over 2 secondsLMotion.Create(0f, 10f, 2f) .WithEase(Ease.OutQuad) .Bind(x => value = x) .AddTo(gameObject); // auto-cancel on destroy
// Animate from current value (single-arg overload)LMotion.Create(2f) .WithEase(Ease.OutQuad) .BindToPositionX(transform);
// Get a handle for manual controlvar handle = LMotion.Create(0f, 1f, 0.5f) .BindToPositionX(transform);
handle.Cancel(); // cancelhandle.Complete(); // jump to endhandle.IsActive(); // check if runningCommon BindTo Shortcuts
Section titled “Common BindTo Shortcuts”Transform
Section titled “Transform”| Method | Target |
|---|---|
.BindToPosition(transform) | Transform.position (Vector3) |
.BindToPositionX/Y/Z(transform) | Single axis (float) |
.BindToLocalPosition(transform) | Transform.localPosition (Vector3) |
.BindToLocalPositionX/Y/Z(transform) | Single local axis (float) |
.BindToLocalScale(transform) | Transform.localScale (Vector3) |
.BindToLocalScaleX(transform) | float → localScale.x |
.BindToRotation(transform) | Transform.rotation (Quaternion) |
.BindToEulerAngles(transform) | Euler angles (Vector3) |
.BindToLocalEulerAnglesZ(transform) | float → localEulerAngles.z |
UI / Renderer
Section titled “UI / Renderer”| Method | Target |
|---|---|
.BindToColor(renderer/graphic) | Material / Graphic color (Color) |
.BindToColorA(component) | float → color.a (any Graphic) |
.BindToColorR/G/B(component) | float → color channel |
.BindToAlpha(canvasGroup) | CanvasGroup.alpha (float) |
.BindToCanvasGroupAlpha(canvasGroup) | CanvasGroup.alpha (alias) |
.BindToFillAmount(image) | Image.fillAmount (float) |
.BindToSliderValue(slider) | Slider.value (float) |
.BindToSizeDelta(rectTransform) | RectTransform.sizeDelta (Vector2) |
.BindToAnchoredPosition(rectTransform) | RectTransform.anchoredPosition (Vector2) |
.BindToAnchoredPositionX/Y(rectTransform) | Single axis (float) |
.BindToText(tmpText) | TMP_Text.text (zero-alloc string) |
.BindToTMPTextColorAlpha(tmpText) | TMP_Text color alpha (float) |
Key Conventions
Section titled “Key Conventions”- Namespace rule:
DG.Tweening→LitMotion— when migrating from DOTween Pro, removeusing DG.Tweening;and addusing LitMotion;+using LitMotion.Extensions;. Do NOT use both namespaces in the same file (ambiguousEasetype). See dotween-migration-guide.md for full migration checklist. - Prefer manual
.Cancel()for frequently toggled objects —.AddTo(gameObject)auto-cancels on destroy, not on disable. For GameObjects that disable/enable often, store theMotionHandleand cancel inOnDisable(). MotionHandleis a struct — store it to cancel/complete; check.IsActive()before operating- Zero allocation —
LMotion.Createallocates nothing on the managed heap - Ease functions —
Ease.Linear,Ease.InOutQuad,Ease.OutBack,Ease.OutElastic, etc. (30+ options) - Loop types —
LoopType.Restart,LoopType.Yoyo,LoopType.Flip,LoopType.Increment;-1= infinite - Sequences —
LSequence.Create()chains motions;.Append()= serial,.Join()= parallel. For callbacks in sequences, see project-utilities.md.
Gotchas
Section titled “Gotchas”-
Cancel()/Complete()THROW on an inactive handle (InvalidOperationException: Motion has been destroyed or no longer exists) — unlike DOTween’s.Kill(), which silently no-ops on a dead/finished tween. The default (never-started)MotionHandlestruct and any handle whose motion has already finished are not active. A direct DOTween→LitMotion port oftween.Kill()→handle.Cancel()will crash the first time it runs before the motion starts, or on any cleanup path (Hide()/Dispose()/OnDestroy()) after the motion completed. Always guard:// ❌ WRONG — throws if sequenceHandle is default or already finishedthis.sequenceHandle.Cancel();// ✅ CORRECT — guard every Cancel()/Complete() with IsActive()if (this.sequenceHandle.IsActive()) this.sequenceHandle.Cancel();// ✅ For collections / nullable handlesforeach (var h in this.handles) if (h.IsActive()) h.Cancel();if (this.maybeTween.HasValue && this.maybeTween.Value.IsActive()) this.maybeTween.Value.Cancel();Migration field report (TheOneFeature, 2026-06-09): unguarded
Cancel()ports crashed inTextCounting,ChestRewardsView,TweenTabElementAnim,StreakSuddenDeadPlayerView,StreakGroupView,DonateMilestoneView,BarPulseHandler, et al. — surfacing as unobserved UniTask exceptions from popup Dispose paths. -
Leaked handles:
MotionHandlenot disposed or.AddTo(gameObject)missing → motion runs after object destroyed, causing NullReferenceException. Always.AddTo()or manually.Cancel()in OnDestroy/OnDisable -
AddTo destroys, not disables:
.AddTo(gameObject)cancels on GameObject.Destroy, not onSetActive(false). Components that disable/enable frequently need manual cancellation inOnDisable() -
BindTo on destroyed target: Binding to a Transform/CanvasGroup that gets destroyed mid-tween silently fails or throws. Cancel the handle before destroying the target
-
Not Burst-compatible: LitMotion’s managed API (delegates, closures) cannot run inside Burst-compiled ISystem code. Use LitMotion from MonoBehaviours only
-
Sequence ordering:
.Join()runs parallel with the previous.Append(), not with all prior items. Misunderstanding this causes timing bugs in complex sequences -
BindToLocalScale(and otherVector3binders) silently fail to compile when caller passes afloat(CS0315).BindToLocalScale,BindToLocalPosition,BindToPosition, and similarVector3shortcuts are typed-generic — they only accept anLMotion<Vector3, ...>. A common mistake is creating anLMotion<float, ...>(e.g.LMotion.Create(1f, 1.1f, 0.2f)) and trying to bind it to scale, intending the float as a uniform scale factor.// ❌ WRONG — passes float scale factor to a Vector3 binderLMotion.Create(1f, 1.1f, 0.2f).BindToLocalScale(t => transform.localScale = t * Vector3.one); // CS0315// ✅ CORRECT — Vector3 throughoutLMotion.Create(Vector3.one, Vector3.one * 1.1f, 0.2f).BindToLocalScale(transform);// ✅ ALSO CORRECT — explicit bind callback when you need custom logicLMotion.Create(1f, 1.1f, 0.2f).Bind(t => transform.localScale = Vector3.one * t); // no shortcut, custom assignmentRule of thumb: If you want a
Vector3result, START withVector3values inLMotion.Createand use the shortcut binder. If you want a scalar (float) result that you’ll map to aVector3yourself, use the generic.Bind(t => ...)callback and assign manually.Field reports: see references/incidents.md.
-
Unity 6 first-open DOTween regeneration drops TMP extensions (CS1929): when a project that still ships DOTween Pro is first opened in Unity 6, DOTween’s setup regenerates
Assets/Plugins/Demigiant/**— module markers switch from#if true // MODULE_MARKERto scripting-define-gated form (#if DOTWEEN_TEXTMESHPRO,#if DOTWEEN_DEAUDIO, …), line endings flip LF→CRLF (whole files show modified in git), and DLLs are re-exported. If TMP support was previously enabled via#if true, all TMP tween extensions (e.g.TMP_Text.DOCounter) silently vanish →CS1929compile errors. Fix: addDOTWEEN_TEXTMESHPROto Scripting Define Symbols for every relevant platform (or run Tools > Demigiant > DOTween Utility Panel > Setup DOTween, which applies defines perDOTweenSettings.assetmodule flags — confirmtextMeshProEnabled: 1), then commit the regenerated files + define once so fresh checkouts stay clean. Full repro + the related Odin Inspector module-activation gotcha: references/dotween-migration-guide.md § “Unity 6 first-open regeneration gotchas”.