Skip to content
hikari
RenderingEditorAIToolchainDocumentation
Download

© 2026 Flying Rat Studio.
All rights reserved.

Explore the engineDocumentationContributorsDownloadLicenseBack to top
Documentation / Systems
Browse docs
Overview
Tutorials17
OverviewPlay, Edit, and scenesFirst UI documentFirst game projectFirst entityComponent properties and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides25
OverviewWorking in the editorDevelopment guideGameplay APIActor and component lifecycleThreads, jobs, events, and routinesGameplay AI tasksGame AI: perception and movement playgroundBrain assetsBrain execution for swarm populationsLocalizationGame cursorsChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringChoosing and scaling shadowsTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / Unreal
Systems32
OverviewArchitectureApplication lifecycleFrontends and driversPlatforms and supportSession services and cross-scene stateScenes and gameplayActor communication (hi.actors)Game-facing refsSave / replication wire versionCoordinate space and camera conventionsRenderingRenderer architecture mapFrame governorPipeline compilationSkeletal animationGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitUI documentsAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)Document schemasUI and editorEditor asset hot reloadEditor Project Selector
Language reference3
OverviewAkari GPU ABIAkari language referenceKawa language reference
Engine overview
Start exploring
  • No matching sections. Try fewer words or another topic.
NavigateEnter Openesc Close
Overview
Tutorials17
OverviewPlay, Edit, and scenesFirst UI documentFirst game projectFirst entityComponent properties and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides25
OverviewWorking in the editorDevelopment guideGameplay APIActor and component lifecycleThreads, jobs, events, and routinesGameplay AI tasksGame AI: perception and movement playgroundBrain assetsBrain execution for swarm populationsLocalizationGame cursorsChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringChoosing and scaling shadowsTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / Unreal
Systems32
OverviewArchitectureApplication lifecycleFrontends and driversPlatforms and supportSession services and cross-scene stateScenes and gameplayActor communication (hi.actors)Game-facing refsSave / replication wire versionCoordinate space and camera conventionsRenderingRenderer architecture mapFrame governorPipeline compilationSkeletal animationGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitUI documentsAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)Document schemasUI and editorEditor asset hot reloadEditor Project Selector
Language reference3
OverviewAkari GPU ABIAkari language referenceKawa language reference
Engine overview
Systems8 min read

Skeletal animation

On this page
On this pagePipelineCooked dataAnimation componentAnimation graphsStates and parametersTransitionsSync groupsLayersClip eventsFoot IKRoot motionGame APIJoint socketsPerformanceCurrent limits Back to top

Reference for skinned characters: how skeletons and clips are cooked, how animation graphs evaluate, and what game code can drive and read back. For a step-by-step first character, start with Tutorial: first skeletal animation. For non-skeletal value animation (UI, springs, transitions), see Motion Kit.

Pipeline

text
glTF / USD / FBX ──Shinra──► .shinmodel (mesh + skeleton + clips)
.animgraph.json   ──Shinra──► .shinanimgraph (compiled graph)
                                   │
            Animation component ───┤ per frame, in parallel character jobs
                                   ▼
        graph evaluation → layers → foot IK → joint palette → vertex-shader skinning

One evaluation module serves the game runtime and the editor's preview, so what Asset Detail shows is what Play runs.

Cooked data

  • Axes. Engine and glTF are right-handed, Y-up, −Z forward; skin data is never axis-remapped. See Coordinate space.
  • One skin per model. A model with several skins fails the cook. Multi-part models (_p0, _p1, …) carry the same skeleton in every weighted part; clips live on _p0.
  • Joints. The palette is the skin's joints plus their ancestors up to a root, at most 256 joints (bone indices are 8-bit). Joint names are required and are the identity used for sockets, masks and IK.
  • Rest pose is the authored local transform (glTF default pose, UsdSkel restTransforms, FBX node transform). It may differ from the bind pose.
  • Weights. Up to 4 influences per vertex, normalised. Skinned vertices are 40 bytes, rigid vertices 32 bytes.
  • Bounds are cooked once: the rest bounds grown by the largest displacement any clip produces. They are not recomputed per frame, so culling and shadows never miss a limb.
  • Collision uses the bind pose or an authored capsule. Animated colliders are not supported.
  • Clips are uncompressed. A cooked clip flagged as compressed is rejected at load.

