Input & Controls¶
All input is polled through the static Input class, typically
from OnUpdate. The scripts that reach for it most
often are data-collection controllers (start and stop recording, mark episode outcomes,
switch tasks) and robot driver scripts (WASD-style locomotion control).
Keyboard¶
Keys are identified by the KeyCode enum. Four query styles
cover the common needs:
| Method | Returns true… |
|---|---|
Input.IsKeyPressed(key) |
…on the first frame the key goes down. |
Input.IsKeyHeld(key) |
…every frame after that initial press. |
Input.IsKeyDown(key) |
…every frame the key is down (pressed or held). |
Input.IsKeyReleased(key) |
…on the frame the key is released. |
The right choice is almost always IsKeyPressed for one-shot actions and
IsKeyDown for continuous ones:
using Hazel;
using Hazel.Data;
protected override void OnUpdate(float ts)
{
// One-shot recording controls: each press triggers exactly once.
if (Input.IsKeyPressed(KeyCode.Enter))
Observer.StartRecording();
if (Input.IsKeyPressed(KeyCode.X))
Observer.EndCurrentEpisode(success: false);
if (Input.IsKeyPressed(KeyCode.Y))
Observer.EndCurrentEpisode(success: true);
if (Input.IsKeyPressed(KeyCode.Escape))
Observer.StopRecording();
// Continuous robot drive: every frame while held.
if (Input.IsKeyDown(KeyCode.W))
DriveForward(ts);
if (Input.IsKeyDown(KeyCode.A))
TurnLeft(ts);
}
Reach for IsKeyPressed when one press should map to one action: starting a session,
closing an episode, switching to a task index, resetting the scene. Reach for
IsKeyDown or IsKeyHeld when the action should happen every frame the key is held:
driving a robot, scrubbing a value, holding a finger gripper closed.
IsKeyHeld vs IsKeyDown
IsKeyDown is the union of pressed-and-held. IsKeyHeld excludes the very first
frame of the press. Both are fine for continuous actions; IsKeyDown is the more
common choice and matches every other engine's "is the key down right now".
Common bindings¶
There are no engine-defined keybindings for script-level work. These are conventions worth following so users see consistent controls across scenes:
| Key | Common use |
|---|---|
| Enter | Start a recording session |
| X | End the current episode as failed |
| Y | End the current episode as successful |
| Esc | Stop recording |
| R | Reset the scene to its starting state |
| Space | Pause / step / toggle a debug flag |
| 1 – 9 | Switch task index (with Observer.SetCurrentTaskIndex) |
| W A S D | Drive a robot |
See Recording with the Observer for the full episode-lifecycle API and Getting started for the WASD walker example.
Mouse¶
Input exposes the same four query styles for mouse buttons —
IsMouseButtonPressed, IsMouseButtonHeld, IsMouseButtonDown,
IsMouseButtonReleased — plus
GetMousePosition() for the cursor.
Mouse buttons are identified by the MouseButton enum.
See the Input reference for the complete list including the
mouse scroll wheel.
Controllers¶
Connected gamepads are queried by id:
Input.GetConnectedControllerIDs()returns the IDs currently plugged in.Input.IsControllerButtonDown(id, button)andInput.GetControllerAxis(id, axis)read button and stick state.
Buttons and axes use the
GamepadButton enum and matching axis identifiers.
A gamepad driver script for a robot then looks the same shape as the keyboard one,
swapping Input.IsKeyDown for Input.GetControllerAxis(id, axis) on the stick that
should drive forward velocity.