Skip to content
hikari
RenderingEditorAIToolchainDocumentation
Download

© 2026 Flying Rat Studio.
All rights reserved.

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

Brain execution for swarm populations

On this page
On this pageProgram and execution storageScheduling, sensing and eventsPlayable testHeadless verificationCustom gameplay tasks Back to top

A defineSwarm population can run the same Brain definitions as actors. Each member owns execution state; one population owner supplies the immutable program, sensing, target positions, scheduling and movement. Brain assets and code-authored Brains use identical task and transition semantics.

Swarm rows are not actors. They have no actor messages, attached components or individual actor inspector. Use a World-owned component or subsystem to bridge those services, then operate on the population's columns in bulk. The Example's src/ai_crowd.zig demonstrates this with an embedded crowd_ai owner and a separate ai_crowd_member swarm. No actor is created for each crowd member.

Program and execution storage

hi.ai.population.Program.bind(definition) validates and copies a definition into population-owned value storage. When loading an asset, call it once with the callback-scoped result of world.brainProgram(asset). Keep the copy, never the borrowed pointer. The owner must belong to one World; destroying it releases that population's state. A new Play loads the newly cooked asset.

hi.ai.brain.CompactInstance uses the same executor as Instance, retaining the machine and latest decision record, without an override array or history ring. On the tested macOS arm64 build it occupies 48 bytes, versus 560 bytes for Instance. Position, targets, observations and routes are additional storage.

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

pub const Crowd = hi.defineSwarm(.{
    .name = "crowd",
    .capacity = 1000,
    .data = struct {
        x: f32 = 0,
        y: f32 = 0,
        z: f32 = 0,
        execution: hi.ai.brain.CompactInstance = .{},
        search_seconds: ?f32 = null,
    },
});

The owner starts each new row with execution.start(definition) before spawning it. During simulation, call decide(definition, facts) and stepWithParameters(definition, position, targets, dt, overrides). The override slice is indexed by the definition's parameter slots: null or an absent slot inherits the shared default. Resolve named slots when binding the definition. This lets populations keep overrides in separate fields instead of reserving all 16 parameters in every execution instance.

Runtime(parameter_capacity, history_capacity) provides intermediate storage choices. A local override can only address a slot below parameter_capacity. Instance remains Runtime(16, 16); CompactInstance is Runtime(0, 0). All definitions keep the existing Brain capacities and supported task set.

Scheduling, sensing and events

  • population.Decisions performs round-robin admission over liveIndices() and a due-time column. begin(dt, limit) advances simulation time and resets the work budget. next(live, due) admits at most that limit, scanning at most the live population once. The caller sets each admitted member's next due time. Zero, negative or non-finite dt admits no work.
  • Keep the previous service time per member and pass accumulated simulation time to task execution. If a condition enters a new state now, do not charge that new state's timer for time before its entry. The sample starts its next task step at the following admission. Movement follows cached routes every frame.
  • population.Subject distinguishes actor identities from swarm identities. Swarm identity includes population ID, slot and generation. It is World-local; do not move these identities or service state between Worlds.
  • scheduler.Scheduler(population.Subject).Service(...) supplies the existing spatial candidate discovery, bounded observations, fairness and query budgets for mixed actor/swarm identities. scheduler.Service(...) remains the actor specialization. The game supplies snapshots and publishes results into columns.
  • Vision.querySegment allows a swarm observer with no actor collider to cast an occlusion segment. Pass an invalid actor as the exclusion. Subject identities do not create physics bodies; adapters still choose how to resolve any target collider. The sample uses swarm observers and ordinary actor targets.
  • population.Stimuli(capacity) receives stimuli once through the owner's onMessage. Each admitted member checks the bounded inbox using distance and category filtering. Its sequence cursor prevents duplicate delivery. The newest audible event wins; old events expire, overflow replaces the oldest, and overwritten exposes inbox pressure. Start new members at the inbox's current sequence so recycled slots do not inherit earlier noises.

Budgets bound admitted work, not CPU milliseconds. Snapshot gathering, sorting, memory maintenance, rendering and motor integration still cost work proportional to population size. Admission is currently synchronous; it does not dispatch jobs. The sample reserves separate budgets for its actor and swarm sensing services.

Playable test

Open Tutorials → AI Swarm Population (scenes/ai_population.json) and start Play. The dedicated scene starts with 100 members. Choose 1000 to scale up or 0 to retire the population. It contains no stationary load guards or door encounter. Creation and removal are limited to 32 members per simulation tick.

All members share assets/brains/crowd.brain.json:

  • Blue members patrol; hearing noise turns them amber while investigating.
  • Purple members search for the shared search_seconds duration.
  • Detecting a target takes priority over noise and turns members red as they flee.
  • Members have 6 m or 11 m hearing and different speeds. All initially inherit the Brain's search duration; the data model also supports individual overrides.

Use Noise to place a stimulus or Move player to move a visible target. Use Inspect, then click near a member to select it. The panel displays its slot/generation, state, transition reason, hearing, speed, selected target and bounded decision history. The yellow outline marks the selection. History starts with the latest record at selection and records subsequent decisions; selecting another generation clears it. Retire selected / respawn replaces that member with freshly initialized data while maintaining the requested population size.

The owner actor also exposes those diagnostics through the ordinary live actor inspector. This is an explicit population inspection adapter; there is no general editor hierarchy or inspector for arbitrary swarm rows yet.

The panel reports state counts, decisions, rays, route plans, CPU time, decision lateness, observation age, inbox overwrites and reserved data bytes. Reserved data counts the owner's runtime and member field payloads at capacity, excluding swarm bookkeeping, GPU resources and the actor's general overhead.

Change the Brain's search-duration default, let it cook, then start a new Play to apply it to the whole population. Pause freezes decisions and movement. Scene unload or owner disable retires members and clears the visual binding.

The fixture admits at most 128 decisions, 128 perception steps, 32 sight rays and 8 route plans per tick. It uses the existing flat-ground planner and shared scene obstacle snapshot. Members route around static walls; member-to-member avoidance, crowd packing, navmeshes and animation are not implemented by this sample. Rendered members are small instanced markers.

Headless verification

From src/hikari:

sh
zig build test -Dtest-filter=population -Dtest-filter=brain -Dtest-filter=scheduler -Dtest-filter=vision -Dgame-src=<absolute example/src>
zig build ai-population-bench -Dgame-src=<absolute example/src> -Doptimize=fast

See the measured benchmark results.

The benchmark runs 100 and 1,000 moving members sharing a code-authored Brain, with parameter overrides, a noise event, actor-target perception and selected member tracing. It checks admission limits and delivery to every member, and reports mean/p95 CPU time, worst decision lateness, noise delivery delay, observation age and storage sizes. Analytic visibility replaces physics; these numbers exclude the playable adapter, navigation, rendering and GPU work. The game-package test separately drives 1,000 real swarm rows through the sample's Brain/movement loop and checks route budgets and retirement/recycling.

See Brain assets, component storage, and Game AI for the underlying contracts.

Custom gameplay tasks

Populations can implement gameplay tasks with a borrowed member adapter and Registry.Driver(0). Share the bound table, issue an owner for each member lifetime using Subject.swarm, and cancel before retirement. Capability masks reject actor-only actions during binding. The existing moving crowd fixture keeps its movement/wait behavior and compact execution storage.

PreviousBrain assetsNext Localization

Documentation follows the current engine checkout.

Snapshot 86f12d68Source docs/guides/swarm-ai.md
On this pageProgram and execution storageScheduling, sensing and eventsPlayable testHeadless verificationCustom gameplay tasks Back to top