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