This page covers slopes, ladders, moving platforms, flying and ranged enemies, knockback and stun, bosses, and baking options. Each section names the demo scene that shows it (in Samples/Demo/Scenes).
Demo: 03_Slopes_OneWay
Two slope angles are supported on the ground Tilemap:
| Angle | Tiles |
|---|---|
| 45° | One tile rising one cell. |
| 1:2 (about 26.6°) | Two tiles rising one cell: a low half and a high half. |
Both directions (rising and falling to the right) work, including tiles flipped horizontally in the Tilemap.
Detection. For tiles whose collider type is Sprite, baking reads the sprite’s physics shape and matches its top edge against the shapes above. Tiles that do not match are treated as solid blocks. No setup is needed if your slope sprites have accurate physics shapes. To check, open the sprite in the Sprite Editor and select Custom Physics Shape.
Overrides. If a tile is detected wrongly, use a Nav Tile Types asset:
The kind Empty makes the graph ignore a tile entirely. The tile is still physically solid, but agents never plan to stand on it. 05_MovingPlatforms uses this for lava: enemies never path into it, and the demo player respawns when touching it. Use it for hazards (spikes, lava, water) so enemies do not walk into them.
Agents on slopes. While standing on a slope, NavAgent2D turns gravity off so the agent does not slide. Walking follows the slope’s surface. Agents also step over small lips, up to a quarter of a cell, such as seams between slope and flat tiles.
Demo: 04_Ladders
Rules:
MovementProfile has Can Climb Ladders (default on) and Climb Speed (default 3 cells per second). Profiles with climbing off simply have no climb links.LinkType.Climb links connect ladder cells to each other and to the ground at the exits.
Demo: 05_MovingPlatforms
Add GameObject > GTNav 2D > Moving Platform. It creates:
Rigidbody2D;BoxCollider2D;MovingPlatform2D.Set it up:
MovingPlatform2D in the scene (Auto Find Moving Platforms). You can also list platforms explicitly. Rebake after changing stops.How agents ride. Agents plan rides like any other link (LinkType.Ride). The cost includes the expected wait and the travel time, so they ride only when it is worth it. The agent:
Repaths requested while boarding, riding or getting off are applied after the ride. If the platform does not come within one full cycle, the agent replans.
Targets on a platform. When the destination is on a platform (for example a player riding it), the agent walks to the closest spot beside one of its stops, waits for it to dock, steps on and moves toward the target on board. If a ledge above a stop is quicker, it drops onto the docked platform instead (within the profile’s Max Fall Height), jumping only when the platform will still be there on landing. It rides along while the target stays on the platform. Once the target is elsewhere, at each dock it either gets off or rides on to a later stop, whichever reaches the target sooner; the same applies when the goal moves during a planned ride. An agent standing still on a platform (waiting, attacking, stunned) always moves with it.
Your own platform. Implement IMovingPlatform:
Then register it with NavGraph2D.AddMovingPlatform and rebake.
Demo: 06_Flying
Add GameObject > GTNav 2D > Flying Chaser. It creates:
Rigidbody2D;BoxCollider2D sized to the profile;FlyingAgent2D with a Flying Profile;FlyingChaser with Flyer Settings.FlyingAgent2D
INavAgent, so positions are feet, like ground agents. It also implements IFlyingAgent:
Dash(target, speed): a straight-line dash that ignores pathfinding;IsDashing;HasClearLine(from, to).FlyingProfile
| Field | Default | Description |
|---|---|---|
| flySpeed | 5 | Cells per second. |
| acceleration | 30 | Cells per second². |
| width / height | 0.8 / 0.8 | Body size in cells. |
| passThroughOneWay | on | Fly through one-way platforms. |
FlyingChaser works in four steps:
coverMode decides:
ApproachLow (default): tries lower and wider points, so the flyer comes in from the side.WaitNearby: hovers in the open near the cover (never resting on the roof) and dives as soon as the target comes out. FlyingChaser.IsWaiting is true meanwhile.It shares detection, patrol and give-up rules with the other behaviours.
| FlyerSettings field | Default | Description |
|---|---|---|
| hoverHeight | 3 | Height above the target’s feet. |
| hoverSideOffset | 2 | Horizontal offset of the hover point, on the flyer’s side. |
| coverMode | ApproachLow | What to do when terrain hides the target from the hover height: ApproachLow or WaitNearby. |
| hoverTolerance | 0.6 | How close to the hover point the dive may start. |
| diveWindup | 0.5 | Hover time before the dive. |
| diveSpeed | 12 | Dive speed (units per second). |
| diveOvershoot | 1 | How far past the target the dive continues. |
| hitRadius | 1 | Distance between body centers that counts as a hit. |
| recoverTime | 0.8 | Pause after a dive. |
Demo: 09_Ranged
Add GameObject > GTNav 2D > Ranged Shooter. It creates:
NavAgent2D;RangedShooter with Shooter Settings;Presets.RangedShooter works like this:
minRange–maxRange) from which a shot reaches the target, and walks, jumps, climbs or rides there.aimWindup seconds.fireCooldown.If the target comes closer than retreatDistance, it moves to a farther firing spot. If there is none, it fires from where it stands. It shares detection, patrol and give-up rules with the other behaviours.
Trajectories
projectileGravity, like a grenade or arrow. The launch velocity is solved with the same step-by-step model as jumps (Ballistics), so the projectile lands exactly where it was aimed. The shooter checks both the flat and the lobbed arc and uses one that clears the terrain, so it can throw over cover. The launch speed limits the range to about speed² / gravity.Every shot is checked against the terrain before firing (the projectile’s radius is swept along the path). One-way platforms do not block shots by default. With leadTarget on, the shooter aims where the target will be, based on its current velocity.
| ShooterSettings field | Default | Description |
|---|---|---|
| minRange / maxRange | 4 / 8 | Preferred distance band to the target. |
| retreatDistance | 3 | Back off when the target is closer than this. |
| muzzleHeight | 1 | Spawn height above the feet. A Muzzle transform on the shooter overrides it. |
| aimWindup | 0.5 | Aiming time before each shot. |
| fireCooldown | 1.2 | Pause after each shot. |
| trajectory | Straight | Straight or Arc. |
| projectileSpeed | 12 | Speed (units per second). For arcs, the maximum launch speed. |
| projectileGravity | 15 | Downward acceleration of arcs. |
| preferHighArc | off | Prefer the lobbed arc over the flat one. |
| projectileLifetime | 3 | Seconds before a projectile that hit nothing disappears. |
| leadTarget | off | Aim at the predicted position. |
Projectile2D is a simple, physics-free projectile:
AttackHit / On Attack Hit.radius, hitLayers, passThroughOneWay, rotateToVelocity.Impact for effects and RangedShooter.Fired for muzzle flashes or sounds.For your own visuals, use any prefab with a Projectile2D component.
Demo: 07_Combat (press J to attack)
| Member | Description |
|---|---|
NavAgent2D.ApplyKnockback(Vector2 velocity, float seconds) |
Sets the body’s velocity and stops steering for seconds. Also on FlyingAgent2D, which slows down by itself since it has no gravity. |
INavAgent.Suspend(float seconds = -1) / Resume() / IsSuspended |
Stop and resume steering. A negative duration suspends until Resume. The destination is kept. |
EnemyBehaviour2D.Stun(float seconds) |
Suspends the agent and enters EnemyState.Stunned. Afterwards the enemy resumes the chase if the target is in range, otherwise it returns to patrol. |
EnemyBehaviour2D.IsStunned |
True while stunned. |
A typical hit:
void OnHitEnemy(EnemyBehaviour2D enemy, int direction)
{
var agent = enemy.GetComponent<NavAgent2D>();
if (agent != null) agent.ApplyKnockback(new Vector2(direction * 9f, 5f), 0.25f);
enemy.Stun(1.2f);
}
There is no dedicated boss behaviour, because every boss is different. Build one from the existing parts:
GroundChaser and RangedShooter, and keep exactly one enabled at a time. They share the same NavAgent2D.Stun for a short pause, so the change is readable.using GTNav2D;
using UnityEngine;
public class TwoPhaseBoss : MonoBehaviour
{
public GroundChaser melee; // enabled at start
public RangedShooter ranged; // disabled at start
public ChaserSettings enragedSettings;
public MovementProfile enragedProfile;
bool enraged;
// Call this from your own health system.
public void OnHealthChanged(float fraction)
{
if (!enraged && fraction <= 0.5f)
{
enraged = true;
melee.ChaserSettings = enragedSettings;
GetComponent<NavAgent2D>().Profile = enragedProfile;
melee.Stun(1f); // short "roar" before phase two
}
}
// Example: alternate between melee and ranged every few seconds.
public void SwitchToRanged(bool useRanged)
{
melee.enabled = !useRanged;
ranged.enabled = useRanged;
}
}
Demo: 08_RuntimeBake
| Method | When to use it |
|---|---|
| Bake On Awake (default) | Bakes when the scene starts. Small and medium levels bake in milliseconds. |
| Bake In Background | Bakes at startup on a worker thread. Agents wait until it finishes. |
| Bake To Asset (graph Inspector) | Bakes in the editor and saves a NavGraphData asset next to the scene. It loads instantly at startup. If the tilemaps or profiles change, the Inspector warns that the asset is stale and the graph falls back to baking at runtime. |
NavGraph2D.Bake() |
Synchronous rebake from script. |
NavGraph2D.BakeAsync(Action onComplete) |
Rebakes without blocking. The tilemaps are read immediately and the work runs on a worker thread (spread over frames on WebGL). The old graph stays in use until the new one is swapped in. Agents repath automatically. IsBaking is true meanwhile. |
Moving platform ride links are always rebuilt at runtime, because they depend on where the platforms are.