# Unreal Engine: Introduction to AI

*2025-10-15*

> Notes taken from the sixteenth week of Game Programming Foundations


After last week's deeper dive into [game effects]({{< relref "/posts/2025/unreal-engine-15-game-effects" >}}), this week was **AI fundamentals**: [AI Characters](https://dev.epicgames.com/documentation/unreal-engine/artificial-intelligence-in-unreal-engine), [AI Controllers](https://dev.epicgames.com/documentation/unreal-engine/ai-controllers-in-unreal-engine), and the [Navigation System](https://dev.epicgames.com/documentation/unreal-engine/navigation-system-in-unreal-engine) ([NavMesh](https://dev.epicgames.com/documentation/unreal-engine/modifying-the-navigation-mesh-in-unreal-engine)) – the three pillars of making entities that can think, move, and collide.

Rather than re-invent the wheel, I took advantage of the existing codebases and examples from the course and uploaded them to the following repositories for future reference:

- [sawnoff-studios/nav-mesh-demo](https://github.com/sawnoff-studios/nav-mesh-demo)
- [sawnoff-studios/avoidance-demo](https://github.com/sawnoff-studios/avoidance-demo)

Notes below.

---

## The Key Elements of AI

- **AI Character** – the entity in the game world. Humanoids typically derive from the **Character** class (getting movement, health, collision); non-humanoids (drones, tanks) from **Pawn**
- **AI Controller** – the "brain" for AI actors (move, attack). Distinct from the AI Character and exists separately – the same controller/pawn split the player side has had since the controllers week
- **Navigation System (NavMesh)** – AI characters rely on the NavMesh to understand traversable space and calculate paths from A to B

### What the split buys you

- **Delegation of tasks:** the controller issues commands (move to this location), the character executes them
- **Separation of awareness:** the character physically exists in the world; the controller handles high-level decision-making
- **Classic example:** an AI guard patrols an area → the guard "sees" the player → the controller abandons patrolling and chases

## Adding the NavMesh

- Place a **NavMeshBoundsVolume** (Volumes section) to designate the nav mesh area - the volume acts as a container for the NavMesh
- Paths are built automatically from the geometry inside the volume; green areas are walkable surfaces
- Walls, stairs, and uneven terrain are all taken into account
- View it by pressing **P**, or the `Show Navigation` console command

### View modes and debugging

A **RecastNavMesh** actor is created automatically when the NavMesh is added – this does the actual generation work. Useful view modes on it:

- **Draw Polygon Costs** - displays the cost agents pay for path calculations
- **Tile build time as heatmap** - colour-codes tiles by how long they took to build
- **Heuristic Scale** - tunes the pathfinding bias (see flag below)

### Multiple agents of different sizes

- Different-sized agents need multiple NavMeshes: small agents in tight spaces, larger agents where they fit
- Adding an agent entry automatically creates an extra RecastNavMesh actor
- Enable drawing on it to inspect; `CycleNavDrawn` cycles visibility between them at runtime
- NavMesh assignment can be automatic – the pawn's **capsule size** determines which NavMesh it uses

## Custom Nav Volumes

**Nav Modifier Volumes** come with four pre-created setups:

- **Default** - regular navigable area
- **Null** - impassable
- **Obstacle** – expensive to cross, only crossed when essential
- **Low Height** – cannot be traversed

Specific regions can be assigned these properties to influence how AI behaves when crossing them.

For full control, inherit from `NavArea` to create a **custom NavMesh modifier** – altering the default crossing cost, the fixed area entry cost, and the display colour.

## Nav Link Proxies

Areas that weren't connected automatically can be linked manually:

- **NavLinkProxy** – placed so its left/right points connect to the NavMesh; can constrain the direction of travel
- **Smart Nav Link Proxies** – for complicated links, e.g. jumping up a ledge:
  - Override `ReceiveSmartLinkReached` - triggers when an actor steps on the link's start
  - Set *Smart Link is Relevant* to true
  - `CalculateVelocity()` with `DestinationLocation` and `StartingLocation` inputs, `Velocity` output
- **Auto-generation:** tick *Generate Nav Links* on the RecastNavMesh actor, create a new actor with `GeneratedNavLinksProxy` as parent, set *Link Proxy Class* to it, and links that need jumping should generate automatically

## Dynamic NavMeshes

- NavMesh generation is **Static** by default – generated before runtime, never updated
- *Navigation Mesh → Runtime → Runtime Generation* offers:
  - **Dynamic Modifiers Only** – updates the NavMesh but only for Nav Modifiers
  - **Dynamic** - adapts to everything including collisions; the most resource-intensive

## Avoidance Systems

- **No Avoidance** – agents don't attempt to avoid each other; collisions happen
- **Reciprocal Velocity Obstacle (RVO)** – each actor pushes away from other agents it encounters, adapting paths on the fly
- **Detour Crowd Manager** – considers other actors when selecting paths; use a `DetourCrowdAIController` to control characters, and tune *Project Settings → Crowd Manager* (max agents, max agent radius)
- **MassCrowd / Mass AI** - outperforms the others and scales to thousands of agents

---

## Notes on things that stood out

The mental model that made this week click: the controller/pawn split for AI mirrors the player's controller/pawn split exactly – meaning everything from the controllers and communication weeks transfers wholesale. An AI guard "seeing" a player is a perception problem bolted onto the same architecture you already know.

The avoid-system ladder (None → RVO → Detour Crowd → Mass) is really a scalability ladder – picking the right rung for your agent count matters more than any settings tweak within a rung.