Animation component

The builtin animation component sits beside Render in the inspector.

FieldMeaning
GraphThe .animgraph.json asset that drives the character. Without one, Clip plays directly
Playing / LoopingPlayback state
SpeedGlobal rate; negative plays backwards
TimeSeek. Zero re-enters every layer's initial state
Root motionMove actor, Report only or Off (JSON "transform", "script", "off") — see Root motion
ImportantExempt from the evaluation budget (not from distance culling)

A skinned model without an animation component still draws in its rest pose.

Animation graphs

Graphs are authored in Asset Detail (.animgraph.json; read the document schema before writing one by hand). A new graph has no states and is valid; it simply holds the rest pose.

States and parameters

  • A state plays one clip, a 1D blend along one float parameter, or a 2D blend over two float parameters.
  • 2D blends use gradient-band interpolation over freeform points (up to 32). The strongest four weights are kept and renormalised. Coincident points are refused. A 2D blend needs two float parameters to exist.
  • Parameters are floats, bools and triggers. They are shared by every layer of the graph.

Transitions

  • A transition has a condition on parameters, an optional exit time, a duration and a priority. Several transitions may connect the same pair of states.
  • Exit time is a fraction of the source state's dominant clip, combined with the condition. Looping states re-arm it every lap; one-shot states keep it open once reached. always with exit time 1 means "return when done".
  • Interruption. A transition can be interrupted by another one while it blends. The outgoing mix is frozen and blended toward the new destination; each fading source keeps its own clock. Set interruptible: false to block selection until the blend lands.
  • Any State. Each layer has one Any State. Its transitions compete with the current state's own transitions by priority; on a tie the current state wins. An Any State transition into the current state only fires for a trigger condition.

Sync groups

States in the same sync group share a phase clock: every clip samples at phase × its own length, so a Walk ↔ Run blend keeps feet planted. Transitions within a group carry the phase across; leaving the group restarts from zero. The engine aligns phase, not content: clips must be authored with matching foot contacts.

Layers

A graph is one base layer plus up to four ordered overlays (an upper-body aim, a wave). Each overlay has its own state machine, a weight (static, optionally multiplied by a float parameter) and a joint mask (empty means the whole skeleton).

BlendResult
overrideLerps toward the layer's pose by its weight
additiveAdds the layer's difference from the rest pose, scaled by weight

Because the additive reference is the rest pose, DCC-style "rest plus offset" clips need no extra metadata. Overlays never take part in the base layer's sync groups, and only the base layer produces root motion. A graph without overlays costs nothing extra.

Clip events

Markers such as footsteps or hit frames belong to a clip, placed in clip seconds, so re-timing a state does not move them. Each marker has a name (up to 64 bytes) and one float value.

  • One clip speaks per state. In a blend, only the dominant clip fires its markers. A 50/50 Walk/Run blend does not put down two footsteps per stride.
  • During a transition both states fire, so the destination's first-frame markers are not delayed.
  • A marker fires once per crossing, including when a frame skips several loop laps. One-shot clips fire their end marker once.
  • Markers fire even when pose evaluation is skipped by LOD or budget. A distance-culled character's clock is frozen and fires nothing.
  • At most 8 markers per character per step; overflow is flagged.

Delivery happens on the game thread after animation finishes: Zig onAnimationEvent, polling hi.animation().events(id) / fired(id, name), or Kawa on_animation_event(name, value, time). Markers are edited on single-clip state cards in the graph editor.

Foot IK

Foot IK is an optional pass that runs after the pose (layers included) and before skinning. It is configured on the graph in the Foot IK panel: one leg chain (hip → knee → foot) per leg, ray lengths, sole offset and ankle tilt limits. Ranges are fractions of the rig's size.

  • One ray per leg is cast down from where the foot landed last frame, ignoring the character's own body.
  • The pelvis drops by the largest downward reach a planted foot needs (capped and smoothed); a foot that needs to come up bends its leg instead.
  • A leg fades out of IK when the ground is far below a swinging foot or out of the leg's reach.
  • Feet align to the ground normal within the ankle limits.
  • An incomplete leg chain is skipped (and reported in the editor), so preview keeps working while you edit.

