Skip to content
hikari
RenderingEditorAIToolchainDocumentation
Download

© 2026 Flying Rat Studio.
All rights reserved.

Explore the engineDocumentationContributorsDownloadLicenseBack to top
Documentation / Tutorials
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
Tutorials3 min read

Tutorial: first physics body and trigger

On this page
On this page1. Dynamic body (simple)2. Trigger volume3. Fire gameplay from a collisionVerifyNext Back to top

Opt into physics with hi.ComponentPhysics on the archetype, then author a physics block under scene "components". Scene-authored physics defaults to Static when body_type is omitted (or the whole block is missing on a physics-capable archetype) — set "body_type": "Dynamic" explicitly for props that should fall. Runtime spawn still defaults to Dynamic. Collisions reach Zig via onCollision and Kawa via on_collision.

Deep reference: Physics. Samples: trigger_entity.zig, cube_entity.zig, fall_sensor in scenes/physics_playground.json.

1. Dynamic body (simple)

zig
const hi = @import("hikari_game");

pub const BoxEntity = hi.defineActor(.{
    .archetype = "box",
    .components = .{ hi.ComponentRender, hi.ComponentPhysics },
});
json
{
  "id": "box_01",
  "archetype": "box",
  "transform": { "position": [0, 2, 0], "rotation_euler": [0, 0, 0], "scale": [1, 1, 1] },
  "components": {
    "render": {
      "mesh": "asset://./models/cube",
      "material": "asset://./materials/cube"
    },
    "physics": {
      "body_type": "Dynamic",
      "collider_shape": "Box",
      "collider_box_size": [1, 1, 1],
      "mass": 1.0
    }
  }
}

Render scale and collider size are independent when hand-authored. To size the collider from the mesh local AABB (box / sphere / capsule, local space — transform scale is applied at body create):

zig
_ = hi.world().fitColliderToRender(id);
// or read bounds yourself:
if (hi.render().localBounds(id)) |aabb| {
    const min_v, const max_v = aabb;
    _ = .{ min_v, max_v };
}

Common body_type values in samples: Dynamic, Static, Trigger.

Optional "is_active": false parks the body without removing the component (entity "active": false also disables effective physics). "enabled" is accepted as an alias, matching how light / visual_zone spell the same switch; is_active stays canonical and is what gets written back on save. Runtime: hi.world().setPhysicsActive(id, false). See Active / enable trio.

2. Trigger volume

zig
const std = @import("hikari_std");
const hi = @import("hikari_game");

const TriggerLogic = hi.defineComponent(.{
    .name = "trigger_logic",
    .storage = .embedded,
    .data = struct {
        pub const metadata = .{ .runtime_only = true };

        pub fn onCollision(_: *@This(), _: hi.ActorContext, info: *const hi.CollisionInfo) void {
            if (!info.other.isValid()) return;
            const other_name = hi.world().name(info.other);
            switch (info.phase) {
                .enter => std.log.info("enter {s}", .{other_name}),
                .exit => std.log.info("exit {s}", .{other_name}),
                .stay => {},
            }
        }
    },
});

pub const TriggerEntity = hi.defineActor(.{
    .archetype = "trigger",
    .components = .{ hi.ComponentPhysics, TriggerLogic },
});
json
{
  "id": "fall_sensor",
  "archetype": "trigger",
  "transform": { "position": [0, 1, 0], "rotation_euler": [0, 0, 0], "scale": [1, 1, 1] },
  "components": {
    "physics": {
      "body_type": "Trigger",
      "collider_shape": "Box",
      "collider_box_size": [24, 0.5, 24]
    }
  }
}

Triggers do not need a mesh. This sensor sits below the box in step 1. Play with both actors in the same scene and watch the enter/exit logs as the box falls through.

3. Fire gameplay from a collision

Sample message_pad_entity.zig sends messages on first .enter — combine with First messages.

Verify

  1. Play scenes/physics_playground — cubes fall; FallSensor logs when they pass through.
  2. Edit mode — no simulation (bodies frozen).
  3. Stop — document transforms restore; play-time physics poses do not write back.

Next

  • Character controller → First character controller
PreviousTutorial: first mesh and materialNext Tutorial: first character controller

Documentation follows the current engine checkout.

Snapshot 86f12d68Source docs/tutorials/first-physics.md
On this page1. Dynamic body (simple)2. Trigger volume3. Fire gameplay from a collisionVerifyNext Back to top