A two-team AI battle built in Unity where autonomous agents compete to steal the enemy's flag and return it to base. Each team of three agents operates using a Finite State Machine (FSM) with coordinated leader/follower behaviour.
- 2 teams — Red and Blue — each with 3 AI agents
- Agents navigate the environment using Unity's NavMesh
- Objective: steal the enemy flag and return it to your base
- Agents can attack, flee, collect items, and coordinate with teammates
The core AI is a Finite State Machine implemented in AI.cs. Each agent evaluates state transitions every frame based on perception, health, inventory, and team state.
| State | Behaviour |
|---|---|
0 |
Default — evaluate conditions and transition |
1 |
Move toward enemy base, acquire a target |
2 |
Pursue and attack the current target |
3 |
Move to and collect the enemy flag |
4 |
Return to friendly base and score the flag |
5 |
Escort a teammate carrying the flag |
6 |
Defend the friendly base area |
7 |
Flee from an enemy when HP is critically low |
Has enemy flag → State 4 (return), broadcast State 5 to team
Sees flag in field → State 3 (collect)
Sees flag near base → State 6 (defend)
No target visible → State 1 (attack run)
Target in sight → State 2 (attack)
HP < 50 → State 7 (flee)
- Member 1 acts as the Leader — selects the nearest visible enemy as the target
- Members 2 & 3 copy the Leader's target each frame
- If the Leader is killed, followers find a new Leader or self-select a target
- Flag capture broadcasts a state change to all teammates via
SetAllTeamStates()
Assets/
├── Scripts/
│ ├── AI.cs # Core FSM logic (main AI brain)
│ ├── Constants.cs # Tags and GameObject name constants
│ ├── AI Support/
│ │ ├── AgentActions.cs # Action API (MoveTo, Attack, Flee, etc.)
│ │ ├── AgentData.cs # Agent stats, flags, team info
│ │ ├── Sensing.cs # Perception (sphere overlap + raycast)
│ │ └── InventoryController.cs # Item management
│ ├── GamePlaySupport/
│ │ ├── Flag.cs # Flag collect/drop behaviour
│ │ ├── HealthKit.cs # Healing item
│ │ ├── PowerUp.cs # Damage multiplier item
│ │ ├── Collectable.cs # Base class for collectables
│ │ ├── ObjectSpawner.cs # Item respawn logic
│ │ ├── AiAgentSpawner.cs # Agent respawn logic
│ │ ├── TeamData.cs # Team configuration per base
│ │ └── SetScore.cs # Score tracking
│ └── UI/
│ ├── HealthBarUpdate.cs
│ ├── AiMoodIconController.cs
│ ├── InventoryDisplay.cs
│ └── ShowScore.cs
├── Prefabs/
│ ├── Blue Team Member.prefab
│ ├── Red Team Member.prefab
│ ├── Blue Flag.prefab / Red Flag.prefab
│ ├── Base.prefab
│ ├── Health Kit.prefab
│ └── Power Up.prefab
├── Animations/
│ └── Sword Swing.anim
└── Materials/
├── BlueTeam.mat / RedTeam.mat
└── ...
Uses Physics.OverlapSphereNonAlloc to detect nearby objects, filtered by a VisibleToAI layer mask. A raycast checks for wall obstructions before adding objects to the perceived list. Provides:
GetEnemiesInView()/GetFriendliesInView()GetCollectablesInView()GetObjectInViewByName(string name)IsInAttackRange(target)/IsItemInReach(item)
Wraps NavMesh pathfinding and game interactions:
MoveTo(GameObject)/MoveTo(Vector3)— NavMesh-validated movementAttackEnemy(target)— range check, hit probability, optional power-up damageFlee(enemy)— rotates away and samples a valid NavMesh escape pointCollectItem/DropItem/UseItem
Tracks per-agent state: HP, team tags, flag names, base references, power-up status, and mood (AiMood enum: Idle, Attacking, Fleeing, Winning, Losing, Dead).
- Unity 2018.x or later (project uses NavMesh and standard animator)
- No external packages required beyond included Unity Standard Assets
- Clone or download this repository
- Open the project in Unity Hub
- Open the
CaptureTheFlagscene fromAssets/ - Press Play
All custom AI logic lives in Assets/Scripts/AI.cs. The support scripts (AgentActions, Sensing, AgentData) provide the full API — see the header comment block in AI.cs for a complete reference.
- Flee state unreachable — the HP < 50 check in
StateChange()is evaluated after the target check, so agents with a target never flee even when critically injured - No null guard on
GetEnemiesInView()— can returnnull, causing aNullReferenceExceptioninFindTarget()when iterating - Health kits and power-ups unused — agents never pick up or use collectables despite the API supporting it
GameObject.Find()called each frame viaSetAllTeamStates()— fine at this scale, but not performant for larger teams
This project was created as a university assignment. Feel free to use it as a reference or learning resource.