Gitou

Terrain and Enemy Features

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).


Slopes

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:

  1. Create it with Assets > Create > GTNav 2D > Nav Tile Types.
  2. Assign it to the graph’s Tile Types field.
  3. List the tile with the right kind.

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.


Ladders

Demo: 04_Ladders

  1. Create a Tilemap for ladders, for example named “Ladders”. It needs no collider.
  2. Paint ladder tiles on it.
  3. Assign it to the graph’s Ladder Tilemap field. GameObject > GTNav 2D > Nav Graph 2D does this automatically if a Tilemap’s name contains “ladder”.

Rules:

LinkType.Climb links connect ladder cells to each other and to the ground at the exits.


Moving platforms

Demo: 05_MovingPlatforms

Add GameObject > GTNav 2D > Moving Platform. It creates:

Set it up:

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:

  1. walks to the dock;
  2. waits for the platform;
  3. boards and rides;
  4. steps off at the planned stop.

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.


Flying enemies

Demo: 06_Flying

Add GameObject > GTNav 2D > Flying Chaser. It creates:

FlyingAgent2D

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:

  1. Flies to a hover point above and beside the target. The point must have a clear dive line to the target. When terrain blocks the view from above (for example a roof over the target), 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.
  2. Hovers for the wind-up.
  3. Dives in a straight line through the target’s position, slightly past it.
  4. Recovers and repeats.

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.

Ranged enemies

Demo: 09_Ranged

Add GameObject > GTNav 2D > Ranged Shooter. It creates:

RangedShooter works like this:

  1. Finds a standing spot within the preferred range (minRange–maxRange) from which a shot reaches the target, and walks, jumps, climbs or rides there.
  2. Aims for aimWindup seconds.
  3. Fires, then waits 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

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:

For your own visuals, use any prefab with a Projectile2D component.


Knockback and stun

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);
}

Bosses: combining behaviours

There is no dedicated boss behaviour, because every boss is different. Build one from the existing parts:

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;
    }
}

Baking: editor assets and runtime rebakes

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.