In **Crunch Element**, I crafted an AI framework that transforms static VR arenas into living, breathing battlefields. Enemies now coordinate, communicate, and adapt as a unit, creating emergent stealth and combat scenarios that keep every playthrough fresh.
![[tactical-search.gif]]
# Overview
### Compound State Machine
- **At Ease**: routine patrols and idle animations
- **Alerted**: minor threats detected—heightened vigilance
- **Searching**: coordinated sweep of last-known areas
- **Combat**: full engagement with reinforcements
- Transitions broadcast via in-game transmissions, so you feel the shift:
- _Individual Reaction_: “I just heard gunshots!”
- _HQ State Transmission_: “This is HQ. Sending units to investigate!” (if compound has already been previously alerted).
- **Hooking on event logic:** When the compound state machine reaches a specific state (IE: combat), scripted events can be triggered such as drop pod reinforcements the first time the combat state is reached.
- **Dynamic Music:** Each compound state has it's own music that plays while active to show the player the threat level. These tracks can be overridden by area volumes which is very useful for having a different combat audio in a headquarters building than in the mountains, or a different at-ease soundtrack on a certain scene.
### Prefab-Based Cover System
- **Cover Points** are attached to cover prefabs with metadata (cover normal, height, peek offsets).
- Enemies query nearby prefabs, score them by angle and proximity, and smoothly navigate between cover spots for realistic peeking and suppression.
- If a cover is destructible, it will remove itself as invalid after a certain percentage of debris has been destroyed.
### Shared Threat & Communication Pipeline
- **Local Suspicion List**: minor events (gunshots, footsteps) add transient entries per agent.
- **Global Threat List**: significant events (player spotted, loud explosions) generate threat objects shared across agents with configurable delay—mimicking radio chatter.
This approach of local and global lists allows for enemies to be killed before they broadcast their threat to the global network. It also allows for unique entities such as security cameras to create threats, despite their lack of behavior tree logic.
### Utility-Driven Request System
- Gameplay logic, objectives, and compound states create requests if enemies need to accomplish a shared goal such as investigating an area or defusing an objective.
- Agents calculate **utility scores** (distance, ammo, role) and submit a "bid", which is their relative cost of fulfilling that request. The price of a bid is a utility score, typically calculated by distance to the goal, current health, etc. Agents are assigned to requests based on how cheap their bid is. Requests have an agent capacity, so several agents can work together on fulfilling the same request.
- **Type-Specific Processing**: Each enemy type only has certain requests they can handle. An example is snipers ignore “investigate” requests, while bombers may prioritize a “charge” request.

### Diverse Subtrees per Enemy Type
- **Shooter Enemy**: heavy cover evaluation, advanced suppression tactics.
- **Bomber Enemy**: direct charge behaviors, minimal cover usage.

### Callouts
- **Local Callouts**: agents shout contextually (“Moving up!”, “Grenade out!”, “Reloading!”) with per-callout global cooldowns to prevent spam.