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

How to skip over enemies in an array, if(condition)

Discussion in 'Scripting' started by CrisisSystem, Oct 21, 2015.

  1. CrisisSystem

    CrisisSystem

    Joined:
    Oct 7, 2015
    Posts:
    124
    Hey guys, can I poke your brain for a sec? This is my player control script that I am working on, and currently it works to where I can target and kill enemies, but I am trying to remove them from being targetable (not destroy the gameobject) once they are dead (I have a bool in the EnemyAI class that I set: IsDead) which I am setting in the Fixed Update of this script. Anyways, I have tried about 15 different ways which are all obviously wrong.. but the closest I can get it is to have it skip over an enemy in the Enemies[] array, but I can't make it look access it's IsDead variable.

    What I'm really asking here, is in AddAllEnemies() or TargetEnemy() how do I make write this? Be gentle, I'm new. Been following BurgZerg's tutorial and have learned a lot but am now branching out.



    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class PlayerControls : MonoBehaviour {
    7.  
    8.     /*MOVEMENT*/
    9.     public float speed = 3f;                        //Walk speed
    10.     public float runSpeed = 5f;                        //Run speed
    11.     public float turnSpeed = 30f;                    //Turn speed
    12.     private Vector3 movement;
    13.  
    14.     /*TARGETTING*/
    15.     public List<Transform> targets;
    16.     public Transform selectedTarget;    
    17.     public GameObject target;
    18.     public float attackTimer;
    19.     public float coolDown;
    20.     public bool targetDead = false;
    21.     private GameObject[] Enemies;
    22.  
    23.  
    24.     /*SOUNDS*/
    25.     public AudioClip Shotgun;                        //the sound file for shotgun shoost
    26.     new AudioSource audio;                            //required for setting up audio
    27.  
    28.     private Animator anim;
    29.     private Rigidbody playerRigidbody;
    30.     private Transform myTransform;
    31.  
    32.  
    33.     void Awake(){
    34.         anim = GetComponent<Animator> ();
    35.         playerRigidbody = GetComponent<Rigidbody> ();
    36.         myTransform = transform;                                    //caches transform since we're using it a lot
    37.      
    38.     }
    39.  
    40.  
    41.     void Start(){
    42.         targets = new List<Transform> ();
    43.         AddAllEnemies ();                  
    44.         selectedTarget = null;
    45.         attackTimer = 0;
    46.         coolDown = 1.0f;
    47.         audio = GetComponent<AudioSource> ();          
    48.     }
    49.  
    50.  
    51.  
    52.     // Update is called once per frame
    53.     void Update () {
    54.      
    55.         //If you press K, target nearest enemy
    56.         if (Input.GetKeyDown (KeyCode.K)) {
    57.             TargetEnemy();
    58.         }
    59.  
    60.  
    61.         //If you press U, try to access a container if close enough.
    62.         if (Input.GetKeyDown (KeyCode.U)) {
    63.             Messenger.Invoke("LookForContainer");
    64.         }
    65.      
    66.         //If you press I, toggle inventory window
    67.         if (Input.GetKeyDown (KeyCode.I)) {
    68.             Messenger.Invoke("ToggleInventoryWindow");
    69.         }
    70.  
    71.         if (attackTimer > 0)
    72.             attackTimer -= Time.deltaTime;
    73.      
    74.         if (attackTimer < 0)
    75.             attackTimer = 0;
    76.      
    77.      
    78.         if (Input.GetKeyUp (KeyCode.J)) {
    79.             if(attackTimer == 0) {
    80.                 Attack();
    81.                 attackTimer = coolDown;
    82.  
    83.             }
    84.         }
    85.  
    86.  
    87.     }
    88.  
    89.  
    90.  
    91.     void FixedUpdate(){                //This fires every physics update
    92.  
    93.         //If a target is selected, get status of mob's isDead bool
    94. //        if (selectedTarget != null)
    95. //        targetDead = selectedTarget.GetComponent<EnemyAI> ().isDead;
    96.  
    97.         //if target is dead, deselect it and kill it
    98.         if (targetDead) {
    99.             Debug.Log ("Killed A Mob");
    100.             selectedTarget.GetComponent<EnemyAI>().isDead = true;
    101.             selectedTarget.GetComponent<EnemyAI>().KillMe();
    102.  
    103.             DeselectTarget();
    104.  
    105.  
    106.         }
    107.  
    108.         float h = Input.GetAxisRaw ("Horizontal");                        //Raw means it will only return -1, 0, or 1. (so no speed up to go) - Horizontal maps from < or > or A or D
    109.         float v = Input.GetAxisRaw ("Vertical");                        //Maps from up dwn w s
    110.  
    111.         Move (h, v);
    112.         Turning (h);
    113.         Animating (h, v);
    114.  
    115.  
    116.     }
    117.  
    118.  
    119.  
    120.  
    121.  
    122.  
    123.  
    124.  
    125.  
    126.  
    127.  
    128.     void Move(float h, float v){
    129.  
    130.         if (v == -1) {
    131.             myTransform.position -= transform.forward * speed * Time.deltaTime;
    132.         }
    133.      
    134.         if (v == 1) {
    135.             myTransform.position += transform.forward * speed * Time.deltaTime;
    136.         }
    137.  
    138.     }
    139.  
    140.  
    141.     void Turning(float h){
    142.  
    143.         if (h == -1) {
    144.             myTransform.Rotate(-Vector3.up * turnSpeed * Time.deltaTime);
    145.         }
    146.      
    147.         if (h == 1) {
    148.             myTransform.Rotate (Vector3.up * turnSpeed * Time.deltaTime);
    149.         }
    150.  
    151.     }
    152.  
    153.  
    154.     void Animating(float h, float v){
    155. //        bool walking = h != 0f || v != 0f;
    156.         bool walking = v != 0f;
    157.         anim.SetBool ("IsWalking", walking);
    158.  
    159.  
    160.  
    161.  
    162.     }
    163.  
    164.  
    165.     public void AddAllEnemies() {
    166.         //New array called 'Enemies', and fill it with things tagged as Enemy
    167.         Enemies = GameObject.FindGameObjectsWithTag ("Enemy");
    168.      
    169.         //For each loop, create game object called enemy in array 'Enemies'
    170.         //gotta somehow skip by dead enemies
    171.         foreach (GameObject enemy in Enemies)
    172.             AddTarget (enemy.transform);
    173.  
    174.  
    175.  
    176.     }
    177.  
    178.  
    179.     public void AddTarget(Transform enemy)
    180.     {
    181.         targets.Add (enemy);
    182.     }
    183.  
    184.  
    185.     private void SortTargetsByDistance(){
    186.         targets.Sort (delegate(Transform t1, Transform t2) {
    187.             //gets distance and returns a float of how far away
    188.             return (Vector3.Distance (t1.position, myTransform.position).CompareTo (Vector3.Distance (t2.position, myTransform.position)));
    189.         });
    190.     }
    191.  
    192.  
    193.     private void TargetEnemy(){
    194.         if (targets.Count == 0)
    195.             AddAllEnemies ();
    196.      
    197.         if (targets.Count > 0) {
    198.             if (selectedTarget == null) {
    199.                 SortTargetsByDistance ();
    200.                 selectedTarget = targets [0];
    201.  
    202.             } else {
    203.  
    204.                 int index = targets.IndexOf (selectedTarget);            //gives index of selected target and it's relationship to where it is in our list (what?)
    205.  
    206.                 if(index < targets.Count - 1) {
    207.                     index++;
    208.                 } else {
    209.                     index = 0;
    210.                 }
    211.              
    212.                 DeselectTarget();
    213.                 selectedTarget = targets[index];
    214.  
    215.  
    216.             }
    217.          
    218.             SelectTarget();
    219.  
    220.         }
    221.     }
    222.  
    223.  
    224.     private void SelectTarget()
    225.     {
    226.         //        Transform name = selectedTarget.FindChild("Name");                                //Seek out a better solution than FindChild if we use this, FIND's tend to be costly
    227.         Transform isSelected = selectedTarget.FindChild ("TargetSelected");                        //Find the TargetSelected arrow mesh
    228.      
    229.      
    230.         //        if (name == null) {
    231.         //            Debug.LogError ("Could not find the Name on " + selectedTarget.name);
    232.         //            return;
    233.         //        }
    234.      
    235.         //        name.GetComponent<TextMesh> ().text = selectedTarget.GetComponent<Mob> ().Name;
    236.         //        name.GetComponent<MeshRenderer> ().enabled = true;
    237.         selectedTarget.GetComponent<Mob> ().DisplayHealth ();
    238.      
    239.         isSelected.GetComponent<MeshRenderer> ().enabled = true;
    240.         Messenger<bool>.Invoke("show mob vitalbars", true);
    241.         Messenger.AddListener ("Active Mob Died", KillMob);
    242.  
    243.     }
    244.  
    245.  
    246.     public void DeselectTarget()
    247.     {
    248.         //        selectedTarget.FindChild ("Name").GetComponent<MeshRenderer> ().enabled = false;
    249.         selectedTarget.FindChild ("TargetSelected").GetComponent<MeshRenderer> ().enabled = false;
    250.         selectedTarget = null;
    251.         Messenger<bool>.Invoke("show mob vitalbars", false);
    252.  
    253.         //toggle targetDead back to false to get it ready for the next mob
    254.         targetDead = false;
    255.  
    256.     }
    257.  
    258.  
    259.  
    260.     private void Attack() {
    261.         float distance = Vector3.Distance (selectedTarget.transform.position, transform.position);
    262.      
    263.         Vector3 dir = (selectedTarget.transform.position - transform.position).normalized;
    264.      
    265.         float direction = Vector3.Dot (dir, transform.forward);
    266.      
    267.         Debug.Log (direction);
    268.      
    269.         if (distance < 10) {
    270.             if(direction > 0) {
    271.  
    272. //                EnemyHealth eh = (EnemyHealth)selectedTarget.GetComponent ("EnemyHealth");
    273. //                eh.AdjustCurrentHealth (-10);
    274.  
    275.  
    276.                 anim.SetBool ("IsAttacking", true);
    277.                 audio.PlayOneShot (Shotgun, 0.7F);
    278.                 //Debug.Log ("BOOM I SHOOT U");
    279.                 RemoveHPFromEnemy();
    280.                 //new WaitForSeconds (2);
    281.  
    282.                 anim.SetBool ("IsDoneAttacking", true);
    283.  
    284.             }
    285.         }
    286.     }
    287.  
    288.     private void RemoveHPFromEnemy(){
    289.  
    290.         //Transform isSelected = selectedTarget.FindChild ("TargetSelected");                //Find the TargetSelected arrow mesh
    291. //        selectedTarget.GetComponent<Mob> ().DisplayHealth ();
    292.         int removeHP = selectedTarget.GetComponent<Mob> ().curHealth -= 10;
    293.         int mobMaxHP = selectedTarget.GetComponent <Mob> ().maxHealth;
    294.  
    295. //        selectedTarget.GetComponent<Mob> ().maxHealth;
    296.  
    297.         Messenger<int, int>.Invoke("mob health update", removeHP, mobMaxHP);
    298.         //Debug.Log ("Did Some Damage");
    299. //        Messenger<bool>.Invoke("show mob vitalbars", true);
    300.     }
    301.  
    302.     private void KillMob(){
    303.         targetDead = true;
    304.     }
    305.  
    306.  
    307. }
    308.  
     
  2. Azmar

    Azmar

    Joined:
    Feb 23, 2015
    Posts:
    246
    You have privateGameObject[] Enemies to keep track of the enemies, but it doesn't look like you really use it properly. Maybe in RemoveHPFromEnemy() you could have if monster HP is below 0, the enemy control you have like:

    enemies.IsDead = true, and you should really be working around more of the Enemies array.

    I think the way you are doing the whole target system, is causing you future problems of knowing what is going on. Maybe a rewrite of first creating enemies, getting a handle of all their data, being able to control their data individually, and AFTER create the target system.

    Some misc notes, I am assuming a lot of your code is mostly from tutorials. I see a huge amount of getComponents and questionable stuff being done on the fly, which probably reflects from the tutorials. I don't feel like this tutorial will lead you in a good direction for learning proper programming techniques. Maybe it would be better to find a new series of tutorials to follow?
     
    CrisisSystem likes this.
  3. mafiadude1

    mafiadude1

    Joined:
    Jun 28, 2012
    Posts:
    59
    Code (csharp):
    1.  
    2. foreach(GameObject enemy in Enemies){
    3.     if(enemy.GetComponent<EnemyAI>().isDead) continue;
    4.     else AddTarget(enemy.transform);
    5.  
     
    CrisisSystem likes this.
  4. CrisisSystem

    CrisisSystem

    Joined:
    Oct 7, 2015
    Posts:
    124
    Thank you for the response, but I still get the same issue.

    When I press K to find the next target after killing them, it picks the same one since he is closest (SortTargetsByDistance()) and kills him again. If I move closer to another mob it chooses that mob but still it doesn't seem to be skipping by the dead ones in the array. I must've borked something further up in the chain.. I'm going over the script again. Been a long couple days figuring this one out XD
     
  5. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    Once you have your sorted array, you need to loop through them and find the find un-killed one. (currently, it just selects index 0, the first one) The issue there is that you have a List<Transform>, and Transform doesn't have that information. You can use GetComponent<EnemyAI>() on each one in sequence (similar to what mafiadude suggested), and you'd rep[lace your line 200 with this:
    Code (csharp):
    1. for (int t=0;t<targets.Count;t++) {
    2. EnemyAI thisEnemy = targets[t].GetComponent<EnemyAI>()
    3. if (!thisEnemy.isDead) {
    4. selectedTarget = targets[t];
    5. break;
    6. }
    7. }
    I would suggest, that you retool the script to make targets a List<EnemyAI> instead of using GetComponent a lot, though.
     
    CrisisSystem likes this.
  6. CrisisSystem

    CrisisSystem

    Joined:
    Oct 7, 2015
    Posts:
    124
    Ok, thanks for the tips. I'll look into rebuilding based on what you guys have said.. and it sounds like using all the GetComponents is going to make an impact on CPU time, now that I think about it.

    This is a pretty wild tangent from the tutorial, so I'm not really surprised it's problematic. I combined a couple scripts and it got messy fast. :D
     
  7. image28

    image28

    Joined:
    Jul 17, 2013
    Posts:
    457
    only call GetComponent the first time and store the script references in an array. Something like

    Code (CSharp):
    1. private EnemyAI[] enemyScripts;
    2.  
    3. for (int t=0;t<targets.Count;t++) {
    4. if ( enemyScripts[t] == null )
    5. enemyScripts[t] = targets[t].GetComponent<EnemyAI>()
    6. if (!enemyScripts[t].isDead) {
    7. selectedTarget = targets[t];
    8. break;
    9. }
    10. }
     
  8. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    At that point, he's maintaining two arrays. He'd have to sort both of them the same way somehow. At that point, it's better to replace the Transform list entirely, and alter the sort function call to match.
     
    CrisisSystem and image28 like this.
  9. CrisisSystem

    CrisisSystem

    Joined:
    Oct 7, 2015
    Posts:
    124
    I'm considering doing away with the targetting system all together and just going with a set of crosshairs. I had intended to just get this working for now while I figure out what I want exactly, and it does work pretty ok now thanks to you guys. I'm gonna do some more homework before taking the next step with this system. Thanks folks
     
    Azmar likes this.