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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

IENumerator - WaitForSeconds - Not Working / Small Bug OnCollisionEnter - Not Incriminting

Discussion in 'Scripting' started by MisterSkitz, Nov 14, 2018.

  1. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    Basically I have two problems that I cannot solve. Neither seem difficult, but I'm stumped and annoyed.

    1) I've attempted two different approaches to try and make WaitForSeconds to work.
    1a) Invoke(HideStar,3); This didn't work for me. (Didn't know what to return in IENum) Why?
    1b) WaitForSeconds(3); Code runs up to this point.

    What happens is that the UI image/text will display on screen but will not set active back to false.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class StarTabletScript : MonoBehaviour
    7. {
    8.  
    9.     public static GameObject starTab;
    10.     private int starTabCount = 0; // Counts total stars in the scene
    11.     private int starTabCollected=0;// Star off with zero star tabs collected
    12.     private GameObject[] starTabTotal; // Reads the total amount of star tabs in the scene
    13.     public Image starImg; // The  star sprite
    14.     public Text starTxt; // The star Text
    15.  
    16.     private int wait = 2000;
    17.  
    18.     void Start()
    19.     {
    20.         starTab = GetComponent<GameObject>();
    21.         starTabTotal = GameObject.FindGameObjectsWithTag("StarTab");
    22.         starImg.enabled = false;
    23.         starTxt.enabled = false;
    24.         // (ABOVE) Will start off true for (x) amount of seconds(Need IENUMORATOR to work)
    25.         // (BELOW)Displays this text AFTER I get IENumerator to work below
    26.         starTxt.text = starTabCollected + " / " + starTabTotal;
    27.      
    28.      
    29.     }
    30.  
    31.     void OnCollisionEnter(Collision collision)
    32.     {
    33.         if (collision.gameObject.tag == "Player")
    34.         {
    35.  
    36.             starTabCollected++;
    37.             foreach(GameObject star in starTabTotal)
    38.             {
    39.  
    40.                 starTabCount++;
    41.  
    42.             }
    43.             StartCoroutine(ShowStar(starImg,starTxt));
    44.             Destroy(gameObject);
    45.          
    46.          
    47.  
    48.  
    49.  
    50.             Debug.Log(starTabCount);
    51.  
    52.         }
    53.     }// End of OnCollisionEnter
    54.  
    55.    IEnumerator ShowStar(Image starImg, Text starTxt)
    56.     {
    57.      
    58.        // Invoke("HideStar", 3);
    59.         starImg.enabled = true;
    60.         starTxt.enabled = true;
    61.         starTxt.text = starTabCollected + " / " + starTabCount;
    62.         yield return new WaitForSeconds(3);
    63.         starImg.enabled = false;
    64.         starTxt.enabled = false;
    65.     }
    66.  
    67.     void HideStar()
    68.     {
    69.         // Haven't added full code in this function
    70.         // Easy copy / paste if this method works better
    71.         starImg.enabled = false;
    72.         starTxt.enabled = false;
    73.  
    74.     }
    75.  
    76.  
    77.  
    78. }
    79.  
    2) StarTabCollected doesn't increment when player touches a second star. The text will read (ForExample) 1 / 200
    All of the code runs inside of the Ocollision function because the object does get destroyed.
    Why is that?

    Need some help here!
     
    Last edited: Nov 14, 2018
  2. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,900
    Because you're destroying the game object. And you're destroying the script with it. At the end of the frame your GO will gets destroyed.
    You should move out this part of the script somewhere else, what does not get destroyed. Or quit destroying/instantiating constantly, that's bad for the performance regardless, so it's a good habit to pooling objects, especially when you have a lot of them.
     
    xVergilx likes this.
  3. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    Hey LND, thank you for the response! I don't really have a good understanding of how to improve performance. I kinda learn stuff as I go. You gave me a few things to look into, like "pooling". I've never heard of this before. I will remove my Detroy() outside of the OnCollision function and place it at the very end of the script. I'm also starting to realize the true meaning of CoRoutine. Apparently, it doesn't interject the programs natural algorithm, but runs alongside it instead. Which would explain a lot of issues I've experienced with it.
     
  4. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,900
    Quick tutorial on object pooling:


    About co-routine: it's not really multi-thread, you can think about it like interruption. You schedule a time when a piece of code should be running and then "forget it", go with your code and when you scheduled, your application will stop and execute what you scheduled. So technically it is not multi-thread, but it kind of looks like one.
    Which also means you don't do "more" work, you just distribute the work according to your idea. This is what the yield expression is all about, to schedule when the rest of your code should resume for a while.
     
    Kiwasi and MisterSkitz like this.
  5. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class StarTabletScript : MonoBehaviour
    7. {
    8.  
    9.     public static GameObject starTab;
    10.     private int starTabCount = 0; // Counts total stars in the scene
    11.     private int starTabCollected;// Star off with zero star tabs collected
    12.     private GameObject[] starTabTotal; // Reads the total amount of star tabs in the scene
    13.     public Image starImg; // The  star sprite
    14.     public Text starTxt; // The star Text
    15.     [SerializeField]
    16.     private Renderer starMesh; // Used to deactivate the mesh of the star tab upon collision
    17.  
    18.  
    19.  
    20.     void Start()
    21.     {
    22.         starTab = GetComponent<GameObject>();
    23.         starTabCollected = 0;
    24.         starTabTotal = GameObject.FindGameObjectsWithTag("StarTab");
    25.         foreach (GameObject star in starTabTotal)
    26.         {
    27.  
    28.             starTabCount++;
    29.  
    30.         }
    31.  
    32.         StartCoroutine( StartShow());// Shows image upon start
    33.        
    34.        
    35.     }//End of start
    36.  
    37.  
    38.     void OnTriggerEnter(Collider other)
    39.     {
    40.         if (other.tag == "Player")
    41.         {
    42.  
    43.             starMesh.enabled = false;
    44.        
    45.            
    46.             StartCoroutine(ShowStar());
    47.          
    48.         }
    49.     }// End of OnTriggerEnter
    50.  
    51.    IEnumerator ShowStar()// Shows star image on pickup
    52.     {
    53.        
    54.         starTabCollected++;
    55.         Debug.Log("3) Stars collected "+starTabCollected);
    56.         starImg.enabled = true;
    57.         starTxt.enabled = true;
    58.         starTxt.text = starTabCollected + " / " + starTabCount;
    59.         yield return new WaitForSeconds(3);
    60.         starImg.enabled = false;
    61.         starTxt.enabled = false;
    62.         Destroy(gameObject);
    63.     }// End of ShowStar
    64.    
    65.     IEnumerator StartShow()// Shows star on program start
    66.     {
    67.         Debug.Log("1) Total Stars in scene "+starTabCount);
    68.         Debug.Log("2) StarTab.Length testing "+starTabTotal.Length);
    69.         starImg.enabled = true;
    70.         starTxt.enabled = true;
    71.  
    72.         starTxt.text = starTabCollected + " / " + starTabCount;
    73.         yield return new WaitForSeconds(5);
    74.         starImg.enabled = false;
    75.         starTxt.enabled = false;
    76.     }// End of StartShow
    77.  
    78.    
    79.  
    80. }//End of class
    Okay, I refined the code a bit and almost have everything working properly. ( Thanks for that video, LND ).
    However, the last thing I'm having a problem with that I do not quite understand is the starTabCollected variable will only add +1 the first time that I enter the trigger. It will never increment higher than 1. I cannot find anything useful about why this error is occurring.
    Can anyone explain what is happening and why I cannot increase the value more than once?