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
Systems4 min read

Motion Kit

On this page
On this pageGoalNon-goalsWhere it sitsCore modelCurves (easing.zig)DriversSpringPresets (Preset)TransitionsMotions busFLIPReduced motionIntegrationImmediate UIRetainedFrame timingPerformance contractPackage layoutForbidden patternsSee also Back to top

Hands-on walkthrough: Tutorials — First motion.

Shared motion system for runtime HUD, editor chrome, and general gameplay values. Implementation lives under src/hikari/sdk/src/motion/. Exports: hi.motion (full kit) plus root alias hi.Tween (and hi.easing for the easing module). Other types are hi.motion.Spring / Driver / Motions / Transition / Transaction / Preset / Easing.

Goal

Modern UI motion (tween, spring, enter/exit, stagger, interruptible retarget, reduced motion) under hot-path constraints: plain values, no per-frame heap, no dual APIs for game vs editor, one draw path unchanged.

Non-goals

  • Skeletal / clip animation (Shinra / model pipeline).
  • GPU particle systems or shader timeline graphs.
  • Auto-magic layout morphing without caller-stored previous geometry.
  • Per-widget heap timelines, string-keyed animators, or callback graphs on the hot path.
  • A second compositor / transform stack. Motion outputs numbers; UI paints them.

Where it sits

text
gameplay / GameSubsystem / entity data
editor host (spinners, panel open, toast)
        │
        ▼
   motion.*   (easing, tween, spring, driver, presets, Motions bus)
        │
        ├─► world.ui styles / colors / Length / progress   (immediate)
        └─► RetainedUi setStyle / setIconRotation / alpha   (retained)
                    │
                    ▼
              ui.Compositor → one UI draw
LayerOwnsMust not own
motion/Curves, drivers, springs, presets, Motions busWidgets, documents, GPU
Immediate ui/Rebuild + sample caller-owned drivers into stylesA second tween registry
Retained editor/ui/Dirty invalidation when driven values changeDuplicate easing math

Core model

Curves (easing.zig)

Easing + apply(t), plus lerp, clamp01, repeat, pingpong, wave, spin / spinMs.

Drivers

Plain structs — store next to animated state. Poll done(); no hot-path closures.

TypeRole
Tween / TweenVec2 / TweenVec3 / TweenColorDuration + curve; delay, plays, yoyo
Spring / SpringVec2Interruptible; setTarget keeps velocity
DriverUnion of tween / spring / hold
Hold (via Driver.hold)Constant
TransactionInterruptible from/to presentation (begin / retarget / update)

Driver.make(from, to, Spec) builds from a Spec (.tween, .spring, or .snap).

Spring

SwiftUI-style (response, damping_fraction) → internal stiffness/damping. Settles when position and velocity are within eps, then snaps.

Spring.update clamps a delayed frame to a bounded elapsed interval and integrates it in at most 1/60-second steps. This keeps the semi-implicit solver stable after debugger pauses, blocking native work, or idle-frame gaps instead of flinging UI surfaces past their authored travel.

Presets (Preset)

snappy / gentle / bouncy springs; fade_fast / fade_panel / slide_panel / pop tweens. Themes do not redefine physics.

Transitions

Transition recipes (fade_in, panel_in, pop_in, …) seed a TransitionState. Caller owns show/hide lifecycle; sample opacity/offset/scale each frame.

Stagger: tweenSpecStagger(base, index, slot) or staggerDelay.

Motions bus

Dense Motions table keyed by u64 + Channel (no string IDs). drive / retarget / tick / get / active. Respects setReduceMotion. Use Motions.keyWidget(index, gen) for retained WidgetIds.

Immediate UI usually skips the bus — store Spring/Tween on entity/subsystem state.

FLIP

motion.flip.invert(prev_origin, curr_origin) — caller stores previous rect.

Reduced motion

ui.AccessibilityPrefs.reduce_motion (editor Settings + prefs.json). motion.resolve(spec, reduce_motion) → .snap. Exposed on UiContext.reduce_motion / RetainedUi.reduce_motion after applyAccessibility. Editor spinners freeze when set.

Integration

Immediate UI

zig
self.panel_x.setTarget(open_x); // Spring
const x = self.panel_x.update(ctx.dt);
// Host code: world.ui.vStack(...); game modules:
const panel = ui.vStack(.{ .position = .{ x, 16 } });
defer ui.end(panel);

Do not put drivers inside UiContext.

Retained

Mutate properties (setIconRotation, setOpacity, setShift) + invalidate. Spinners use motion.spinMs(now_ms, period) unless reduce_motion.

Editor overlays use editor/ui/overlay_motion.zig (OverlayMotion): settings / confirm / asset picker run panel_in/panel_out; compile splash uses fade; status/recompile loaders pop opacity with Preset.fade_fast.

Frame timing

Drive from sim/UI dt. Wall-clock only via spin / spinMs. Motions.active() is a pacing hint for hosts.

Performance contract

  1. No heap on update / tick / lerpColor. Reserve Motions capacity up front.
  2. Settled drivers are free (tick early-outs; active_count).
  3. One curve table — controls never copy easing formulas.
  4. Compositor unchanged: one atlas, one stream, one UI draw.
  5. No string IDs in the bus.
  6. Color RGB lerps in linear light; alpha straight (lerpColor / withOpacity).

Package layout

text
src/hikari/sdk/src/motion/
  easing.zig  tween.zig  spring.zig  driver.zig
  color.zig   preset.zig transition.zig  reduce.zig
  bus.zig     flip.zig   transaction.zig  motion.zig

Forbidden patterns

  • Second copy of ease-out-cubic in a control file.
  • Growth inside update / tick.
  • Putting Motions inside UiContext frame state.
  • Driving motion from the render thread.
  • Default-on animation for every stock control — opt-in at the host.

See also

  • UI and editor
  • User interface
  • Application lifecycle
  • Scenes and gameplay
PreviousPhysicsNext Temporal Kit

Documentation follows the current engine checkout.

Snapshot 86f12d68Source docs/systems/motion-kit.md
On this pageGoalNon-goalsWhere it sitsCore modelCurves (easing.zig)DriversSpringPresets (Preset)TransitionsMotions busFLIPReduced motionIntegrationImmediate UIRetainedFrame timingPerformance contractPackage layoutForbidden patternsSee also Back to top