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 Voridian · Jul 22, 2014 at 04:47 AM · c#collidertriggerai

Problems when i have multiple enemies on the same scene C#

This might be a complex one but i have a basic AI script i have written that can "Hear" the player using colliders, the script works fine except when there are multiple enemies at once. When one of them hears the player, they all do. Here is the complete EnemyAI script:

 using UnityEngine;
 using System.Collections;
 
 public class EnemyAi : MonoBehaviour {
 
     Transform target; //the enemy's target
     float moveSpeed = 2; //move speed
     float minDist = 0.9f;
     float maxDistance = 5;
     float rotationSpeed = 3; //speed of turning
     bool canHear = false;
     float attackDistance = 1;
     bool canAttack = true;
     Transform player;
     float hearRange = 20;
     public bool couldHearGun = false;
     
     Transform myTransform; //current transform data of this enemy
 
     // Use this for initialization
     void Start () {
         target = GameObject.FindWithTag("PlayerCenter").transform; //target the player
     }
     void Awake()
     {
         myTransform = transform; //cache transform data for easy access/preformance
     }
     // Update is called once per frame
     void Update () {
         player = GameObject.Find("Player").transform;
         if(Vector3.Distance(transform.position, player.position) <= hearRange && couldHearGun){
             Debug.Log("hear the gun");
             canHear = true;
             StartCoroutine(HearPlayer(10));
         }
 
         GameObject Player = GameObject.Find("Player");
         CharacterControler characterControler = Player.GetComponent<CharacterControler>();
         if(characterControler.couldHear && characterControler.makesSound){
             canHear = true;
         }
         if(canHear){
             StartCoroutine(HearPlayer(10));
         }
         
         //rotate to look at the player
         if(Vector3.Distance(transform.position, target.position) <= maxDistance || canHear){
         myTransform.rotation = Quaternion.Slerp(myTransform.rotation, Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
         }
 
         //move towards the player
         if(Vector3.Distance(transform.position, target.position) <= maxDistance || canHear){
             if(Vector3.Distance(transform.position, target.position) >= minDist){ 
         myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
         }
         }
         if(Vector3.Distance(transform.position, target.position) <= attackDistance && canAttack){
             characterControler.health -= 0.15f;
             canAttack = false;
             characterControler.health -= 0.15f;
             StartCoroutine(attackCooldown(1));
         }
     }
     public IEnumerator HearPlayer(float delay){
         yield return new WaitForSeconds(delay);
         canHear = false;
     }
     public IEnumerator attackCooldown (float delay){
         yield return new WaitForSeconds(delay);
         canAttack = true;
     }
 }
 

and here is the complete gun script which makes the sound:

 using UnityEngine;
 using System.Collections;
 
 public class PistolRay : MonoBehaviour {
 
     bool canFire = true;
     public GameObject decal;
     public float clipAmmo = 8;
     public float storedAmmo = 80;
     float missingShots = 0;
     GameObject player;
     GameObject characterControler;
     bool reloading = false;
 
     // Use this for initialization
     void Start () {
     }
     
     // Update is called once per frame
     void Update () {
         player = GameObject.Find("Player");
         CharacterControler characterControler = player.GetComponent<CharacterControler>();
         characterControler.ammoCount = clipAmmo;
         characterControler.totalAmmo = storedAmmo;
 
         RaycastHit hit;
         Ray shooterRay = new Ray(transform.position, transform.forward);
 
         if(Input.GetButton("Fire1") && canFire && clipAmmo > 0){
             if(GameObject.Find ("EnemyAi") != null){
                 GameObject enemy = GameObject.Find("EnemyAi");
                 Debug.Log("Test");
             EnemyAi enemyAi = enemy.GetComponent<EnemyAi>();
             enemyAi.couldHearGun = true;
             StartCoroutine (SoundCooldown(1));
             }
         }
 
         if(Input.GetButton("Fire1") && canFire && clipAmmo > 0){
             Debug.DrawRay (transform.position, transform.forward, Color.green);
                 if(Physics.Raycast(shooterRay, out hit, Mathf.Infinity)){
                 if(hit.collider.tag == "Enemy"){
                     hit.transform.GetComponent<EnemyCC>().health -= 15;
                 }
             }
             var hitRotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
             Instantiate(decal, hit.point, hitRotation);    
             //GameObject decalInstance = 
             //decal.transform.parent = hit.transform;
             canFire = false;
             clipAmmo -= 1;
             missingShots += 1;
             StartCoroutine(FireRate(1));
             }
         if(Input.GetButtonDown("Fire1") && canFire && clipAmmo == 0 && !reloading){
             reloading = true;
             StartCoroutine(ReloadTime(3));
         }
 
         if(Input.GetButtonDown("Reload") && storedAmmo != 8 && !reloading){
             reloading = true;
             StartCoroutine(ReloadTime(3));
         }
         }
     public IEnumerator FireRate (float delay){
         yield return new WaitForSeconds(delay);
         canFire = true;
     }
     public IEnumerator SoundCooldown(float delay){
         GameObject enemy = GameObject.Find("EnemyAI");
         EnemyAi enemyAi = enemy.GetComponent<EnemyAi>();
         yield return new WaitForSeconds(delay);
         enemyAi.couldHearGun = false;
 
     }
     public IEnumerator ReloadTime (float delay){
         yield return new WaitForSeconds(delay);
         reloading = false;
         if(storedAmmo >= 8){
             storedAmmo -= missingShots;
             clipAmmo += missingShots;
             missingShots = 0;
         }
     }
 }


there is also a character controller script which does a similar thing but its a long script and very messy but i can post if needed.

thanks for any help

Comment
Add comment · Show 1
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 Kiwasi · Jul 22, 2014 at 05:38 AM 0
Share

There are a thousand and one inefficiencies in this code that you probably want to deal with.

  • Caching your own transform does nothing for performance

  • Don't call Find every frame, call it once during start and store the result. Same with GetComponent

  • You call the HearPlayer coroutine every frame. This has the potential to start hundreds of coroutines that all do the same thing. A better option would be to start the coroutine in the set method of canHear.

  • You calculate distance for a comparison every frame. Use Vector3.sqr$$anonymous$$agnitude ins$$anonymous$$d

That's just a few places to start. I would strongly suggest using events for this structure ins$$anonymous$$d.

1 Reply

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

Answer by Kiwasi · Jul 22, 2014 at 05:28 AM

As I see it you problem could be on line 39. Hear you check a couple of values on the characterController, then set canHear to true. canHear will be set true on every frame that the characterController makes a sound.

To fix this simply add the distance check to line 39.

Comment
Add comment · Show 6 · 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 Voridian · Jul 22, 2014 at 05:36 AM 0
Share

thanks for the reply, i assume you mean change it to:

         if(Vector3.Distance(transform.position, target.position) <= hearRange){
         if(characterControler.couldHear && characterControler.makesSound){
             canHear = true;
         }
         }

which has the effect of only one of the enemies hearing the gunshot sound. i think its to do with the Gameobject.find only finding and storing the first target (PistolRay line 31: GameObject enemy = GameObject.Find("EnemyAi");) but i am not to sure

avatar image Kiwasi · Jul 22, 2014 at 05:41 AM 0
Share

That is correct. GameObject.Find returns the first object Unity finds. You could make a List of Enemies and use foreach. But events will ultimately be better.

avatar image Voridian · Jul 22, 2014 at 06:17 AM 0
Share

i have had no experience with lists and i dont quite understand the tutorials i was just watching, would you $$anonymous$$d explaining how i would make it work?

avatar image Kiwasi · Jul 22, 2014 at 06:42 AM 0
Share

Lists are pretty easy. They function the same as arrays, but are sized dynamically. Some important pseudo code follows.

 // This line tells C# you want to use Lists
 using system.collections.generic;
 
 // Declare and initialise a List like so
 private List<EnemyAI> enimies = new List<EnemyAI>();
 
 // Call the add method to add a new item
 enimies.add(enemyAI);
 
 // Use foreach to do something to every item
 foreach(EnemyAI enemy in enimies){
     enemy.couldHearGun = false;
     // Any other code that needs to apply to each enemy goes in here
 }

avatar image Voridian · Jul 22, 2014 at 06:50 AM 0
Share

was that all supposed to go in Update? aside from: using system.collections.generic;

il keep fiddling with it but having the rest in update causes a ton of errors

EDIT: ok i forgot to declare it properly Derp... well now i got that done the only error i get is: enemies.add(EnemyAi); 'system.collections.generic.list' does not contain a definition for 'add'

EDIT EDIT: OH typo in your script. its Add with a capitol. now i just have another error saying that enemies.Add(EnemyAi); 'EnemyAi is a type but used like a variable'

Show more comments

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

23 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Detecting inside an area without a collider 1 Answer

Work around for onTriggerStay? 1 Answer

Guides or Tutorials for a Very Basic Enemy AI? [Unity 5] 1 Answer

Select collider for GetComponent? 1 Answer

Unity Pro Navigation AI c# animations and stopping? 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