Architecture overview

An overview of how the package is structured.

Here you will learn how various parts of the package fit together.

Overview

There are several different parts of the package. Broadly, they can be grouped into:

  • Movement scripts, which tell the agent how to move and where it should move (see Movement scripts).

  • Graphs, which describe where an agent can move (see Graph Types).

  • Temporary obstacles, which cut holes in the navmesh or update it in other ways (see Graph Updates during Runtime).

  • Off-mesh links, which allow an agent to move or jump between otherwise disconnected parts of the navmesh (see NodeLink2).

  • Path modifiers, which post-process paths to for example smooth them (see Using Modifiers).

What you will primarily interact with is the movement script and the Seeker component. Both need to be attached to an agent that needs to move. The movement script controls how the agent should move, its velocity, rotation, and so on, as well as what the current destination of the agent is and when it should recalculate its path. The Seeker component is controlled by the movement script. The movement script tells it to calculate a path, and the Seeker will chug along and later (possibly in a later frame) return the result to the movement script. The Seeker is also responsible for running any path modifiers which may be attached.

The AstarPath component holds all the graph data in a scene. It follows the singleton pattern, so there should only be one such component in a scene. It may contain one or many graphs, of the same or different types. Each graph, in turn, contains and manages all its nodes (of which there may be many, sometimes up to millions).

You can access the graph data directly. For more info on this, see Accessing graph data.

The local avoidance system is almost completely separate from all pathfinding. Local avoidance doesn't care about which graph it is used on, or even that there are graphs. The movement script interacts with local avoidance using the RVOController component, which you may attach to your character GameObjects. The local avoidance simulation itself is done by the RVOSimulator component. It also follows the singleton pattern, and so only one should exist per scene. The RVOSimulator has its own internal worker threads, which it uses to simulate local avoidance with maximum performance.

The calculation of a path

When you set the destination of a movement script, this fires off a sequence of events:

  • The movement script will soon realize that its destination has changed, and will schedule an automatic path recalculation.

  • It creates a path object (e.g. ABPath) which it sends to the Seeker for calculation (except for the FollowerEntity, which skips the Seeker).

  • The Seeker will apply some settings and then send the path to the main AstarPath component.

  • The path is then put in a queue and a worker thread will pick it up as soon as possible. There may be many worker threads working on pathfinding at the same time.

  • The worker thread calculates the path using the A* algorithm. If you are interested, you can read more about that here: https://www.redblobgames.com/pathfinding/a-star/introduction.html.

  • The worker thread finishes the path calculation and puts the calculated path in a return queue.

  • In the next Update loop, the AstarPath component sends a message to the Seeker component that the path is calculated.

  • The Seeker runs modifiers which smoothes the path, or post-processes it in other ways. See Using Modifiers.

  • Finally, the Seeker calls the callback in the movement script to indicate that the path is now calculated and ready to be followed.

You can also bypass the Seeker component if you want to, and use the AstarPath component directly. Take a look at Searching for paths if you want to read more about that.