Search Unity

Coroutine Question (Freeze Enemy)

Discussion in 'Scripting' started by TreasureChestMimic, Feb 7, 2018.

  1. TreasureChestMimic

    TreasureChestMimic

    Joined:
    Jan 26, 2018
    Posts:
    8
    Hey everyone. Back with yet another question. I'm trying to setup an enemy that can be frozen for a set amount of time, then unfreezes, after which the player can once again freeze the enemy. This is what I've got so far:

    Code (CSharp):
    1.     public bool frozen;
    2.     public float currentDamage;
    3.  
    4.  
    5.     // Use this for initialization
    6.  
    7.     void Start () {
    8.         frozen = false;
    9.         currentDamage = GetComponent<enemyDamage> ().damage;
    10.     }
    11.     // Update is called once per frame
    12.     void FixedUpdate () {
    13.         if (frozen) {
    14.             GetComponent<enemyDamage>().damage = 0;
    15.             transform.gameObject.layer = 8;
    16.             GetComponent<enemyDamage>().enabled = false;
    17.             GetComponent<enemyHealth>().enabled = false;
    18.             GetComponent<enemyMovement> ().enabled = false;
    19.             StartCoroutine (freezeTime());
    20.         }
    21.     }
    22.     IEnumerator freezeTime (){
    23.         yield return new WaitForSeconds (10);
    24.             frozen= false;
    25.             GetComponent<enemyDamage>().damage = currentDamage;
    26.             transform.gameObject.layer = 9;
    27.             GetComponent<enemyDamage>().enabled = true;
    28.             GetComponent<enemyHealth>().enabled = true;
    29.             GetComponent<enemyMovement>().enabled = true;
    30.         StopCoroutine (freezeTime());
    31.     }
    32. }
    33.  
    34.  
    a Raycast from a character sets frozen on the object. As is it freezes the enemy that gets hit, then after 10 seconds sets them back to their original status. Problem comes when I try to freeze them again, they don't actually freeze. Or even more confusing, they freeze for a fraction of a second, then go back to normal. Not sure what is going on here.. Any ideas would be appreciated!
     
  2. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    Disabling and enabling MonoBehaviours when you want them to stop doing stuff is often too simple a solution for cases like this- coroutines will still keep running on them as long as the GameObject itself is enabled, since that's what the coroutine is tied to in the background, and mostly all disabling does is stop receiving Update/FixedUpdate/LateUpdate calls. If you have some sort of a "frozen" status, then it would be better to make an event in your status script that other components can register to, to get called when frozen and be able to react to it appropriately in multiple places at once.

    Components should handle themselves, whenever possible, and when not possible they should be handled by a controller of some sort in a higher position, with a wider scope- they shouldn't be controlled laterally by another component. You should get into the habit of making fields private to avoid the temptation to do so.

    As to your specific problem, there's not really any reason to do anything with FixedUpdate- make the "frozen" field private, give it a public property or a function like BecomeFrozen() or something, and trigger the coroutine from there only when going from "false" to "true". As it is, you're starting a new instance of the coroutine every single FixedUpdate for those first 10 seconds after being frozen, because frozen is still true and the coroutine is just waiting before changing anything.

    Also, you don't need to call StopCoroutine inside of the same coroutine- it stops automatically when it reaches the end of the function body. And you shouldn't cache damage values the way you do with "currentDamage" IMO- if you need the damage value from EnemyDamage, you should cache the EnemyDamage reference, not the value itself. You're just begging for bugs this way.
     
    Last edited: Feb 8, 2018
  3. TreasureChestMimic

    TreasureChestMimic

    Joined:
    Jan 26, 2018
    Posts:
    8
    First, thank you for your reply!
    Second boy seems like I'm doing about everything wrong, which isn't that surprising to be honest.

    Not going to lie, this is a bit over my head right now, so I'm going to do a little bit of research and try it again I suppose.