Skip to content
hikari
RenderingEditorAIToolchainDocumentation
GitHub
hikari

© 2026 Flying Rat Studio.
All rights reserved.

Explore the engineDocumentationContributorsLicenseBack to top
Documentation / Systems
Browse docs
Overview
Tutorials16
OverviewFirst game projectFirst entityAuthored user_data and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesPlay, Edit, and scenesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides16
OverviewDevelopment guideGameplay APIChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / UnrealActor and component lifecycle
Systems28
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 governorGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)UI and editorEditor asset hot reloadEditor Project Selector
Language reference2
OverviewAkari language referenceKawa language reference
Engine overview
Start exploring
  • No matching sections. Try fewer words or another topic.
NavigateEnter Openesc Close
Overview
Tutorials16
OverviewFirst game projectFirst entityAuthored user_data and the inspectorFirst mesh and materialFirst physics body and triggerFirst character controllerFirst session servicesFirst UIFirst input actionFirst messagesPlay, Edit, and scenesFirst runtime spawnFirst motionFirst skeletal animationAssets in Play (soft refs and hot reload)Dynamic editor recompile
Guides16
OverviewDevelopment guideGameplay APIChoosing component storageBuild and packagingProject filePluginsHikari Plugin APIData-driven content, JSON, and pathsScripting with KawaShader authoringTime of dayUser interfaceUI layoutUI widgetsMigration from Unity / UnrealActor and component lifecycle
Systems28
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 governorGPU particlesVisual ZonesVolumetric mediaInputAudioPhysicsMotion KitTemporal KitAssets and ShinraPrefabsAsset residencyAsset formats (Shinra pipeline)UI and editorEditor asset hot reloadEditor Project Selector
Language reference2
OverviewAkari 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 cc148c75Source 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