Your Cart
Loading
unity enemy patrol 3d unity3d enemy patrol unity how to make enemy patrol

Unity Enemy Patrol 3D Tutorial | Unity Tutorial

Unity Enemy Patrol 3D Tutorial | Unity Tutorial


In this Unity tutorial, we’ll walk you through creating a 3D enemy patrol system from scratch. Learn how to set up an enemy that follows waypoints, waits at specific points, and handles ground detection. We'll cover scripting with C# to control enemy movement, implement ground checks using LayerMasks, and refine patrol behavior to avoid common issues like jittering.



WATCH FULL TUTORIAL ON YOUTUBE



CHECK OUR PROJECTS


SUBSCRIBE FOR LATEST OFFERS



=========================================================


Unity Projects - ON SALE!!!


1. Water Sort Puzzle 9000 Levels

https://payhip.com/b/cjDb8


2. Ball Sort Puzzle 9000 Levels

https://payhip.com/b/IbtoD


3. Sling Shot

https://payhip.com/b/PjLDH


=========================================================



Scripts:


EnemyPatrol.cs


using UnityEngine;

using System.Collections;


public class EnemyPatrol : MonoBehaviour

{

  public Transform[] waypoints;     // Array of waypoints

  public float speed = 2f;       // Patrol speed

  public float waitTime = 2f;      // Time to wait at each waypoint

  public float groundCheckDistance = 0.2f; // Distance to check for ground

  public LayerMask groundLayer;     // Layer mask to specify ground layers


  private int currentWaypointIndex = 0;

  private Rigidbody rb;

  private bool isWaiting = false;

  private bool isGrounded;


  void Start()

  {

    rb = GetComponent<Rigidbody>();

    rb.freezeRotation = true; // Prevent rotation

    rb.useGravity = true;   // Enable gravity

    if (waypoints.Length > 0)

    {

      StartCoroutine(Patrol());

    }

  }


  void FixedUpdate()

  {

    // Check if the enemy is grounded using the LayerMask

    isGrounded = Physics.Raycast(transform.position, Vector3.down, groundCheckDistance, groundLayer);


    // Apply manual adjustment to prevent unrealistic behavior

    if (!isGrounded)

    {

      Vector3 adjustedVelocity = rb.velocity;

      adjustedVelocity.y = 0; // Prevent vertical movement

      rb.velocity = adjustedVelocity;

    }

  }


  private IEnumerator Patrol()

  {

    while (true) // Infinite loop for continuous patrolling

    {

      if (waypoints.Length == 0) yield break;


      Transform targetWaypoint = waypoints[currentWaypointIndex];

      Vector3 direction = (targetWaypoint.position - transform.position).normalized;


      // Move the enemy manually

      Vector3 movement = direction * speed * Time.fixedDeltaTime;

      rb.velocity = Vector3.zero; // Reset velocity before applying movement

      rb.MovePosition(rb.position + movement);


      // Check if we've reached the waypoint

      if (Vector3.Distance(transform.position, targetWaypoint.position) < 0.1f)

      {

        if (!isWaiting)

        {

          StartCoroutine(WaitAtWaypoint());

        }

      }


      yield return new WaitForFixedUpdate(); // Wait until the next FixedUpdate

    }

  }


  private IEnumerator WaitAtWaypoint()

  {

    isWaiting = true;

    yield return new WaitForSeconds(waitTime); // Wait for the specified time

    isWaiting = false;


    // Move to the next waypoint

    currentWaypointIndex = (currentWaypointIndex + 1) % waypoints.Length;

  }

}





DOWNLOAD CODESTER FILES