What Is Tweening?
The word "tween" comes from "in-between" a term borrowed from traditional animation, where junior animators were responsible for drawing the frames between the key poses drawn by senior animators. In game development and interactive media, tweening is the process of automatically generating intermediate values between a start state and an end state over a period of time.
A tween animates a property a position, a rotation, a scale, a color, or any numeric value from point A to point B. The simplest tween is a straight linear interpolation. More expressive tweens use easing functions to shape the motion curve, giving animations personality: a bouncy UI button, a smooth camera glide, a snappy card flip.
Unity provides several native tools for tweening, and the community library DOTween is the de-facto standard for more advanced needs. This chapter covers all of them.
Native Tweening with Lerp()
Linear Interpolation (Lerp) is the mathematical foundation of all tweening. Given a start value A, an end value B, and a parameter t between 0 and 1, Lerp returns the value that is fraction t of the way from A to B.
t = 0returns At = 0.5returns the midpoint between A and Bt = 1returns B
Basic Linear Movement
using UnityEngine;
public class LinearMover : MonoBehaviour
{
public Vector3 startPosition;
public Vector3 endPosition;
public float duration = 2f;
private float _elapsed = 0f;
void Start()
{
startPosition = transform.position;
}
void Update()
{
if (_elapsed < duration)
{
_elapsed += Time.deltaTime;
float t = Mathf.Clamp01(_elapsed / duration); // normalize to 0..1
transform.position = Vector3.Lerp(startPosition, endPosition, t);
}
}
}
The "Lazy" Lerp Pattern
There is a popular shortcut where instead of tracking elapsed time, you lerp from the current position toward the target each frame. This naturally produces an ease-out effect because the distance shrinks each frame and the step size shrinks with it.
public Transform target;
public float speed = 5f;
void Update()
{
// Each frame, move 'speed * Time.deltaTime' fraction of the remaining distance
transform.position = Vector3.Lerp(transform.position, target.position, speed * Time.deltaTime);
}
This pattern is extremely common because it is short and produces a pleasing deceleration for free. However, it has a subtle problem: the motion is frame-rate dependent. Use the lazy pattern for visual polish where exact timing does not matter (camera follow, smooth UI hover effects).
Easing Functions
A pure linear Lerp produces mechanical, robotic motion. Real-world objects accelerate and decelerate. Easing functions transform the linear parameter t into a curved value, shaping the speed profile of the animation.
The three fundamental families are:
- EaseIn: slow start, fast end like a car pulling away.
- EaseOut: fast start, slow end like a car braking to a stop.
- EaseInOut: slow start, slow end, fast middle the most natural-looking motion for most UI animations.
Using an Easings Helper Class
// Example Easings.cs (excerpt add the full class to your project)
public static class Easings
{
// Cubic ease in: accelerates from zero
public static float EaseInCubic(float t)
{
return t * t * t;
}
// Cubic ease out: decelerates to zero
public static float EaseOutCubic(float t)
{
float f = t - 1f;
return f * f * f + 1f;
}
// Cubic ease in-out
public static float EaseInOutCubic(float t)
{
if (t < 0.5f)
return 4f * t * t * t;
else
{
float f = (2f * t) - 2f;
return 0.5f * f * f * f + 1f;
}
}
// Elastic ease out: spring-like overshoot
public static float EaseOutElastic(float t)
{
float p = 0.3f;
return Mathf.Pow(2f, -10f * t) * Mathf.Sin((t - p / 4f) * (2f * Mathf.PI) / p) + 1f;
}
}
Applying an Easing to a Lerp
using UnityEngine;
public class EasedMover : MonoBehaviour
{
public Vector3 startPosition;
public Vector3 endPosition;
public float duration = 1.5f;
private float _elapsed = 0f;
void Start()
{
startPosition = transform.position;
}
void Update()
{
if (_elapsed < duration)
{
_elapsed += Time.deltaTime;
float tLinear = Mathf.Clamp01(_elapsed / duration);
// Apply easing to the linear t
float tEased = Easings.EaseInOutCubic(tLinear);
transform.position = Vector3.Lerp(startPosition, endPosition, tEased);
}
}
}
The pattern is always the same: compute a linear t, transform it through an easing function, then use the result as the Lerp parameter. You can swap the easing function without touching any other code.
Lerp and AnimationCurve
Unity's AnimationCurve class lets you define a custom curve using a visual curve editor in the Inspector. This is extremely powerful for designers and artists who want to fine-tune animation timing without writing code.
using UnityEngine;
public class AnimationCurveMover : MonoBehaviour
{
public Vector3 startPosition;
public Vector3 endPosition;
public float duration = 1f;
// Edit this curve visually in the Inspector
public AnimationCurve curve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
private float _elapsed = 0f;
void Start()
{
startPosition = transform.position;
}
void Update()
{
if (_elapsed < duration)
{
_elapsed += Time.deltaTime;
float normalizedTime = Mathf.Clamp01(_elapsed / duration); // 0..1
// Sample the curve at the normalized time
float curveValue = curve.Evaluate(normalizedTime);
transform.position = Vector3.Lerp(startPosition, endPosition, curveValue);
}
}
}
Installing DOTween
DOTween is the most popular tweening library for Unity, created by Daniele Giardini (Demigiant). It is available in two versions: DOTween (free) and DOTween Pro (paid, adds visual animation tool).
Installation Steps
- Download DOTween from the Unity Asset Store (search "DOTween") or from
dotween.demigiant.com. - Import the package into your Unity project.
- Unity will prompt you to run the DOTween Setup Wizard do this.
- Add
using DG.Tweening;at the top of any script that uses DOTween.
How to Use DOTween
DOTween extends Unity's built-in types with extension methods. You call a tween method directly on a Transform, Rigidbody, Material, or other component.
Basic Transform Tweens
using UnityEngine;
using DG.Tweening;
public class DOTweenExamples : MonoBehaviour
{
public Vector3 targetPosition = new Vector3(5f, 0f, 0f);
public Vector3 targetRotation = new Vector3(0f, 180f, 0f);
public Vector3 targetScale = new Vector3(2f, 2f, 2f);
void Start()
{
// Move to world position in 1 second
transform.DOMove(targetPosition, 1f);
// Rotate to Euler angles in 1 second
transform.DORotate(targetRotation, 1f);
// Scale to target scale in 0.5 seconds
transform.DOScale(targetScale, 0.5f);
}
}
Method Chaining
transform
.DOMove(new Vector3(5f, 0f, 0f), 1.5f)
.SetEase(Ease.OutBounce) // apply a bounce easing
.SetDelay(0.5f) // wait 0.5s before starting
.SetLoops(3, LoopType.Yoyo) // repeat 3 times, alternating direction
.OnStart(() => Debug.Log("Tween started"))
.OnComplete(() => Debug.Log("Tween finished"));
Sequences
A DOTween Sequence lets you chain multiple tweens in order, run some in parallel, and insert delays or callbacks all without nested coroutines.
void PlayIntroAnimation()
{
Sequence seq = DOTween.Sequence();
// Step 1: fade in (0.3 seconds)
seq.Append(canvasGroup.DOFade(1f, 0.3f));
// Step 2 (runs alongside step 1): slide in from left
seq.Join(transform.DOLocalMove(Vector3.zero, 0.3f).SetEase(Ease.OutBack));
// Step 3: wait a moment
seq.AppendInterval(0.5f);
// Step 4: scale up slightly and back
seq.Append(transform.DOScale(1.05f, 0.1f));
seq.Append(transform.DOScale(1f, 0.1f));
// Callback when all done
seq.OnComplete(() => Debug.Log("Intro done"));
seq.Play();
}
Killing Tweens
Always kill tweens on an object before starting a new one on the same property, especially if the tween can be triggered repeatedly.
// Kill all tweens on this transform, then start a new one
transform.DOKill();
transform.DOMove(newTarget, 0.5f).SetEase(Ease.OutQuad);
Choosing the Right Tool
- Simple one-off smooth movement with no timing requirements use the lazy Lerp pattern
- Precisely timed animation with standard easing use an easing helper class with tracked elapsed time
- Designer-configurable animation timing use
AnimationCurvein the Inspector - Complex sequences, callbacks, Material/Light/UI animations, elastic/bounce effects use DOTween
- Character or gameplay animations keyed to specific poses use Unity's Animator component with Animation Clips
Summary
Tweening is one of the highest-impact skills in game UI and interactive experience development.
- Use
Vector3.Lerp,Quaternion.Lerp, andMathf.Lerpfor simple interpolation - Apply easing functions to the
tparameter to shape the motion curve - Use
AnimationCurvewhen designers need visual control over timing - Install DOTween for sequences, callbacks, chaining, and animating any property with minimal code
- Kill tweens before starting new ones on the same property
Need help with Unity3D development?
I'm a senior developer with 16+ years experience, including AAA projects at Ubisoft. Let's discuss how I can help with your game or interactive project.
Start a Conversation