Skip to content

Sprite Animation

The sprite animation system plays frame-based animations by cycling through a sequence of textures. The AnimationPlugin is included by the engine by default.

SpriteAnimator Component

Add SpriteAnimator to an entity with Transform and Sprite to animate it.

PropertyTypeDefaultDescription
clipstring''Animation clip name (registered or .esanim asset)
speednumber1.0Animation speed multiplier
playingbooleantrueIs animation playing
loopbooleantrueLoop when finished
enabledbooleantrueComponent active

Animation Clip Format

Animation clips are defined as .esanim files — a JSON format listing texture frames and playback settings:

{
"version": "1.0",
"type": "animation-clip",
"fps": 12,
"loop": true,
"frames": [
{ "texture": "assets/walk_01.png" },
{ "texture": "assets/walk_02.png" },
{ "texture": "assets/walk_03.png" },
{ "texture": "assets/walk_04.png" }
]
}
FieldTypeDefaultDescription
fpsnumber12Frames per second (used as default for all frames)
loopbooleantrueLoop playback
framesarrayList of frame objects
frames[].texturestringTexture path or UUID
frames[].durationnumberOptional per-frame duration in seconds. Overrides fps for this frame.

Per-Frame Duration

By default, every frame uses the same duration derived from fps. To make individual frames longer or shorter, add a duration field (in seconds):

{
"version": "1.0",
"type": "animation-clip",
"fps": 12,
"loop": true,
"frames": [
{ "texture": "assets/attack_01.png" },
{ "texture": "assets/attack_02.png", "duration": 0.5 },
{ "texture": "assets/attack_03.png" },
{ "texture": "assets/attack_04.png", "duration": 0.05 }
]
}

Frames without duration fall back to 1 / (fps * speed). The SpriteAnimator.speed multiplier still applies to per-frame durations.

Editor Workflow

  1. Create a clip — right-click in the asset browser → Create → Animation Clip (.esanim)
  2. Edit frames — open the clip in the visual editor to add/remove/reorder texture frames and set FPS
  3. Assign to entity — add a SpriteAnimator component and select the clip in the inspector
  4. Preview — the animation plays in the Scene View and Game View

Runtime API

Playing Animations

Set the clip property to switch animations:

import { defineSystem, addSystem, Query, Mut, SpriteAnimator } from 'esengine';
addSystem(defineSystem(
[Query(Mut(SpriteAnimator))],
(query) => {
for (const [entity, animator] of query) {
animator.clip = 'walk';
animator.speed = 1.5;
animator.playing = true;
}
}
));

Registering Clips in Code

For procedurally generated animations, register clips at runtime:

import { registerAnimClip, getAnimClip } from 'esengine';
registerAnimClip({
name: 'explosion',
fps: 24,
loop: false,
frames: [
{ texture: tex1Handle },
{ texture: tex2Handle },
{ texture: tex3Handle },
],
});

Stopping and Resetting

// Pause
animator.playing = false;
// Resume
animator.playing = true;
// Switch clip (resets to frame 0)
animator.clip = 'idle';