My enemy is not doing random patrol when there is no player/zombie in the range

I checked everything I could but I cant find what’s wrong.
here is the full code :-

using UnityEngine;
using UnityEngine.AI;
public class Enemy_Ai : MonoBehaviour
{
public NavMeshAgent navMeshAgent;
public float patrolRange = 100f;
public float attackRange = 4f;
public float bulletImpactForce = 10f;

private Transform closestZombie;
private Transform closestPlayer;
private bool hasTarget;
public float shootingInterval = 1f; // interval between shots in seconds
private float lastShotTime;
public float bulletSpeed = 50f;
public BulletOPM bulletP;

void Start()
{
    navMeshAgent.speed = 3.5f;
    navMeshAgent.stoppingDistance = 4.5f;
    patrolRange = 200.0f;
    attackRange = 25.0f;
    closestZombie = FindClosestZombie();
    closestPlayer = FindClosestPlayer();
    hasTarget = false;
}

void Update()
{
    closestZombie = FindClosestZombie();
    closestPlayer = FindClosestPlayer();
    if (navMeshAgent.enabled)
    {
        navMeshAgent.stoppingDistance = 7.0f;
        if (closestZombie != null || closestPlayer != null)
        {
            hasTarget = true;
            if (closestZombie != null && closestPlayer != null)
            {
                // Both a zombie and player are within range, choose the closest one
                if (Vector3.Distance(transform.position, closestZombie.position) < Vector3.Distance(transform.position, closestPlayer.position))
                {
                    if (Vector3.Distance(transform.position, closestZombie.position) <= attackRange)
                    {
                        navMeshAgent.SetDestination(closestZombie.position);
                        Attack(closestZombie);
                    }
                    else
                    {
                        hasTarget = false;
                    }
                }

                else
                {
                    if (closestPlayer != null)
                    {
                        if (Vector3.Distance(transform.position, closestPlayer.position) <= attackRange)
                        {
                            navMeshAgent.SetDestination(closestPlayer.position);
                            Attack(closestPlayer);
                        }
                        else
                        {
                            hasTarget = false;
                        }
                    }
                }
            }
            else if (closestZombie != null)
            {
                if (Vector3.Distance(transform.position, closestZombie.position) <= attackRange)
                {
                    navMeshAgent.SetDestination(closestZombie.position);
                    Attack(closestZombie);
                }
                else
                {
                    hasTarget = false;
                }
            }
            else
            {
                if (closestPlayer != null)
                {
                    if (Vector3.Distance(transform.position, closestPlayer.position) <= attackRange)
                    {
                        navMeshAgent.SetDestination(closestPlayer.position);
                        Attack(closestPlayer);
                    }
                    else
                    {
                        hasTarget = false;
                    }
                }
            }


        }
        else if (!hasTarget)
        {
            // Nobody around, go on a random patrol
            navMeshAgent.speed = 3.5f;
            Vector3 randomDirection = Random.insideUnitSphere * patrolRange;
            randomDirection += transform.position;
            NavMeshHit hit;
            NavMesh.SamplePosition(randomDirection, out hit, patrolRange, 1);
            Vector3 finalPosition = hit.position;
            navMeshAgent.SetDestination(finalPosition);
        }
    }
}

public void disableNMA()
{
    navMeshAgent.enabled = false;
}
private Transform FindClosestZombie()
{
    GameObject[] zombies = GameObject.FindGameObjectsWithTag("Zombie");
    float minDistance = Mathf.Infinity;
    Transform closest = null;
    foreach (GameObject zombie in zombies)
    {
        float distance = Vector3.Distance(transform.position, zombie.transform.position);
        if (distance < minDistance)
        {
            minDistance = distance;
            closest = zombie.transform;
        }
    }
    return closest;
}

private Transform FindClosestPlayer()
{
    GameObject[] players = GameObject.FindGameObjectsWithTag("Player");
    float minDistance = Mathf.Infinity;
    Transform closest = null;
    foreach (GameObject player in players)
    {
        float distance = Vector3.Distance(transform.position, player.transform.position);
        if (distance < minDistance)
        {
            minDistance = distance;
            closest = player.transform;
        }
    }
    return closest;
}
void Attack(Transform target)
{
    navMeshAgent.speed = 7.0f;

    if (Vector3.Distance(transform.position, navMeshAgent.destination) <= attackRange)
    {
        transform.LookAt(target);
        if (Time.time - lastShotTime > shootingInterval)
        {
            if (bulletP != null)
            {
                GameObject bullet = bulletP.GetPooledObject();

                bullet.transform.position = transform.position;
                bullet.transform.rotation = transform.rotation;
                bullet.SetActive(true);
                bullet.GetComponent<Rigidbody>().AddForce(bullet.transform.forward * bulletSpeed, ForceMode.Impulse);
                if (target.GetComponent<Rigidbody>() != null)
                {
                    target.GetComponent<Rigidbody>().AddForce(bullet.transform.forward * bulletImpactForce, ForceMode.Impulse);
                }
                lastShotTime = Time.time;
            }
        }
    }

}

}

Your code will never hit the else if (!hasTarget) part unless there are 0 zombies and 0 players in the scene. Your FindClosestZombie() and FindClosestPlayer() functions will always return something if they exist in the scene. This then means that your Update() code will enter the first if and therefore never hit the else if. You set hasTarget to false if the zombie or player is not within attack range but it doesn’t matter because the else if doesn’t get evaluated in this frame (because it is an else) and on the next update you would just enter the first if again because there will always be at least one player. Assuming of course that there is at least one player which - as far as I know - is the point of a game. Changing it to just an if (remove the else) may be what you want because the hasTarget = false that you set in the first if will get evaluated. However, your enemies will start changing directions every frame which is probably not going to be what you want

1 Like

Privacy & Terms