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

Game-facing refs

On this page
On this pageZigKawaDemo Back to top

Game-facing identity handles. The only way game code (Zig / Kawa) references things.

TypeSchemeUse forNot for
AssetRefasset://… stem + AssetKindCooked assets: texture, model, material, model_doc, audio, collision, script, shader, font, sprite_atlas, prefab, particle, animation_graph, ui_document, localizationJSON tables, OS paths, cooked suffixes, skybox (use a .texture ref)
ContentRefcontent:// (dirs allowlist, AssetStore only) · writable:// / project:// (FS)Tables, configs, savesScenes, cooked assets
SceneRefrelative stem scenes/foo (runtime: cooked .shinscene only)Level load via AssetStoreContent tables, free-form content
PrefabRefrelative stem prefabs/foo (runtime: cooked .shinprefab only)Prefab retain / spawnScenes, loose content
ActorRefgeneration handle (EntityId alias)Live actors (find / send / bind)Strings as “entities”
VoiceHandlegeneration-checked slotLive audio voice from hi.audio().playCue / crossfadeCue paths (use AssetRef)

Note

AssetRef paths are extension-free. Disk names (.shinmodel, .shintexture, …) belong to packaging. AssetStore / Shinra maps AssetKind to the on-disk suffix; game code never writes cooked extensions.

URI forms (full rules: Assets and Shinra — Asset URIs and packs):

FormMeaning
asset://<pack>/<logical>Explicit pack; scene loads retain it through their derived asset dependency closure
asset://./<logical>Unscoped absolute logical path; product catalog maps path → pack; AssetStore acquires the owning pack automatically. Not FS-relative

There is no pack-search form. Seal enforces one path → one pack.

Path identity (engine internals): Shinra pipeline events may still emit cooked suffixes. Compare stems with asset_kind.stemsEqual / asset_deps.stemsEqual (not bare string/pathsEqual). Scenes use scene_ref.stemOf / withAuthoringJson / withCooked for store and editor disk loads.

Shaders are AssetKind.shader but identity is a package id (gbuffer_wacky, _engine/gbuffer), not a file stem. Platform expand lives in graphics/material/shader_artifact.zig (Metal one .metallib; D3D12 _vs_/_ps_/_cs_.cso). Materials still set shader.package; runtime acquires expanded store paths only for the synchronous native copy/compile and then releases them. Session launch binds AssetStore; device-init must follow launch.

Not refs (plain names): archetype, input action, message name, physics preset, audio bus.

Engine-internal native atoms (AudioHandle, RenderHandle, PhysicsHandle in src/hikari/src/native/handle.zig) back subsystem tables — games use AssetRef for cue paths and VoiceHandle for live voices.

API surfaceType
RenderUpdate.mesh / .material / .albedoAssetRef (kinds .model / .material / .texture)
setSkyboxTexture / attachSessionScript / defineActor(.{ .script = … })AssetRef (skybox = .texture; script = .script)
paths.read / json.parseRefContentRef (content:// first segment ∈ project content_dirs)
requestSceneLoad (replace / additive)SceneRef
retainPrefab / spawnPrefabPrefabRef
find / findBySceneId / findByName / raycast hit / spawn return / lifecycle actor.idActorRef
hi.audio().playCue / crossfade returnVoiceHandle
Procedural setMesh(vertices)no asset (CPU verts only)

Dead / invalid ActorRef → host no-ops (never crash). Bad AssetRef / ContentRef → validate fail / soft no-op.

Implementation: sdk/src/asset_ref.zig, content_ref.zig, scene_ref.zig, prefab_ref.zig, actor_ref.zig. Kind + suffix table: sdk/src/asset_kind.zig (engine assets/asset_kind.zig re-exports). Host: host_api.zig + game_api/host_bind.zig.

Zig

zig
const tex = hi.AssetRef.must(.texture, "asset://./textures/pbr_capsule_albedo");
const mat = hi.AssetRef.must(.material, "asset://./materials/default");
const cfg = hi.ContentRef.must("content://resources/ref_demo.json");

var parsed = try hi.json.parseRef(Config, allocator, cfg);
defer parsed.deinit();

const target = hi.world().find("target_zig");
if (!hi.world().isAlive(target)) return;

try hi.render().applyRender(target, .{
    .mesh = hi.AssetRef.must(.model, "asset://./models/cube"), // optional
    .material = mat,
    .albedo = tex,
    .notify_dirty = true,
    .release_primitive = true,
});

hi.world().send(target, ping);
hi.world().send(hi.ActorRef.invalid, ping); // no-op

const load = hi.world().requestSceneLoad(hi.SceneRef.must("scenes/refs_demo"), .{}) catch return;
_ = hi.world().releaseSceneLoad(load);
  • Literals: AssetRef.must(kind, uri) / ContentRef.must / SceneRef.must (comptime non-empty; scene/asset cooked suffixes are compile errors).
  • Dynamic strings: tryFrom then host validate.
  • EntityId is an alias of ActorRef.

Kawa

text
World.find(id) / Actors.find(id)        → ActorRef | nil
Actor.is_alive / Actors.is_alive / send → safe on dead
Actors.has / get_number / set_number    → component fields by name (dead → false/nil)
Content.read("content://…")            → string | nil   (content_dirs + AssetStore; no FS fallback)
Render.set_material(actor, mat [, alb])→ asset:// stems only (no .shin*)
Scene.set_skybox_texture("asset://…")  → asset:// stem (primary)
Scene.set_skybox_texture_secondary(…)  → asset:// stem (secondary)
Scene.set_skybox_blend(t)              → dual cubemap mix [0,1]
Scene.load("scenes/foo")               → SceneRef stem (not content://; not .json)

ActorRef is weak (holding a ref never keeps an actor alive). Prefer Actors.* / hi.actors for new find/send/field access; full guide: Actor communication.

Demo

scenes/refs_demo (Browse scenes → Tutorials → References; on disk refs_demo.json / .shinscene):

ActorRole
target_zig / target_kawaref_target — flash on ping
driver_zigContentRef read → AssetRef material+albedo → ActorRef message
driver_kawascripts/ref_demo — same

Data: resources/ref_demo.json, resources/ref_demo_note.txt.

PreviousActor communication (hi.actors)Next Save / replication wire version

Documentation follows the current engine checkout.

Snapshot 86f12d68Source docs/systems/refs.md
On this pageZigKawaDemo Back to top