I have the following scenario (Diagram 1); the grey circles are AI agents and the green squares are trigger boxes. Diagram 2 is a zoomed in version of Diagram 1. Each trigger has the same tag, so an agent will look for the closest trigger to them and move towards it. When an agent’s transform reaches the center of the trigger they start to earn points, and after a random amount of time they move on.
When an agent has started to earn points I’d like to change the trigger’s tag to “occupied” so that other agents don’t try to move to this trigger, and instead look for the closest “vacant” one. The problem is the timing. I cannot change the tag OnTriggerEnter because the agent inside is still moving towards the center of the trigger, and therefore changing the tag would make it think the trigger is occupied and it would start looking for another trigger. But at the same time, not changing it allows other agents to continue to enter the trigger.
I have tried to change the tag during OnTriggerStay, as soon as the agent starts earning points. And when the agent leaves (OnTriggerExit), the tag is set back to vacant so that other agents can use it. The trouble here is that if there are multiple agents entering the trigger at around the same time, the trigger has no way of knowing the difference between them. For example, Agent 1 enters the trigger, but just before they reach the trigger’s center, Agent 2 enters the trigger. At this point there’s two agents in the trigger, but the trigger doesn’t know that. So Agent 1 could trigger OnTriggerEnter, while Agent 2 can then trigger OnTriggerStay, skipping OnTriggerEnter.
And that is the basis of the issue. I would like to be able to have OnTriggerEnter, Stay and Exit triggered by only one agent at a time. How could I do this?
Here is my script:
using UnityEngine;
using System.Collections;
public class AICover : MonoBehaviour {
public string enemyTag;
public string coverFreeTag;
public string coverNotFreeTag;
public string uniqueID;
private EnemyUniqueID enemyUniqueID;
public bool almostNotFree = false;
public Transform coverTransform;
private NavMeshAgent enemyNavMeshAgentScript;
private float enemyNavMeshAgentOrigRadius;
// Use this for initialization
void Start () {
coverTransform = transform;
coverFreeTag = coverTransform.gameObject.tag;
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter (Collider other) {
if (other.CompareTag (enemyTag)) {
enemyNavMeshAgentScript = other.GetComponent<NavMeshAgent> ();
enemyNavMeshAgentOrigRadius = enemyNavMeshAgentScript.radius;
enemyNavMeshAgentScript.radius = 0.0001f;
if (coverTransform.gameObject.tag == coverFreeTag && !almostNotFree) {
uniqueID = System.DateTime.Now.ToString ("ddMMyyyyHHmmss") + Random.Range (1, 1000).ToString ();
enemyUniqueID = other.GetComponent<EnemyUniqueID> ();
enemyUniqueID.enemyID = uniqueID;
almostNotFree = true;
}
}
}
void OnTriggerStay (Collider other) {
if (other.CompareTag (enemyTag) && coverTransform.gameObject.tag == coverFreeTag && almostNotFree && uniqueID == enemyUniqueID.enemyID) {
coverTransform.gameObject.tag = coverNotFreeTag;
}
}
void OnTriggerExit (Collider other) {
if (other.CompareTag(enemyTag)) {
enemyUniqueID = other.GetComponent<EnemyUniqueID>();
enemyNavMeshAgentScript.radius = enemyNavMeshAgentOrigRadius;
if (coverTransform.gameObject.tag == coverNotFreeTag && almostNotFree && uniqueID == enemyUniqueID.enemyID) {
coverTransform.gameObject.tag = coverFreeTag;
almostNotFree = false;
}
}
}
}