Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

AI Issue with one faction but not the other

Discussion in 'Scripting' started by RaGEn, Jul 25, 2017.

  1. RaGEn

    RaGEn

    Joined:
    Feb 3, 2015
    Posts:
    88
    Hello

    This question has got me stumped. One of my AI's will not attack the other AI. The Human soldier has troubles using raycasts to find his target.The game always says the enemy is behind a wall. But oddly enough if I make the Human soldier's faction into the Aliens and give them an alien health script they attack fine. I have everything on both the Aliens and Humans to ignore raycasts besides the their health.

    Also for another note this script works in another game where I created this script (hence why the health is called Russians and Americans). I am at my wits end, I can't figure out why this is happening. If anyone could be of any help. I'd be very grateful.

    I know it's silly I'm posting my whole script here, but I am so at a lost for this, I just so desperate for help. Please forgive me.

    Code (CSharp):
    1. public class RangedAI : MonoBehaviour {
    2.  
    3.     public GameObject Waypoint;
    4.  
    5.     public string EnemyFaction;
    6.     public string FriendlyFaction;
    7.     public GameObject Target;
    8.     public GameObject ClosestEnemy;
    9.     public bool Blocked;
    10.     UnityEngine.AI.NavMeshAgent agent;
    11.     public bool BehindWall;
    12.     private bool Attacking;
    13.     public float AttackTime =2f;
    14.     private AmericanHP americanhp;
    15.     private RussianHP russianhp;
    16.  
    17.  
    18.     public GameObject Barrel;
    19.  
    20.     public GameObject Bullet;
    21.  
    22.  
    23.     private bool Attackable;
    24.  
    25.  
    26.     public float ShootTime;
    27.     private float ShootTimeMin = 1f;
    28.     private float ShootTimeMax = 3f;
    29.  
    30.  
    31.     public bool ActiveDead;
    32.     private float Timer =3f;
    33.  
    34.     public float distance1;
    35.     public float distance2;
    36.  
    37.  
    38.     void Awake ()
    39.     {
    40.         agent = GetComponentInParent <UnityEngine.AI.NavMeshAgent> ();
    41.         ShootTime = Random.Range (ShootTimeMin, ShootTimeMax);
    42.  
    43.         if (EnemyFaction == ("Aliens"))
    44.             {
    45.         americanhp = GetComponentInChildren <AmericanHP> ();
    46.             }
    47.  
    48.         if (EnemyFaction == ("Humans"))
    49.                 {
    50.             russianhp = GetComponentInChildren <RussianHP> ();
    51.                 }
    52.     }
    53.  
    54.     GameObject FindClosestEnemy()
    55.     {
    56.         GameObject[] gos;
    57.         gos = GameObject.FindGameObjectsWithTag(EnemyFaction);
    58.         GameObject closest = null;
    59.         float distance = Mathf.Infinity;
    60.         Vector3 position = transform.position;
    61.  
    62.         foreach (GameObject go in gos)
    63.         {
    64.             Vector3 diff = go.transform.position - position;
    65.             float curDistance = diff.sqrMagnitude;
    66.             RaycastHit hit;
    67.             BehindWall = true;
    68.             if (go.transform.FindChild ("Marksmen") == true)
    69.             {
    70.                 Attackable = false;
    71.             }
    72.  
    73.             if (go.transform.FindChild ("Marksmen") == false)
    74.             {
    75.                 Attackable = true;
    76.             }
    77.             if (Physics.Raycast (transform.position, (go.transform.position - transform.position), out hit) && hit.collider.gameObject.tag == (EnemyFaction))
    78.             {
    79.                 BehindWall = false;
    80.  
    81.             }
    82.  
    83.             if (Physics.Raycast (transform.position, (go.transform.position - transform.position), out hit) && hit.collider.gameObject.tag == ("Wall"))
    84.             {
    85.                 BehindWall = true;
    86.             }
    87.             if (curDistance < distance && BehindWall == false && Attackable == true)
    88.             {
    89.                 closest = go;
    90.                 distance = curDistance;
    91.             }
    92.         }
    93.         return closest;
    94.     }
    95.  
    96.     void Update ()
    97.     {
    98.        
    99.         if (FriendlyFaction == ("Humans") && americanhp.Dead == true && ActiveDead == false)
    100.         {
    101.             ActiveDead = true;
    102.             gameObject.tag = ("Killed");
    103.             GetComponent<Animation> ().Play ("Death");
    104.             agent.Stop ();
    105.  
    106.         }
    107.  
    108.         if (FriendlyFaction == ("Aliens") && russianhp.Dead == true && ActiveDead == false)
    109.         {
    110.             ActiveDead = true;
    111.             gameObject.tag = ("Killed");
    112.             GetComponent<Animation> ().Play ("Death");
    113.             agent.Stop ();
    114.  
    115.         }
    116.         if (ActiveDead == false)
    117.         {
    118.         if (Target != null && Target.tag == ("Killed"))
    119.         {
    120.             Target = null;
    121.         }
    122.            
    123.  
    124.         if (Attacking == true && AttackTime == 2f)
    125.         {  
    126.             GetComponent<Animation> ().Stop ("Idle");    
    127.             GetComponent<Animation> ().Play ("Attack");
    128.         }
    129.  
    130.         if (Waypoint == null && Target == null)
    131.         {
    132.             GetComponent<Animation> ().Play ("Idle");
    133.             agent.Stop ();
    134.         }
    135.  
    136.         if (Target == null)
    137.         {
    138.             ClosestEnemy = FindClosestEnemy ();
    139.         }
    140.         if (Target == null && ClosestEnemy != null)
    141.         {
    142.             float dist = Vector3.Distance (ClosestEnemy.transform.position, transform.position);
    143.             if (dist <= 70)
    144.             {
    145.                 RaycastHit hit;
    146.                 if (Physics.Raycast (transform.position, (ClosestEnemy.transform.position - transform.position), out hit) && hit.collider.gameObject.tag != ("Wall"))
    147.                 {
    148.                     Target = ClosestEnemy;
    149.                 }
    150.  
    151.             }
    152.  
    153.             if (dist >= 71)
    154.             {
    155.                 Target = null;
    156.             }
    157.         }
    158.  
    159.         if (Target == null)
    160.         {
    161.             Target = null;
    162.         }
    163.  
    164.             if (Target != null)
    165.             {
    166.                 float dist = Vector3.Distance (ClosestEnemy.transform.position, transform.position);
    167.  
    168.                 if (dist >= 71)
    169.                 {
    170.                     Target = null;
    171.                 }
    172.             }
    173.  
    174.  
    175.             if (Target == null && Waypoint != null && Attacking == false)
    176.         {
    177.             agent.SetDestination (Waypoint.transform.position);
    178.             agent.Resume ();
    179.             if (Attacking == false)
    180.             {
    181.              GetComponent<Animation> ().Play ("Run");
    182.             }
    183.         }
    184.  
    185.  
    186.  
    187.         if (Target != null && Waypoint == null)
    188.         {
    189.             agent.SetDestination (Target.transform.position);
    190.             agent.Resume ();
    191.             if (Attacking == false)
    192.             {
    193.                 GetComponent<Animation> ().Play ("Run");
    194.             }
    195.         }
    196.  
    197.  
    198.  
    199.         if (Target != null && Blocked == true)
    200.         {
    201.             agent.SetDestination (Target.transform.position);
    202.             agent.Resume ();
    203.             if (Attacking == false)
    204.             {
    205.              GetComponent<Animation> ().Play ("Run");
    206.             }
    207.         }
    208.  
    209.  
    210.  
    211.    
    212.  
    213.         if (Target != null && Blocked == false)
    214.         {
    215.             float dist2 = Vector3.Distance (Target.transform.position, transform.position);
    216.                 if (dist2 <= distance1)
    217.             {
    218.                 agent.Stop ();
    219.                 if (Attacking == false)
    220.                 {
    221.                     GetComponent<Animation> ().Play ("Idle");
    222.                 }
    223.             }
    224.         }
    225.  
    226.         if (Target != null)
    227.         {
    228.  
    229.             RaycastHit hit;
    230.             if (Physics.Raycast (transform.position, (Target.transform.position - transform.position), out hit) && hit.collider.gameObject == (Target))
    231.             {
    232.                 Blocked = false;
    233.             }
    234.  
    235.             if (Physics.Raycast (transform.position, (Target.gameObject.transform.position - transform.position), out hit) && hit.collider.gameObject.tag == ("Wall"))
    236.             {
    237.                 Blocked = true;
    238.             }
    239.                    
    240.         }
    241.     }
    242.     }
    243.  
    244.  
    245.     void FixedUpdate ()
    246.     {
    247.         if (ActiveDead == false)
    248.         {
    249.  
    250.         if (Attacking == true)
    251.         {
    252.             AttackTime -= Time.deltaTime;
    253.         }
    254.  
    255.         if (AttackTime <= 0)
    256.         {
    257.             Attacking = false;
    258.             AttackTime = 2f;
    259.         }
    260.  
    261.         if (Target != null)
    262.         {
    263.             float dist3 = Vector3.Distance (Target.transform.position, transform.position);
    264.                 if (dist3 <= distance2)
    265.             {
    266.  
    267.                     if (Target != null && Blocked == false && Attacking == false)
    268.                     {
    269.                     ShootTime -= Time.deltaTime;
    270.                     transform.LookAt(new Vector3(Target.transform.position.x, transform.position.y, Target.transform.position.z));
    271.                 }
    272.  
    273.                     if (Target != null && Waypoint == null && dist3 >=distance2)
    274.                     {
    275.                         agent.SetDestination (Target.transform.position);
    276.                         agent.Resume ();
    277.                             GetComponent<Animation> ().Play ("Run");
    278.                         if (Attacking == false)
    279.                         {
    280.                             GetComponent<Animation> ().Play ("Run");
    281.                         }
    282.                     }
    283.  
    284.  
    285.                 if (ShootTime <= 0)
    286.                     {
    287.  
    288.                         Attacking = true;
    289.                         Instantiate (Bullet, Barrel.transform.position, Barrel.transform.rotation);
    290.                         ShootTime = Random.Range (ShootTimeMin, ShootTimeMax);
    291.                         }
    292.    
    293.            
    294.                 }
    295.             }
    296.         }
    297.     }
    298.  
    299.     void OnTriggerEnter (Collider other)
    300.     {
    301.         if (ActiveDead == false)
    302.         {
    303.             if (other.gameObject == Waypoint) {
    304.                 Waypoint = null;
    305.                 agent.Stop ();
    306.                 GetComponent<Animation> ().Play ("Idle");
    307.             }
    308.         }
    309.     }
    310.  
    311. }
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,848
    You need to break line 146 into multiple lines, and use Debug.Log to print out every detail you can think of until you can see what's going on.

    Include the position and direction of the ray cast, the name of the object hit, and its tag... that should make it pretty obvious (if indeed the problem is that it's seeing a wall where you don't think it should).

    There are all sorts of performance problems with this script, which I'm resisting the urge to talk about because your first priority is to make it work at all. ;) And it may well be that in your game, the performance is good enough. But feel free to post back if you ever want to make it faster!
     
  3. RaGEn

    RaGEn

    Joined:
    Feb 3, 2015
    Posts:
    88
    Thanks for the reply! By all means you can tell me about the problems. I look at every project as a chance to learn and to improve. I'd love anything you could tell me!
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,848
    Well, the big one is that on every frame, you're calling GameObject.FindGameObjectsWithTag(). That has to search every object in the scene, comparing tags, to build up a list of objects to return. And every object with this script attached is doing it all over again. So if you have dozens of agents, you're searching the entire scene hierarchy, building a list, and tearing it down dozens of times per frame. Ouch!

    So, much better would be to have some global (or class static) List that each object throws itself on. There is just one such list (because it's global/static), and it never gets built or torn down; it just exists for the life of the scene, and objects update it as they are born or destroyed. Then your FindClosestEnemy code can simply iterate over this list.

    The other, much smaller, issue I noticed was that you're calling GetComponent<Animation> all over the place. Every time you call that, Unity has to search all the components on this object, looking for one of type Animation. That's fairly quick, but it'd certainly be faster if you just called this once in Awake and saved it, like you're already doing for agent, americanhp, and russianhp.
     
  5. RaGEn

    RaGEn

    Joined:
    Feb 3, 2015
    Posts:
    88
    Thanks for the tips! I'll make those changes. Also I found the problem, the raycast from the human is going off in a random direction instead of going for their target. I just need to fix out how to fix that now.
     
    JoeStrout likes this.
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,848
    Awesome sauce. I love your growth mindset! Good luck with your game!
     
    RaGEn likes this.