Class FollowerEntity Extends VersionedMonoBehaviour, IAstarAI, ISerializationCallbackReceiver, IFollowerEntity

Public

Movement script that uses ECS.

Warning

This script is still in beta and may change in the future. It aims to be much more robust than AIPath/RichAI, but there may still be rough edges.

This script is a replacement for the AIPath and RichAI scripts.

This script is a movement script. It takes care of moving an agent along a path, updating the path, and so on.

The intended way to use this script is to use these three components:

Features

  • Uses Unity's ECS (Entity Component System) to move the agent. This means it is highly-performant and is able to utilize multiple threads.

  • Supports local avoidance (see Local Avoidance).

  • Supports movement on spherical on non-planar worlds (see Spherical Worlds).

  • Supports movement on navmesh/recast graphs.

  • Does not support movement on grid and point graphs at the moment. This will be added in a future update.

  • Supports time-scales greater than 1. The agent will automatically run multiple simulations per frame if the time-scale is greater than 1 to ensure stability.

  • Supports off-mesh links. Subscribe to the onTraverseOffMeshLink event to handle this.

  • Automatically stops when trying to reach a crowded destination when using local avoidance.

  • Clamps the agent to the navmesh at all times.

ECS

This script uses Unity's ECS (Entity Component System) to move the agent. This means it is highly-performant and is able to utilize multiple threads. Internally, an entity is created for the agent with the following components:

Then this script barely does anything by itself. It is a thin wrapper around the ECS components. Instead, actual movement calculations are carried out by the following systems:

In fact, as long as you create the appropriate ECS components, you do not even need this script. You can use the systems directly.

Using ECS components has some downsides, though. Accessing properties on this script is significantly slower compared to accessing properties on other movement scripts. This is because on each property access, the script has to make sure no jobs are running concurrently, which is a relatively expensive operation. Therefore it is recommended to access properties on this script as little as possible. Or, if possible, use an ECS system and access the properties on the ECS components directly (which is much faster).

This is not a baked component. That is, this script will continue to work even in standalone games. It is designed to be easily used without having to care too much about the underlying ECS implementation.

Differences compared to AIPath and RichAI

