Gameplay code should read named actions, not raw key codes. Bindings live in JSON; Zig and Kawa both resolve the same ids.
Deep reference: Input.
1. Add an action
Edit configs/input_actions.json in your project (runtime path config://input_actions.json — not in startup config). Add an entry to the "actions" array:
{
"kind": "com.hikari.config.input_actions",
"version": 2,
"actions": [
{
"id": "interact",
"bindings": {
"keys": ["r"],
"gamepad_buttons": ["x"]
}
}
]
}Bindings use readable control names, and arrays allow more than one control from the
same device. Omit fields that do not apply; the defaults are scale 1, deadzone
0.15, and player 0. See the input reference
for every accepted name and scalar-axis examples.
Rebuild / relaunch so the action map reloads.
2. Read from Zig
In an entity update:
const std = @import("hikari_std");
const hi = @import("hikari_game");
pub fn update(_: *@This(), _: hi.ActorRef, _: *const hi.TickContext) void {
if (hi.world().actionPressed("interact")) {
std.log.info("interact", .{});
}
}Held state is hi.world().actionHeld("move_forward"). actionReleased reports the
release edge, while actionValue returns a named scalar from digital pairs, gamepad
axes, mouse delta, or wheel input. Compose two named scalars with actionVector2:
const move = hi.world().actionVector2("move_x", "move_y");Use actionBinding / setActionBinding for runtime rebinding. Changes affect the next
input resolve and differences from authored defaults persist in the user's sparse
configs/input_bindings.json when the session shuts down. Projects continue to own
the action list and defaults in configs/input_actions.json. The current desktop input
backend owns player slot 0; other player slots return disconnected until
multi-controller backend support lands.
Samples: player_entity.zig (actionHeld for move); session HUD toggles profiler/visualizers in session_ui.zig (F3/F4/F5/F6).
3. Read from Kawa
fn update(dt, total_time) {
_ = dt;
_ = total_time;
if (Input.pressed("interact")) {
Debug.log("interact");
}
if (Input.held("move_forward")) {
// ...
}
}Sample: assets/scripts/camera_controller.kawa (Input.held("move_forward"), Input.mouse_left / mouse_delta + Actor.set_rotation_euler for view).
Verify
- Play the scene that contains your entity/script.
- Press the bound control — log line or gameplay response once per press (
pressed) vs while held (held). - Confirm Edit mode does not run entity updates (actions will not fire there).
Next
- First messages
- First entity — attach the action to a new actor