Search code examples
c#unity-game-enginenullreferenceexceptionqvector3d

Vector3 is being reset to 0,0,0 Unity


I'm making a game right now where the enemies become alerted to the player and chase them indefinetely until the player stand on a "safe plate" in game. When the player stands here the enemies should then return to their original position.

The issue is that whenever the player stands on the plate I get a null reference exception error and I can see the original guard position has been reset to 0,0,0 in the console. I'm assuming the reason for the null reference exception is because the world origin isn't on the nav mesh I'm using, although I could easily be wrong about that. I just can't seem to figure out why the vector3 value has changed at all since the guardPosition variable is initiated on Start and never touched again.

I've included both my enemyAi class (script attached to enemy) and my class associated with stepping on plates. If there's anything more needed to include let me know. If anyone has any ideas, help would be appreciated. Cheers.

Screenshot on console after stepping on plate

public class EnemyAI : MonoBehaviour
{
    
    DeathHandler dh;

    [SerializeField] Transform target;
    [SerializeField] float chaseRange = 5f;
    [SerializeField] float killRange = 2f;

    [SerializeField] GameObject explosionEffect;

    NavMeshAgent navMeshAgent;
    float distanceToTarget = Mathf.Infinity;
    bool isDead = false;
    bool isAlert = false;

    Vector3 guardPosition;

    void Start()
    {
        GameObject gob;
        gob = GameObject.Find("Player");
        dh = gob.GetComponent<DeathHandler>();

        guardPosition = transform.position;

        navMeshAgent = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        distanceToTarget = Vector3.Distance(target.position, transform.position);

        print(guardPosition + " guard position during update");

        //alert a dude
        if (distanceToTarget <= chaseRange && !isDead)
        {
            isAlert = true;
        }

        //chase a dude
        if (isAlert == true)
        {
            ChasePlayer();
            print(isAlert);
        }
    }

    public void ChasePlayer()
    {
        navMeshAgent.SetDestination(target.position);

        //explode a dude
        if (distanceToTarget <= killRange)
        {
            Explode();
            dh.KillPlayer();
        }
    }

    public void SetAlertStatus(bool status)
    {
        isAlert = status;
    }

    public void ReturnToPost()
    {
        //isAlert = false;
        print(guardPosition + " guard position after stepping on plate");
        navMeshAgent.SetDestination(guardPosition);
    }    

    void Explode()
    {
        Instantiate(explosionEffect, transform.position, transform.rotation);

        isDead = true;
        Destroy(gameObject);
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, chaseRange);
    }
}
public class SafeSpots : MonoBehaviour
{
    
EnemyAI enemyAi;

    

    void Start()
    {
        GameObject gob;
        gob = GameObject.FindGameObjectWithTag("Enemy");
        enemyAi = gob.GetComponent<EnemyAI>();
    }

    public void OnTriggerStay(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
            

            enemyAi.SetAlertStatus(false);
            enemyAi.ReturnToPost();
        }
    }
}

Solution

  • You are getting a disabled instance of EnemyAI. Instead, use FindGameObjectsWithTag then iterate through all of them and add their EnemyAI to a list which you can iterate through when necessary. By the way, it's better to use CompareTag when possible to reduce garbage:

    public class SafeSpots : MonoBehaviour
    {
        
        List<EnemyAI> enemyAis;
    
        void Start()
        {
            GameObject[] enemies= GameObject.FindGameObjectsWithTag("Enemy");
            enemyAis = new List<EnemyAI>();
           
            foreach (GameObject enemy in enemies)
            {
                enemyAis.Add(enemy.GetComponent<EnemyAI>());
            }
        }
    
        public void OnTriggerStay(Collider other)
        {
            if (other.CompareTag("Player"))
            {
                foreach(EnemyAI enemyAi in enemyAis)
                {
                    enemyAi.SetAlertStatus(false);
                    enemyAi.ReturnToPost();
                }
            }
        }
    }