In contrast to other movement scripts, this movement script does not use path modifiers at all (except for the seeker's built-in start-end modifier). Instead, this script contains its own internal FunnelModifier which it uses to simplify the path before it follows it.

This script has been written to remedy several inconsistency issues with other scripts. For example, it goes to great lengths to ensure that the reachedDestination and reachedEndOfPath properties are as accurate as possible at all times, even before it has had time to recalculate its path to account for a new destination. It does this by locally repairing the path (if possible) immediately when the destination changes instead of waiting for a path recalculation. This also has a bonus effect that the agent can often work just fine with changing destinations, even if it almost never recalculates its path (though the repaired path may not always be optimal).

Best practices for good performance

The main performance foot-gun when using this script, is that accessing properties on it is pretty expensive since it needs to synchronize with entity storage. Therefore it is recommended to access properties on this script as seldom as possible. Avoid setting fields to the same value over and over again every frame, for example. If you have a moving target, try to use the AIDestinationSetter component instead of setting the destination property manually, as that is faster than setting the destination property every frame.

You can instead write custom ECS systems to access the properties on the ECS components directly. This is much faster. For example, if you make the agent follow a particular entity, you could create a new DestinationEntity component which just holds an entity reference, and then create a system that every frame copies that entity's position to the DestinationPoint.destination field (a component that this entity will always have).

This script has some optional parts. Local avoidance, for example. Local avoidance is used to make sure that agents do not overlap each other. However, if you do not need it, you can disable it to improve performance.

Public Methods

DrawGizmos ()
Public
GetRemainingPath (buffer, stale)

Fills buffer with the remaining path.

Public
Move (deltaPosition)

Move the agent.

Public
SearchPath ()

Recalculate the current path.

Public
SetDestination (destination, facingDirection=…)

Set the position in the world that this agent should move to.

Public
SetPath (path, updateDestinationFromPath=true)

Make the AI follow the specified path.

Public
SyncWithEntity ()

Copies all settings from this component to the entity's components.

Public
SyncWithEntity (managedState, shape, movementSettings)

Copies all settings from this component to the entity's components.

Public
Teleport (newPosition, clearPath=true)

Instantly move the agent to a new position.

Public

Public Variables

autoRepath

Policy for when the agent recalculates its path.

Public
canMove

Enables or disables movement completely.

Public
debugFlags

Enables or disables debug drawing for this agent.

Public
desiredVelocity

Velocity that this agent wants to move with.

Public
desiredVelocityWithoutLocalAvoidance

Velocity that this agent wants to move with before taking local avoidance into account.

Public
destination

Position in the world that this agent should move to.

Public
endOfPath

End point of path the agent is currently following.

Public
entity

Entity which this movement script represents.

Public
entityExists

True if this component's entity exists.

Public
groundMask

Determines which layers the agent will stand on.

Public
hasPath

True if this agent currently has a path that it follows.

Public
height

Height of the agent in world units.

Public
isStopped

Gets or sets if the agent should stop moving.

Public
isTraversingOffMeshLink

True if the agent is currently traversing an off-mesh link.

maxSpeed

Max speed in world units per second.

Public
needsSyncWithEntity
Public
onSearchPath

Called when the agent recalculates its path.

Public
onTraverseOffMeshLink

Callback to be called when an agent starts traversing an off-mesh link.

pathPending

True if a path is currently being calculated.

Public
position

Position of the agent.

Public
radius

Radius of the agent in world units.

Public
reachedDestination

True if the ai has reached the destination.

Public
reachedEndOfPath

True if the agent has reached the end of the current path.

Public
remainingDistance

Approximate remaining distance along the current path to the end of the path.

Public
rotation

Rotation of the agent.

Public
rotationSmoothing

How much to smooth the visual rotation of the agent.

Public
rvoAgent

Local avoidance settings.

Public
steeringTarget

Point on the path which the agent is currently moving towards.

Public
stopDistance

How far away from the destination should the agent aim to stop, in world units.

Public
updatePosition

Determines if the character's position should be coupled to the Transform's position.

Public
updateRotation

Determines if the character's rotation should be coupled to the Transform's rotation.

Public
velocity

Actual velocity that the agent is moving with.

Public

Private/Protected Members

AssertEntityExists ()
Private
Awake ()
Protected
CancelCurrentPathRequest ()
Private
ClearPath ()
Private
FinalizeMovement (nextPosition, nextRotation)

Move the agent.

Private
FindComponents ()
Private
MovementUpdate (deltaTime, nextPosition, nextRotation)

Calculate how the character wants to move during this frame.

Private
OnAfterDeserialize ()
Private
OnBeforeSerialize ()
Private
OnDisable ()

Called when the component is disabled or about to be destroyed.

Private
OnEnable ()
Private
OnPathComplete (path)
Private
OnUpgradeSerializedData (version, unityThread)

Handle serialization backwards compatibility.

Protected
Reset ()

Handle serialization backwards compatibility.

Protected
ShapeGizmoColor
Private Static Readonly
Start ()
Private
achetypeWorld
Private Static
agentCylinderShapeAccessRO
Private Static
agentCylinderShapeAccessRW
Private Static
agentOffMeshLinkTraversalRO
Private Static
archetype
Private Static
destinationPointAccessRO
Private Static
destinationPointAccessRW
Private Static
indicesScratch
Private Static
localTransformAccessRO
Private Static
localTransformAccessRW
Private Static
managedState
Private
managedStateAccessRO
Private Static
managedStateAccessRW
Private Static
movement
Private
movementControlAccessRO
Private Static
movementControlAccessRW
Private Static
movementOutputAccessRW
Private Static
movementPlaneAccessRO
Private Static
movementPlaneAccessRW
Private Static
movementSettingsAccessRO
Private Static
movementSettingsAccessRW
Private Static
movementStateAccessRO
Private Static
movementStateAccessRW
Private Static
nextCornersScratch
Private Static
path
Private
resolvedMovementAccessRO
Private Static
scratchReferenceCount
Private Static
seeker

Cached Seeker component.

Private
shape
Private
tr

Cached transform component.

Private

Deprecated Members

canSearch

Enables or disables recalculating the path at regular intervals.

Public