Heya!
At the moment I'm trying to optimize our game's enemy group-AI. The scenario is as follows:
![alt text][1]
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 ();
enemyHealth = GetComponent ();
nav = GetComponent ();
enemyHealth = GetComponent ();
anim = GetComponent ();
//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;
}
}
}
[1]: /storage/temp/42818-enemy-group-ai.png
↧