Want more features? Check out the with advanced patrol ai with navmesh pathfinding, player detection with awareness meter, alert states, group coordination, and patrol schedules.
Part of these game systems:
beginner AI & Pathfinding

Waypoint Patrol AI

Enemy patrol between waypoints with configurable speed, wait times, and patrol patterns (loop, ping-pong, random).

Unity 2022.3+ · 2.3 KB · WaypointPatrol.cs

How to Use

1

Create empty GameObjects as waypoints, position them in the scene

2

Attach WaypointPatrol to your enemy

3

Drag waypoints into the array in inspector

4

Choose patrol pattern: Loop, PingPong, or Random

5

Adjust speed and wait time at each waypoint

6

Gizmos show patrol path in Scene view (select the enemy)

Source Code

WaypointPatrol.cs
C#
using UnityEngine;

/// <summary>
/// Moves an enemy between waypoints with configurable patterns.
/// Supports loop, ping-pong, and random patrol modes.
/// </summary>
public class WaypointPatrol : MonoBehaviour
{
    public enum PatrolMode { Loop, PingPong, Random }

    [Header("Waypoints")]
    [SerializeField] private Transform[] waypoints;

    [Header("Movement")]
    [SerializeField] private float moveSpeed = 3f;
    [SerializeField] private float rotationSpeed = 5f;
    [SerializeField] private float arrivalThreshold = 0.2f;

    [Header("Waiting")]
    [SerializeField] private float waitTime = 1f;

    [Header("Pattern")]
    [SerializeField] private PatrolMode patrolMode = PatrolMode.Loop;

    private int currentIndex;
    private int direction = 1;
    private float waitTimer;
    private bool isWaiting;

    private void Update()
    {
        if (waypoints == null || waypoints.Length == 0) return;

        if (isWaiting)
        {
            waitTimer -= Time.deltaTime;
            if (waitTimer <= 0f)
                isWaiting = false;
            return;
        }

        MoveToWaypoint();
    }

    private void MoveToWaypoint()
    {
        Transform target = waypoints[currentIndex];
        if (target == null) return;

        Vector3 targetPos = target.position;
        Vector3 direction3d = (targetPos - transform.position);
        direction3d.y = 0f; // Keep on same plane

        float distance = direction3d.magnitude;

        if (distance <= arrivalThreshold)
        {
            ArrivedAtWaypoint();
            return;
        }

        // Move
        Vector3 moveDir = direction3d.normalized;
        transform.position += moveDir * moveSpeed * Time.deltaTime;

        // Rotate towards movement direction
        if (moveDir != Vector3.zero)
        {
            Quaternion targetRotation = Quaternion.LookRotation(moveDir);
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
        }
    }

    private void ArrivedAtWaypoint()
    {
        isWaiting = true;
        waitTimer = waitTime;

        switch (patrolMode)
        {
            case PatrolMode.Loop:
                currentIndex = (currentIndex + 1) % waypoints.Length;
                break;

            case PatrolMode.PingPong:
                currentIndex += direction;
                if (currentIndex >= waypoints.Length - 1 || currentIndex <= 0)
                    direction *= -1;
                break;

            case PatrolMode.Random:
                int next;
                do { next = Random.Range(0, waypoints.Length); }
                while (next == currentIndex && waypoints.Length > 1);
                currentIndex = next;
                break;
        }
    }

    /// <summary>
    /// Pause patrol at current position.
    /// </summary>
    public void PausePatrol() => enabled = false;

    /// <summary>
    /// Resume patrol from current position.
    /// </summary>
    public void ResumePatrol() => enabled = true;

#if UNITY_EDITOR
    private void OnDrawGizmosSelected()
    {
        if (waypoints == null || waypoints.Length == 0) return;

        Gizmos.color = Color.cyan;
        for (int i = 0; i < waypoints.Length; i++)
        {
            if (waypoints[i] == null) continue;
            Gizmos.DrawWireSphere(waypoints[i].position, 0.3f);

            if (i < waypoints.Length - 1 && waypoints[i + 1] != null)
                Gizmos.DrawLine(waypoints[i].position, waypoints[i + 1].position);
        }

        // Close loop if in Loop mode
        if (patrolMode == PatrolMode.Loop && waypoints.Length > 1
            && waypoints[0] != null && waypoints[waypoints.Length - 1] != null)
        {
            Gizmos.DrawLine(waypoints[waypoints.Length - 1].position, waypoints[0].position);
        }
    }
#endif
}
Ready for more? Waypoint Patrol AI Pro Advanced patrol AI with NavMesh pathfinding, player detection with awareness meter, alert states, group coordination, and patrol schedules.