Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by ande92 · Mar 18, 2015 at 04:49 PM · aienemynavigationenemyaigroup

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:

alt text

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


group-ai-scenario.png (1.5 kB)
enemy-group-ai.png (1.8 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by ande92 · Mar 19, 2015 at 12:20 PM

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 [i].SendMessage ("ToArmsMen");
                         i++;
 
 
                     }
 
                 }

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

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by AlwaysSunny · Mar 18, 2015 at 03:31 PM

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.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ande92 · Mar 18, 2015 at 08:41 PM 0
Share

Thanks for the reply!

The Physics.CheckSphere() seems to be effective finding out different objects entering the sphere, but is there a way to ignore the gameobject that's calling it? Since I'm attaching the script - which calls the CheckSphere() - to the enemy, I don't need information that it found itself inside the sphere. (I guess it doesn't really matter in the end, but still...) I only need information if OTHER enemies are entering it. (I'm using a layer$$anonymous$$ask which only affects enemies though.)

Also, since I'm still new to C# and program$$anonymous$$g in general, I can't seem to find a way to actually detect other gameobject's combat status (=bool inCombat)? The actual bool is public so I can access it inside other scripts, but I have only 1 Enemy$$anonymous$$ovement-script that all the enemies share.

The main goal is still to do the following:

  1. If the enemy is out of combat, call Physics.CheckSphere()

  2. If the enemy detects another enemy inside the sphere WITH inCombat = true, change its inCombat to true.

So the actual detection of other gameobject's boolean status - while sharing the same script - seems to be difficult.

Any example code would be greatly appreciated!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Enemy Rigidbody Not Responding to Gravity 1 Answer

how can i make the enemy kill more players one after the other chasing them ??? thank you 0 Answers

Problem with the movement of AI 1 Answer

Why do the AI get caught on trees? 0 Answers

Enemy is not chasing player. it is escaping. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges