06 — Tuning and Extending
Gizmos are your AI debugger
Every script in this kit draws its senses when selected: sensor spheres and cones, feeler rays, patrol routes, A* paths, grid cells. This isn't decoration — AI bugs are almost always invisible-state bugs, and drawing the state is how you find them. Habit to grade for: any new sense or decision a student adds should come with an OnDrawGizmosSelected line showing it. (Debug.DrawRay inside Update works too, and shows runtime rays.)
Add an on-screen state label in one line inside any Tick method: Debug.Log is fine for moments, but for continuous state try a TextMesh above the enemy's head, or just the tint trick the kit already uses.
Tuning cheat-sheet (the dials and what they feel like)
- Vision radius / cone — how "aware" the world feels. Wide+short = brawler; narrow+long = sentry.
- Lose-sight time — enemy memory. 1 s = goldfish, forgiving; 5 s = relentless, tense. This one dial sets the stealth tone of the whole game.
- Chase vs player speed — the fairness dial. Enemy slightly slower = pressure without hopelessness; equal = corridor-dependent; faster = must be escapable via level design (LOS breaks, one-way drops).
- Alert pause — reaction fairness. Shorter = harder, "twitchier" game.
- Attack cooldown + range — combat rhythm. With
stoppingDistance(3D) tune until enemies don't overlap the player. - Patrol wait — makes patrols feel like behavior rather than a conveyor belt; randomize ±50% for cheap naturalism.
Class exercise that lands well: give every team the same demo scene and five minutes to tune "an easy enemy" and "a terrifying enemy" — then compare Inspector values on screen. Same code; wildly different games.
High-value extensions, in teaching order
- Investigate / last-known-position (the biggest IQ jump per line): while vision succeeds, store
lastSeen = player.position. On losing sight, go tolastSeen, wait 2 s, then give up. Works identically in all three enemies — in 3D it'sSetDestination(lastSeen), top-down it'sPathTo(lastSeen). - Hearing: a second sense that ignores walls but has a small radius; sprinting players are "louder" (bigger radius). Wire it to enter Investigate rather than Chase — now you have a stealth game.
- Alarm propagation: enemies alert nearby enemies (see lesson 05's exercise).
- Health & death: give enemies a
Healthcomponent; on death, disable the AI and collider, tint gray. Connect the 3DStrike()hook to the player's health too. - Waypoint variety: patrol styles — loop, ping-pong, random next point — one enum, ten lines, visibly different personalities.
When you outgrow the enum FSM
The switch-statement FSM is right for this course. Its growth path, in order: class-per-state (each state an object with Enter/Tick/Exit — same idea, better for many states); behavior trees (hierarchical, designer-friendly; the standard for complex game AI — look at Behavior Designer or Unity's Behavior package); utility AI (score every option, pick the best — great for sims). Each is a decide-layer swap; your sensors and movement code survive intact, which is the payoff of the three-layer split from 01 - Enemy AI Concepts.
Reusing and exporting
The same drill as the other kits: select Assets/EnemyAIStarterKit, right-click → Export Package… — or copy just the scripts you need; only EnemyKitSetup.cs (editor-only) and the AI Navigation package (3D only) have any dependencies. TargetSensor, GridPathfinder2D, and DamageFlash are drop-in reusable in any project today.
Back to 00 - Start Here