Skip to content

Animation

Keyframe animation of properties: moving platforms, swinging doors, blinking lights.

  • Inherits: Instance
  • Creatable: Yes: new Animation(), or Instance.new('Animation', parent).
  • Replication: Replicated: clients get a copy, and changes the server makes reach them.

An Animation plays keyframes on properties of its target, which is its parent unless you set target. Each track animates one property of one object: the target itself, or an object inside it named by path ('Lid', 'Arm/Hand'). Numbers, vectors and colors blend between keys along an easing curve; other values (booleans, materials, text) switch when the next key is reached. On a Model, the position property moves the model’s pivot, and every part with it.

An animation runs on the side that calls play(). On the server (or with autoplay), the property changes replicate, so every player sees the same motion. In a LocalScript, only that player sees it, at full frame rate: good for purely visual effects.

Problems with a track (a missing object, an unknown or read-only property, a value of the wrong type) are written to the game’s output as warnings, and that track is skipped. An animation can have up to 200 tracks and 2,000 keys in total.

Type: AnimationTrack[] · Default: [] · Access: read/write · Replicates: yes

The keyframe tracks, one per animated property: see AnimationTrack and AnimationKey. Assigning checks them, throwing a TypeError that says what’s wrong, and sorts each track’s keys by time. Assign a new list to change them: changing the list in place isn’t noticed.

Type: number · Default: 0 · Range: 0 to 3,600 (clamped) · Access: read/write · Replicates: yes

Seconds; 0 = the time of the last key.

Type: boolean · Default: false · Access: read/write · Replicates: yes

Start over at the end instead of stopping.

Type: number · Default: 1 · Range: 0 to 10 (clamped) · Access: read/write · Replicates: yes

Playback rate (2 = twice as fast).

Type: boolean · Default: false · Access: read/write · Replicates: yes

Plays on the server as soon as the game runs (no script needed).

Only for animations inside the Workspace.

Type: Instance | null · Default: null · Access: read/write · Replicates: yes

What the tracks animate (default: the animation’s parent).

Type: boolean · Default: false · Access: read-only · Replicates: yes

True while playing.

Type: number · Access: read/write

Seconds into the animation. Setting it jumps there (and poses the target).

Inherited from Instance: name, archivable, id, className, parent, destroyed

getLength(): number

Length in seconds: length, or the time of the last key when that is 0.

play(target?: Instance): void

Plays from the start. target overrides the target property (default: the parent). Runs on whichever side calls it: the server (everyone sees it) or a LocalScript (just that player). When the script that played it stops, the animation stops.

The animation must be in the game; otherwise it throws. Starting it again restarts it.

stop(): void

Stops where it is (fires stopped).

Inherited from Instance: getPropertyChangedSignal, setAttribute, getAttribute, getAttributes, getAttributeChangedSignal, getChildren, getDescendants, findFirstChild, findFirstChildOfClass, findFirstChildWhichIsA, findFirstAncestor, findFirstAncestorWhichIsA, waitForChild, isA, isDescendantOf, isAncestorOf, getFullName, clearAllChildren, destroy, clone, toString

Arguments: none

Fires when the animation stops: it reached the end (not looped) or stop() was called.

Arguments: none

Fires each time a looped animation starts over.

Inherited from Instance: changed, childAdded, childRemoved, descendantAdded, descendantRemoving, ancestryChanged, destroying, attributeChanged

import { Animation, Part, getChild, workspace } from '@rally/sdk';
const platform = getChild(workspace, 'Lift', Part);
const lift = new Animation();
lift.name = 'Rise';
lift.tracks = [
{
property: 'position',
relative: true, // offsets from where the platform is when play() starts
keys: [
{ t: 0, value: [0, 0, 0], easing: 'sineInOut' },
{ t: 3, value: [0, 20, 0] }, // hold at the top for 2 seconds
{ t: 5, value: [0, 20, 0], easing: 'sineInOut' },
{ t: 8, value: [0, 0, 0] },
],
},
];
lift.looped = true;
lift.parent = platform; // the target is the animation's parent
lift.play();
import { Animation, Part, getChild, workspace } from '@rally/sdk';
const lamp = getChild(workspace, 'Lamp', Part); // has a PointLight called Light inside
const blink = new Animation();
blink.tracks = [
{ path: 'Light', property: 'enabled', keys: [{ t: 0, value: true }, { t: 0.5, value: false }] },
];
blink.length = 1;
blink.looped = true;
blink.parent = lamp;
blink.play();