How to detect - as an enemy - if a fellow enemy next to you is in combat with the player?

Heya!
At the moment I’m trying to optimize our game’s enemy group-AI. The scenario is as follows:

42818-enemy-group-ai.png

The goal as a player is to pull an enemy from the group with a gun, and hope that the other enemies are smart enough to follow the enemy’s lead, except the most northern enemy.

The game uses Unity’s native navigation system, so as soon as the enemy takes damage (refers to the gameobject’s Health-script), the enemy’s boolean “inCombat” turns true and sets its destination towards the player (NavMeshAgent.SetDestination()).

I’ve tried to calculate each enemy’s distance from each other with Vector3.Distance().
So far they are able to find each other’s distance as a float in the world, but I’m still trying to find a way to figure out how the enemies could detect each other’s inCombat-status.

TLDR: So far I’m able to pull one enemy at the time. I want the enemy to be able to detect if a close-by enemy is in combat. If it is, set inCombat to true and set destination towards the player. Question: How to do that?

public class EnemyMovement : MonoBehaviour
	{

		Transform player;               	// Reference to the player's position.
		PlayerHealth playerHealth;    	  // Reference to the player's health.
		EnemyHealth enemyHealth;        // Reference to this enemy's health.
		NavMeshAgent nav;               // Reference to the nav mesh agent.
		float speed = 5f;					// speed-variable used for rotating the enemy's rotation when close to the player
		Animator anim;					// Reference to the Animator.
		Vector3 enemyInitialPos;		// Enemy's initial position. Used for calculating enemy's max fighting distance (=How far can the enemy walk from its initial position, until it goes out of combat?)
		float maxEnemyFightingRadius = 20f; //Enemy's maximum fighting distance, until out of combat.
		float enemyFightingRadius;		//Enemy's current fighting radius from its initial position.
		Transform enemy; // used for calculating enemy's position.

		public bool inCombat;		//handles enemy's falling in and out of combat
		public float aggroRange = 7f;	//enemy's aggro range.

		void Awake ()
		{
			// Set up the references.
			player = GameObject.FindGameObjectWithTag ("Player").transform;
			enemy = GameObject.FindGameObjectWithTag("Enemy").transform;

			playerHealth = player.GetComponent <PlayerHealth> ();
			enemyHealth = GetComponent <EnemyHealth> ();
			nav = GetComponent <NavMeshAgent> ();
			enemyHealth = GetComponent<EnemyHealth> ();
			anim = GetComponent <Animator> ();

			//enemy's position right now
			enemyInitialPos = transform.position;

		}

		void Start ()
		{
			inCombat = false;
			nav.speed = 3;
			nav.stoppingDistance = 2f;
		}

		void Update ()
		{
			//calculates enemy's distance from another enemy
			float enemyDistance = Vector3.Distance(enemy.position, enemyInitialPos);
			Debug.Log (enemyDistance);

			//calculates enemy's distance from its initial position to where it's right now
			enemyFightingRadius = Vector3.Distance (transform.position, enemyInitialPos);

			//variables for rotating the enemy towards the player, when close
			float distance = Vector3.Distance (player.transform.position, transform.position);
			Quaternion targetRotation = Quaternion.LookRotation (player.transform.position - transform.position);

			//Just a way to rotate the enemy's rotation towards the player, when the player gets close to the enemy, since the NavMeshAgent rotates too slow.
			if (distance < 2.5f && enemyHealth.currentHealth > 0) {
				transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, speed * Time.deltaTime);
			}

			//-----------ENEMY'S MOVEMENT TOWARDS THE PLAYER----------
			// If the enemy and the player have health left...
			if (enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0) {

				// ... set the destination of the nav mesh agent to the player.

				//If the player goes too close to the enemy, the enemy becomes angry.
				if (distance < aggroRange && inCombat == false) { 
					inCombat = true;
				}

				//If a nearby enemy is in combat, set inCombat to true and set its destination towards the player.
//				if (enemyDistance < 6f/* && ...*/) { //obviously just checking the enemyDistance won't work, since a tightly grouped pack will go to combat instantaneously, and that's not what we want.
//					inCombat = true;
//				}

				//Handles the animator-state
				if (inCombat) {
					anim.SetBool ("inCombat", true); //Running animation
				} else if (inCombat == false) {
					anim.SetBool ("inCombat", false); //Idle animation
				} 
			
				//Handles the agent's movement towards the player
				if (inCombat) {
					nav.SetDestination (player.position);
				} 
				if (enemyFightingRadius > maxEnemyFightingRadius) {
					nav.Stop ();
					enemyInitialPos = transform.position; // Recalculates the enemy's initial position.
					inCombat = false;
				} 
				if (inCombat == true) {
					nav.Resume ();
				}

			}
			// Otherwise...
			else {
				// ... disable the nav mesh agent.
				nav.enabled = false;
			}
		}


	}

The common way to go about this involves managerial oversight. When I first encountered the need for “group” decisions, I wanted a script which could respond to “events” involving two or more agents. This wound up being a flexible system that worked pretty well. I could ensure only X enemies ever engaged the player simultaneously, for instance, or get enemies to work in concert.

In your scenario, this might be overkill. You might be able to get away with having a “sensor” trigger on your agents (or a call to Physics.CheckSphere). A script on the agent polls the sensor to detect the status of nearby agents and react accordingly.

I found a relatively viable solution. I use Physics.OverlapSphere() on the enemy while it’s in combat, went through the array with while-loop, and initiated a “War Shout-like”-method on each enemy detected, which in turn put a nearby outOfCombat-enemy IN combat.

if (inCombat && enemyFightingRadius < maxEnemyFightingRadius) { // "enemyFightingRadius < maxEnemyFightingRadius" is essentially the enemy's max fighting range it can travel to, until returning to its initial position
					Collider[] enemies = Physics.OverlapSphere (transform.position, shoutRadius, enemyMask);
					
					int i = 0;
					
					while (i < enemies.Length) {
					
						enemies *.SendMessage ("ToArmsMen");*
  •  				i++;*
    
  •  			}*
    
  •  		}*
    

The ToArmsMen() is just a method containing a “inCombat = true” variable.