# Crowd Actor

`ACrowdToolkitActor` (display name **Crowd Toolkit Actor**) is the one object you interact with.
It wraps the simulation library as an Actor: every tunable lives as a property in its details
panel, and every operation - spawn, order, query, walls - is a Blueprint-callable function.

Each actor owns its **own independent simulation** (created on `BeginPlay`, destroyed on
`EndPlay`), so any number of crowd actors can run side by side. All positions are in **world
space**; the simulation's X/Y maps directly to world X/Y, and Z is
[tracked per agent](../concepts/06-ground_snapping.md).

::: tip
You usually don't place this yourself - the [subsystem](./02-subsystem.md) adopts a placed
instance or spawns one, and you reach it with
[`GetCrowd`](./03-function_library.md#world-access). Place a `BP_Crowd` when you want to configure
it in the details panel.
:::

---

## Configuration properties

All config properties are `EditAnywhere` + `BlueprintReadWrite`. They are copied into the
simulation **every tick** (via `ApplyConfig`), so changing one at runtime takes effect
immediately. Clamp ranges below are the valid limits; the simulation re-clamps on apply.

![Crowd actor details panel](../assets/api/crowd-details-panel.png)

### Agent

| Property | Default | Range | Description |
|---|---|---|---|
| **Radius** | `15` | `1 – 60` | Agent collision radius. Global - every agent shares it. |
| **Speed** | `100` | `≥ 0` | Default max speed for agents with no [per-agent override](#per-agent-speed). Uncapped on top. |
| **Acceleration** | `400` | `0 – 5000` | How fast agents speed up, units/s². `0` = instant. |
| **Deceleration** | `600` | `0 – 5000` | How fast agents slow down, units/s²; also shapes the arrival braking curve so stops ease out. `0` = instant. |
| **Turn Rate** | `540` | `0 – 1440` | Max heading change while travelling, deg/s - agents arc into new directions instead of flipping. `0` = unlimited. |
| **Stuck Timeout** | `2` | `0 – 30` | Seconds without progress before [`OnAgentsStuck`](../concepts/05-events.md) reports an ordered agent (re-fires each interval). `0` disables stuck events. |

### Formation

See [Formations](../concepts/02-formations.md).

| Property | Default | Range | Description |
|---|---|---|---|
| **Shape** | `Blob` | enum | `Blob`, `Box`, or `Wedge`. |
| **Settle Radius** | `10` | `1 – 50` | How close to its slot an agent must be to count as settled. |
| **Slot Spacing** | `1.1` | `0.5 – 2` | Slot spacing, in agent diameters. |

### Navigation

See [Navigation](../concepts/01-navigation.md).

| Property | Default | Range | Description |
|---|---|---|---|
| **Mode** | `Flow Field` | enum | `None`, `Flow Field`, or `Spatial A*`. |
| **Tile Size** | `20` | `4 – 64` | World units per routing cell. |
| **Smooth Flow** | `true` | bool | *Flow Field only.* Gradient flow vs nearest-of-8 directions. |

### Avoidance

See [Avoidance](../concepts/03-avoidance.md). Always on - these only tune it.

| Property | Default | Range | Description |
|---|---|---|---|
| **Strength** | `150` | `0 – 1000` | Mutual push between two travelling agents. |
| **Settle Push** | `50` | `0 – 1000` | How strongly a settled agent steps aside for a passer-by. |

### Walls

See [Wall Generation](../get_started/04-wall_generation.md).

| Property | Default | Range | Description |
|---|---|---|---|
| **Has Collision** | `true` | bool | Gates physical wall collision. Off = walls still block pathfinding but agents can pass through. |
| **Tile Size** | `40` | `4 – 64` | World units per wall tile. |
| **Near Wall Cost** | `3` | `1 – 20` | Pathfinding traversal multiplier for open cells next to walls. `1` disables the bias. |
| **Wall Generation Method** | `Nav Mesh` | enum | Wall source baked once on `BeginPlay`: `None` or `Nav Mesh`. |
| **Generate Nav Mesh Border Walls** | `false` | bool | Also wall off the nav mesh's outer border, sealing agents inside it. |

### Ground

See [Ground Snapping](../concepts/06-ground_snapping.md).

| Property | Default | Description |
|---|---|---|
| **Snap To Ground** | `false` | Re-trace the ground under each agent every tick and glue its Z to the hit. Off = agents keep their spawn Z. |
| **Ground Trace Channel** | `Visibility` | Collision channel the ground trace runs against. |
| **Ground Trace Up Limit** | `200` | Trace starts this far above the agent's current Z. |
| **Ground Trace Down Limit** | `200` | Trace ends this far below the agent's current Z. On a miss the agent keeps its Z. |
| **Ground Offset** | `0` | Added to the hit to get the agent's Z (e.g. mesh half-height). |
| **Ground Trace Ignored Actors** | `[]` | Actors the trace ignores. **Add your crowd renderer here** (see the [self-collision trap](../concepts/06-ground_snapping.md#the-self-collision-trap)). |
| **Max Ground Traces Per Tick** | `0` | Cap on ground re-traces per tick (round-robin). `0` = trace every agent every tick. |
| **Align Transforms To Ground** | `false` | Tilt rendered transforms to the traced ground normal (slopes). Needs **Snap To Ground**. |

### General

| Property | Default | Description |
|---|---|---|
| **Auto Tick** | `true` | Advance the simulation automatically each frame in `Tick`. Turn off to drive it yourself with [`SimTick`](#simulation-control). |
| **Reset On Begin Play** | `true` | Clear the simulation to empty when play begins. |
| **Transform Scale** | `1` | Uniform scale applied to transforms from [`GetAgentTransforms`](#per-agent-getters). |

### Debug

There is **no master switch**: each overlay is drawn every tick when its own flag is on, so
untick them all to draw nothing. All default to off and are compiled out of Shipping builds.
See [Debugging](#debugging--diagnostics).

| Property | Default | Description |
|---|---|---|
| **Draw Walls** | `false` | The wall grid, one gray box per tile. |
| **Draw Agents** | `false` | Every agent as a sphere of the agent radius (green when settled, white while moving). |
| **Show Slots** | `false` | The slot rings agents settle onto. |
| **Show Nav Goals** | `false` | Each agent's shared formation anchor. |
| **Show Velocity** | `false` | Each agent's velocity vector. |
| **Show Flow Field** | `false` | Per-cell flow arrows of every active flow field. Only populated in **Flow Field** navigation mode. |
| **Show A\* Paths** | `false` | Each agent's current cached route as a polyline. Only populated in **Spatial A\*** navigation mode. |

---

## Functions

### Simulation control

==- SimTick
```cpp
void SimTick(float DeltaSeconds);
```
Advance the simulation by `DeltaSeconds` (pushes the current config first). Called
automatically each frame when **Auto Tick** is on; call it yourself when you've turned Auto
Tick off and want to drive the step manually. `DeltaSeconds` is clamped and substepped
internally, so a frame hitch slows simulated time briefly instead of letting agents tunnel
through walls.
===

==- ResetSimulation
```cpp
void ResetSimulation();
```
Clear all agents, walls and pathfinding/avoidance caches (config is kept). Pending
spawned/removed event batches are discarded - the indices they named no longer exist.
===

==- ApplyConfig
```cpp
void ApplyConfig() const;
```
Copy the actor's config properties into the simulation. Done automatically each tick; rarely
called directly.
===

### Spawning & removing

==- SpawnAgent
```cpp
void SpawnAgent(const FVector& Position);
```
Spawn one agent at `Position`. `Position.Z` becomes its initial [tracked Z](../concepts/06-ground_snapping.md);
the simulation itself takes only X/Y. Reported via [`OnAgentsSpawned`](../concepts/05-events.md).
===

==- SpawnAgentGrid
```cpp
void SpawnAgentGrid(const FVector& Origin, int32 Cols, int32 Rows, float Spacing);
```
Spawn a `Cols × Rows` grid of agents starting at `Origin`, `Spacing` apart.
===

==- RemoveAgent
```cpp
void RemoveAgent(int32 Index);
```
Queue the agent at `Index` for removal. Removals are **deferred**: the simulation applies the
queued batch (sorted, swap-and-pop) at the start of the next tick, so indices stay stable
between ticks and any set of agents can be removed in any order. Until that tick the agent is
still present (count and getters include it). Out-of-range indices and re-queues of an
already-queued index are ignored. Reported via [`OnAgentsRemoved`](../concepts/05-events.md)
before the removing tick, while the index is still valid.
===

==- GetAgentCount
```cpp
int32 GetAgentCount() const;
```
Number of agents currently in the simulation (includes agents queued for removal until the
next tick applies the removal).
===

### Identity - indices & ids

See [Indices & Stable IDs](../concepts/04-indices_and_ids.md). Lookups that miss return `-1`.

==- GetAgentId / GetAgentIndex
```cpp
int32 GetAgentId(int32 Index) const;   // stable id at Index, -1 if out of range
int32 GetAgentIndex(int32 Id) const;   // current index of Id, -1 if no such agent
```
===

==- GetAgentsIds / GetAgentsIndices
```cpp
TArray<int32> GetAgentsIds(const TArray<int32>& Indices) const;   // id per index, -1 per out-of-range
TArray<int32> GetAgentsIndices(const TArray<int32>& Ids) const;   // index per id, -1 per unknown
```
Batch forms - translate a whole selection in one call. Output is parallel to the input.
===

### Per-agent getters

Each getter takes an optional **`Indices` mask**: pass an **empty array** to get every agent
in storage order; pass a list of indices to get exactly those, **in mask order** (an
out-of-range index yields a zeroed entry, so the output always lines up 1:1 with the mask).
All the getters below are **parallel** - element *i* of each refers to the same agent.

==- GetAgentPositions
```cpp
TArray<FVector> GetAgentPositions(const TArray<int32>& Indices) const;
```
World positions, including each agent's tracked Z.
===

==- GetAgentTransforms
```cpp
TArray<FTransform> GetAgentTransforms(const TArray<int32>& Indices) const;
```
Render-ready transforms: location = agent position; rotation faces the travel direction
(holding the last facing while standing still), tilted to the ground normal when
**Align Transforms To Ground**; scale = **Transform Scale** on every axis. See
[Rendering Agents](../get_started/03-rendering_agents.md).
===

==- GetAgentGroundNormals
```cpp
TArray<FVector> GetAgentGroundNormals(const TArray<int32>& Indices) const;
```
Last traced ground normal per agent (world up until a trace has hit). See
[Ground Snapping](../concepts/06-ground_snapping.md).
===

==- GetAgentTargets
```cpp
TArray<FVector> GetAgentTargets(const TArray<int32>& Indices) const;
```
Each agent's individual formation **slot** position.
===

==- GetAgentNavGoals
```cpp
TArray<FVector> GetAgentNavGoals(const TArray<int32>& Indices) const;
```
The shared formation **anchor** the group is routing toward.
===

==- GetAgentVelocities
```cpp
TArray<FVector> GetAgentVelocities(const TArray<int32>& Indices) const;
```
Current velocities - use the magnitude to drive idle/walk/run animation.
===

==- GetAgentSettled
```cpp
TArray<bool> GetAgentSettled(const TArray<int32>& Indices) const;
```
Latched [settle](../concepts/02-formations.md#settling) (arrived) state per agent.
===

==- GetAgentSpeeds
```cpp
TArray<float> GetAgentSpeeds(const TArray<int32>& Indices) const;
```
Effective max speed per agent - the per-agent override where set, otherwise the **Speed**
config value.
===

### Selection queries

Return **indices** into the position array. The screen-rect query is the marquee-select
replacement; doing it per agent in a Blueprint loop costs a visible hitch at high counts.

==- GetAgentsInRect
```cpp
TArray<int32> GetAgentsInRect(const FBox2D& Rect) const;
```
Every agent inside the world-space XY rectangle.
===

==- GetAgentsInRadius
```cpp
TArray<int32> GetAgentsInRadius(const FVector& Center, float Radius) const;
```
Every agent within `Radius` of `Center` on the XY plane (`Center.Z` ignored).
===

==- GetAgentsInScreenRect
```cpp
TArray<int32> GetAgentsInScreenRect(APlayerController* PlayerController,
                                    const FVector2D& ScreenMin,
                                    const FVector2D& ScreenMax) const;
```
Every agent whose position projects inside the screen-space rect `[ScreenMin, ScreenMax]`
(inclusive) for the given player - **marquee selection in one call**. Projection uses each
agent's tracked Z, so it matches what the player sees.
===

### Orders

==- SetAgentsTarget
```cpp
void SetAgentsTarget(const TArray<int32>& Indices, const FVector& Position);
```
Order `Indices` into a [formation](../concepts/02-formations.md) centred on `Position`. The
core movement call. Replacing an unfinished order fires
[`OnAgentsOrdersCanceled`](../concepts/05-events.md) for the affected agents.
===

==- SetAgentTarget
```cpp
void SetAgentTarget(int32 Index, const FVector& Position);
```
Single-agent convenience - a formation of one, so the agent simply walks to the point.
===

### Per-agent speed

On top of the global **Speed** default, you can cap individual agents.

==- SetAgentsSpeed / SetAgentSpeed
```cpp
void SetAgentsSpeed(const TArray<int32>& Indices, float Speed);
void SetAgentSpeed(int32 Index, float Speed);
```
Set the max-speed override. `Speed < 0` **resets** the agents to the global **Speed** config
value; `Speed >= 0` is an absolute per-agent cap (`0` freezes them in place). Read the
effective values back with [`GetAgentSpeeds`](#per-agent-speed).

::: tip
Use this for mixed-speed groups (cavalry vs infantry), slows/buffs, or freezing units in
place without removing them.
:::
===

### Walls

See [Wall Generation](../get_started/04-wall_generation.md).

==- AddWallTile
```cpp
void AddWallTile(int32 X, int32 Y);
```
Block the wall-grid tile at `(X, Y)`. Idempotent - adding an existing tile is a no-op.
===

==- GetWallTiles
```cpp
TArray<FIntPoint> GetWallTiles() const;
```
Every blocked wall tile, as grid coordinates.
===

==- GenerateWallTiles
```cpp
int32 GenerateWallTiles();
```
Generate walls using the selected **Wall Generation Method** (`None` is a no-op). Called once
on `BeginPlay`; returns the number of tiles added.
===

==- GenerateWallTilesFromNavMesh
```cpp
int32 GenerateWallTilesFromNavMesh();
```
Rasterize the world's built navigation mesh into the wall grid (see
[Seeding walls from the nav mesh](../get_started/04-wall_generation.md#seeding-walls-from-the-nav-mesh)).
Requires the nav mesh to be built; safe to call repeatedly. Returns the number of tiles
added.
===

---

## Events

Multicast delegates - bind in Blueprint or C++. Full timing and usage in
[Events](../concepts/05-events.md).

| Event | Delivers | When |
|---|---|---|
| **OnAgentsSpawned** | indices | before the tick that adds them |
| **OnAgentsRemoved** | indices | before the tick that removes them (indices still valid) |
| **OnAgentsReachedGoal** | indices | after a tick, once per arrival |
| **OnAgentsStuck** | indices | after a tick, repeating while stuck |
| **OnAgentsOrdersCanceled** | indices | after a tick, when an order is replaced |

---

## Debugging & diagnostics

==- Debug overlays
Tick any of the debug flags (**Draw Walls**, **Draw Agents**, **Show Slots**, **Show Nav
Goals**, **Show Velocity**, **Show Flow Field**, **Show A\* Paths**) to draw that overlay into
the world. There is no master switch; untick them all to draw nothing.

!!!
Keep the overlays **off when measuring performance** - the agent overlays fetch every agent
array and issue per-agent debug primitives, which dominates the frame at high agent counts.
They are compiled out entirely in Shipping builds.
!!!
===

==- Flow-field cache stats
```cpp
int32 GetFlowFieldCount() const;   // number of cached flow fields
int64 GetFlowFieldBytes() const;   // their total memory
```
The cache grows with the world region the agents span - handy for understanding memory under
[Flow Field](../concepts/01-navigation.md) navigation.
===
