File size: 4,006 Bytes
40c0886
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# Unity Navigation (NavMesh, Pathfinding, AI)

## Overview

Unity's AI Navigation package (`com.unity.ai.navigation`) bakes a
**NavMesh** -- a simplified walkable surface -- and provides
`NavMeshAgent` to move characters along it. This is the standard solution
for AI NPCs in the generated project.

## Baking a NavMesh

1. Mark static colliders as **Navigation Static** (Window > AI >
   Navigation > Object).
2. Bake the NavMesh (Window > AI > Navigation > Bake).
3. At runtime, every `NavMeshAgent` on the scene automatically walks on
   the baked NavMesh.

> For a procedurally generated city, baking at design time is impossible.
> Either:
> * Bake at runtime via `NavMeshSurface.BuildNavMesh()` (AI Navigation
>   package), or
> * Use the simpler approach in `NPCController.cs`: pick random points via
>   `NavMesh.SamplePosition` so the agent always lands on a valid walkable
>   spot.

## NavMeshAgent

```csharp
[RequireComponent(typeof(NavMeshAgent))]
public class NPCController : MonoBehaviour
{
    private NavMeshAgent _agent;

    private void Awake() => _agent = GetComponent<NavMeshAgent>();

    private void Start()
    {
        PickNewDestination();
    }

    private void PickNewDestination()
    {
        Vector3 random = transform.position + Random.insideUnitSphere * 20f;
        if (NavMesh.SamplePosition(random, out NavMeshHit hit, 20f, NavMesh.AllAreas))
            _agent.SetDestination(hit.position);
    }
}
```

Key properties:

| Property            | Meaning                                                    |
|---------------------|------------------------------------------------------------|
| `speed`             | Max movement speed (m/s)                                   |
| `angularSpeed`      | Max turning speed (deg/s)                                  |
| `acceleration`      | How quickly the agent reaches `speed`                     |
| `stoppingDistance`  | Distance at which the agent considers the destination reached |
| `autoBraking`       | Whether to slow down near the destination                  |
| `isStopped`         | Pause the agent without clearing the path                  |
| `remainingDistance` | Distance to the end of the current path                    |
| `pathPending`       | True while a new path is still being computed              |

## State machines for AI

A common pattern is a small finite state machine:

```
Idle  --(timer)-->  Wander  --(player in range)-->  Chase
  ^                    |                                 |
  |     (lost sight)   +---------------------------------+
  +--------------------+
```

The generated `NPCController.cs` implements exactly this pattern with three
states (`Idle`, `Wander`, `Chase`) and switch-based dispatch in `Update()`.

## Pathfinding details

* `NavMeshAgent.SetDestination(target)` is async -- the path may not be
  ready on the same frame. Check `!agent.pathPending` before reading
  `remainingDistance`.
* `agent.pathStatus` tells you whether a path is `PathComplete`,
  `PathPartial` or `PathInvalid`.
* `NavMesh.CalculatePath(source, target, mask, out path)` lets you compute a
  path without an agent (useful for "can the NPC reach this point?" checks).

## NavMeshObstacle

For dynamic obstacles (a car parked across a road, a door that closes), add
a `NavMeshObstacle` component. Set `carve = true` to actually cut a hole in
the NavMesh; otherwise the obstacle only pushes agents around.

## Off-mesh links

When the walkable surface is disconnected (e.g. a gap between rooftops),
drop an `OffMeshLink` to let agents jump or teleport across. You can also
use them for ladders, climbing walls, and jumping down from ledges.

## Performance

* Keep the agent count under ~100 simultaneous active agents on desktop.
* For larger crowds use the **ECS/DOTS navigation** solutions or batch
  pathfinding across frames.
* Set `agent.autoRepath = false` if you do not need the agent to follow
  moving targets, and call `SetDestination` less often (e.g. every 0.5 s).