Root motion

The graph decides what is extracted: the motion joint and which axes (translation X/Y/Z, yaw). The component decides who applies it:

TargetBehaviour
transform (Move actor)The engine moves the actor's local transform each frame
script (Report only)Extracted and published only; read hi.animation().rootMotion and move a character controller yourself
offNot extracted

Extracted motion is removed from the pose so the character does not move twice. Crossfades contribute each state's motion at its weight, loops add whole cycles, and root motion survives LOD pose skipping. A distance-culled character produces none. Use hi.animation().setRootMotionTarget to switch at runtime.

Game API

hi.animation() covers everything the inspector authors, plus readback.

AreaCalls
GraphsetGraph / clearGraph, setGraphFloat / setGraphBool / triggerGraph, graphFloat / graphBool
Playbackplay / playGraph, pause / resumePlayback / stop, setLooping, setSpeed / speed, setTime, isPlaying
ClipsclipCount / clipName / hasClip
State readbackstate / layerState, stateName / layerStateName, isInState
Eventsevents, fired, eventCount / eventAt
Root motionrootMotion, setRootMotionTarget / rootMotionTarget
JointsjointCount, jointName, findJoint, joint(actor, index, .model | .world), jointNamed
CostsetImportant, setGlobalCullDistance, setGlobalEvaluationBudget, setGlobalLodBands
  • State readback returns the state's name hash, unbounded time, progress (looping states fold to [0, 1)), clip length, blend weight and the previous state. Cooked graphs carry state names, so games never hash names themselves.
  • Joint readback is null until the rig has posed once.
  • A graph that has not finished cooking is remembered and bound when it arrives.

Kawa mirrors the same surface as Animation.*; see Scripting with Kawa.

Joint sockets

An actor can hang from a joint of its parent's rig (a sword in hand_r): scene parent_joint, inspector Attach to joint, hi.world().attachToJoint / setParentJoint, Kawa Actor.attach_to_joint. The joint name is the identity, so a model swap that keeps joint names keeps the socket. Before the rig binds, the child hangs from the parent's origin; reparenting drops the socket. See Scenes and gameplay.

Joint-palette allocation failure logs once per heap and uses the reserved two-matrix identity span only when that storage is resident. If even identity storage cannot be allocated, allocation is empty and GPU skinning is omitted; callers must not bind an empty span. Editor previews can retain joint overlays without a full GPU palette. Failed preview pose-buffer allocations release partial ownership and warn before leaving geometry static.

Performance

  • Characters evaluate in parallel jobs; the frame waits for them before uploading joint palettes.
  • Distance LOD comes from the project's animation bands (setGlobalLodBands) and per-actor distance. Distant characters update less often, and beyond the cull distance their clock freezes.
  • Evaluation budget. setGlobalEvaluationBudget caps per-frame evaluation; skipped characters still advance their clock, events and root motion. Important characters are exempt.
  • No heap allocation per frame after a graph binds.
  • Raster skinning runs in the vertex shader (4 influences, linear blend). With ray tracing on, a compute pass also writes skinned vertices for the acceleration structure.

Current limits

  • Transparent and forward-lit skinned materials render unskinned. Skinned meshes are supported in the opaque G-buffer and shadow passes.
  • Swarms render rigid instances only; skinned crowds use one actor per character.
  • No clip compression, retargeting, nested state machines or polar 2D blends.
  • Markers carry one float value and are authored through a graph's clip state.
  • Collision does not follow the animated pose.
PreviousPipeline compilationNext GPU particles

Documentation follows the current engine checkout.

Snapshot 86f12d68Source docs/systems/animation.md
On this pagePipelineCooked dataAnimation componentAnimation graphsStates and parametersTransitionsSync groupsLayersClip eventsFoot IKRoot motionGame APIJoint socketsPerformanceCurrent limits Back to top