Animation
There are two kinds of animation. Skeletal animation bends a character’s skinned mesh with the clips that came with its model. Property animation changes an entity’s values over time, such as its position, a light’s colour or a material’s glow, along keys you set in the editor.
Both run only while the game plays or a scene page simulates.
Importing animated models
Section titled “Importing animated models”Import a .glb, .gltf, .fbx or .obj model with Animations on (the default): its
skeleton becomes a Skeleton asset, and each of its animations an Animation Clip. The
model’s prefab gets a Skeletal Animation component that plays a clip called idle (or the
first whose name has “idle” in it, or else the first clip), so a character placed in a scene
plays its idle when the game plays.
Double-click a clip to open its page: it plays the clip on the skeleton, and has the clip’s Looping setting, its root motion (below), and its Events, named moments in the clip.
Playing one clip
Section titled “Playing one clip”Skeletal Animation plays one clip on a skeleton:
- Skeleton and Clip.
- Speed (1), and Start Time, so a herd of the same animal does not move in step.
- Auto Play: start when the game starts. With it on, setting another clip plays it at once.
- Mesh Entities: the skinned meshes it moves. A character made of several meshes (a body, a head, armour) lists them all here; with the list empty, it moves its own entity’s mesh.
Scripts drive it through SceneAnimation:
local Wave = Guid.new("9a1d6c3e-7f2b-4e8a-b5c4-1d2e3f4a5b6c") -- a clip's ID
function Npc:greet() local animation = SceneAnimation.of(self.entity.scene) animation:setClip(self.entity, Wave) animation:play(self.entity)endGuid kWave = Guid("9a1d6c3e-7f2b-4e8a-b5c4-1d2e3f4a5b6c"); // a clip's ID
void greet(){ SceneAnimation@ animation = SceneAnimation::of(self.scene); animation.setClip(self, kWave); animation.play(self);}stop, pause, resume, isPlaying, time and setTime are there too. Calls made before the
first frame has run, in onStart, do nothing; make them from onUpdate.
Animation graphs
Section titled “Animation graphs”A character that walks, runs, jumps and falls needs to move between its clips smoothly, and blend them by speed. That is an Animation Graph (Create > Animation > Animation Graph), played by an Animation Graph component in place of Skeletal Animation. Give the component the Skeleton, the Graph and its Mesh Entities.
A graph is made of:
- Parameters: values the game sets, of type
Float,Int,BoolorTrigger. A trigger is a one-off: it is set, used by a transition, and clears itself. A new graph has a Speed parameter. - States: what the character is doing, each playing a clip, or a blend tree that mixes clips by parameters. A 1D blend tree mixes along one parameter (idle at speed 0, walk at 2, run at 6); a 2D tree by two, for moving in any direction.
- Transitions: arrows from one state to another, taken when all of their conditions hold
(
Speed > 0.1), cross-fading over their Duration. With Has Exit Time, a transition waits until the state has played that far. Transitions from Any State can be taken from wherever the character is: a fall, a hit. - Layers: graphs over graphs. A layer above the base one can Override it or add to it (Additive), at a Weight, for an upper body that waves while the legs walk.
The graph page
Section titled “The graph page”Double-click the graph to open it. Layers and parameters are listed on the left, the selected layer’s states and transitions are in the middle, and the selected item’s settings are on the right.
- Right-click the canvas: Add Clip State, Add Blend Tree 1D, Add Blend Tree 2D.
- Right-click a state: Make Transition (then click the state it goes to), Set as Default State, Delete State.
- Select a transition to give it conditions: a parameter, a comparison and a value.
To preview, pick a Skeleton and a Mesh in the page’s toolbar and press play. While it plays, set the parameters by hand, and Fire Trigger to try a trigger.
Setting parameters from a script
Section titled “Setting parameters from a script”function Player:onUpdate(dt) local animation = SceneAnimation.of(self.entity.scene) local character = CharacterComponent.of(self.entity) local v = character.velocity animation:setFloat(self.entity, "Speed", math.sqrt(v.x * v.x + v.z * v.z)) animation:setBool(self.entity, "Grounded", character:grounded()) if Input.wasPressed("Jump") then animation:setTrigger(self.entity, "Jump") endendvoid onUpdate(double dt){ SceneAnimation@ animation = SceneAnimation::of(self.scene); CharacterComponent@ character = CharacterComponent::of(self); Float3@ v = character.velocity; animation.setFloat(self, "Speed", Math::Sqrt(v.x * v.x + v.z * v.z)); animation.setBool(self, "Grounded", character.grounded()); if (Input::wasPressed("Jump")) { animation.setTrigger(self, "Jump"); }}setInt sets an Int parameter, such as which weapon is drawn. A name the graph does not have
changes nothing.
Root motion
Section titled “Root motion”Some clips move the character themselves: a lunge, a vault, a walk whose feet must not slide. With root motion, the clip’s travel moves the entity, and the clip plays in place.
- On the clip’s page, under Root Motion, turn on what to take from the clip: Horizontal travel, Vertical travel, and Yaw, its turning. Show travel previews the path. Importing a model with Root motion on does this for its clips.
- On the animator, set Root Motion:
Character: moves the character controller above it, so it still collides. The usual choice.Entity: moves the entity in Root Motion Target, or its own.Script: moves nothing; a script readsrootMotionTranslationandrootMotionYawand decides.Ignore(the default): the travel is dropped.
Only a graph’s base layer gives root motion.
IK (inverse kinematics) bends a limb to reach a point, after the animation has posed it. Add an IK component to the animated entity, or to one above or below it:
- Two Bone IK: an arm or a leg, from its Start Bone, Mid Bone and End Bone, to a Target entity: a hand on a door handle.
- Aim IK: turns a chain of bones, such as the spine and head, to look at a Target, up to Max Angle (60 degrees).
- Foot IK: plants up to four feet on uneven ground, and lowers the hips to keep them there.
Each has a Weight, from 0 to 1, and fades in and out over Fade Seconds when turned on and
off. Without a target entity, a two-bone IK reaches for the point a script gives with
setIkTarget(entity, position); ikReached says whether it got there.
Crowds
Section titled “Crowds”Instanced Skinning animates the instances of an instanced mesh of a skinned model, a crowd of hundreds, at the cost of a few characters. Put it on the entity with the Instanced Mesh (or list the instanced meshes in Targets, one per part of a character) and set its Skeleton and its Clips, the animations the crowd plays.
Each clip is posed at Pose Count points through it (32 at first), and every instance takes one of those poses: more is a smoother spread, and costs more. Each instance plays one of the clips: an Instance Member chooses with its Clip, the clip’s place in the list (0 for the first), so a guest can walk, then stop to talk.
How instances on the same clip pick their poses is the Instanced Mesh’s Pose Assignment:
- Hashed (the default) scatters them, so a crowd does not move as one.
- Unison keeps them in step: dancers on a beat, a column marching.
- Sequential goes through the poses in order, a wave along the list.
- Explicit takes each instance’s pose from a list you set.
Property animation
Section titled “Property animation”A Property Animation Clip animates the values of one entity: its position, rotation and scale, and any number, colour or vector of its components. A door that swings, a light that flickers, a platform that moves along a route and back.
Making a clip
Section titled “Making a clip”- Select the entity, and open the animation panel with Animation on the scene page’s toolbar (or Scene > Animation Panel). It sits under the viewport.
- Create Clip… makes a clip for the entity.
- + Tracks adds tracks for what you have selected; + Track adds one property.
- Move the timeline to a time, change the values, and Key the track (or Key All).
- Select a key to set its exact Time, values and interpolation:
Step,LinearorCubic. - Save.
Play previews it in the scene.
Playing a clip
Section titled “Playing a clip”Give the entity a Property Animator with the Clip. Autoplay starts it with the game,
Speed can be negative to play it backwards, and Loop Mode is Once, Loop or
PingPong (to the end and back).
function Door:open() PropertyAnimatorComponent.of(self.entity):play()endvoid open(){ PropertyAnimatorComponent::of(self).play();}play() starts from the beginning; pause, resume, stop, time and setTime are there
too.
A clip animates numbers, colours, vectors and rotations, not switches or choices. Don’t animate the position of an entity with a dynamic rigid body: physics moves it. Make the body kinematic.