Problem with array and coroutine...Sometimes Works!!!
hi guys, i need help with something, i'm a bit of a newbie to C#, and i'm developing a horror video game.
One of the things I want this code to do is to make is when the player goes through a trigger ( static bool in other Sript) certain lights ( in an array) turn off for a few seconds and then reappear, it sounds simple, doesn't it? The point is that I do not know why this code sometimes works and sometimes it does not, in fact lately the number of times it is not working is more. Then I leave the code. I hope you can help me. Even if you know of a better or more optimized, or less bugged way to do this, I would also be very grateful if you would let me know. Greetings friends, thank you very much in advance.
 public class ParpadearLuces : MonoBehaviour
 {
     public GameObject[] _LucesSubterraneo;
     public GameObject craneo;
    
      // Start is called before the first frame update
     void Start()
     {
         
     }
 
     // Update is called once per frame
     void Update()
     {
         if (CalaveraTrigger.apagarLuces==true)
         {
             StartCoroutine(esperar10Segundos());
            
     }
 
   void ApagarLuces()
     {
         for (int i = 0; i < _LucesSubterraneo.Length; i++)
             _LucesSubterraneo[i].SetActive(false);
 
     }
 
      IEnumerator desaparecerCraneo()
     {
         yield return new WaitForSeconds(1);
         craneo.SetActive(false);
             
             for (int i = 0; i < _LucesSubterraneo.Length; i++)
                 _LucesSubterraneo[i].SetActive(true);
             CalaveraTrigger.apagarLuces = false;
             Destroy(this);
     }
 
     IEnumerator esperar10Segundos()
     {
             
             yield return new WaitForSeconds(10);
             ApagarLuces();
             StartCoroutine(desaparecerCraneo());
     }
     }
 }
 
              Answer by xxmariofer · Jun 11, 2021 at 08:08 AM
You have an issue with the }, and also you need to set CalaveraTrigger.apagarLuces back to false, or it will call apagar luces infinite times and will create unexpected behaviour
  public class ParpadearLuces : MonoBehaviour
  {
      public GameObject[] _LucesSubterraneo;
      public GameObject craneo;
     
       // Start is called before the first frame update
      void Start()
      {
          
      }
  
      // Update is called once per frame
      void Update()
      {
          if (CalaveraTrigger.apagarLuces==true)
          {
              StartCoroutine(esperar10Segundos());
           }
      }
  
    void ApagarLuces()
      {
          for (int i = 0; i < _LucesSubterraneo.Length; i++)
              _LucesSubterraneo[i].SetActive(false);
  
      }
  
       IEnumerator desaparecerCraneo()
      {
          yield return new WaitForSeconds(1);
          craneo.SetActive(false);
              
              for (int i = 0; i < _LucesSubterraneo.Length; i++)
                  _LucesSubterraneo[i].SetActive(true);
              CalaveraTrigger.apagarLuces = false;
              Destroy(this);
      }
  
      IEnumerator esperar10Segundos()
      {
              CalaveraTrigger.apagarLuces=true;
              yield return new WaitForSeconds(10);
              ApagarLuces();
              StartCoroutine(desaparecerCraneo());
      }
  }
 
              Thank you so much. Your answer could be the solution. As you mentioned, I have reviewed the script and I have realized that I had already set the bool to FALSE in the "desaparecerCraneo()" coroutine However, to prevent the bool (CalaveraTrigger.apagarLuces ) from staying false I have added the command to destroy the gameObject at the end of the coroutine (is that the correct way to do it? Are there better ways?). On the other hand, I insist on understanding why sometimes it works and sometimes not, since in many of the scripts that I use coroutines I have this problem. I will be attentive to a possible answer.
In these $$anonymous$$utes I have realized that it is better that in voidOnTriggerEnter () go a boolean in true inside it. And in the update () put an if (boolean == true) {execute the coroutine) ... this way it works every time. Although I still have doubts about whether destroying the object is a good way to do what I was talking about in the previous comment.
Hello,
No deleting the gameobject to avoid "apagarluces" to be set to false is not a good solution. Update gets called every frame, and since you are waiting 1 second to reset the variable to false you are starting (if your game runs at 60fps) 60 times.
To avoid this, as i suggested set
               CalaveraTrigger.apagarLuces=false;
 
                   in the previous code i posted there was an error, change
       IEnumerator esperar10Segundos()
       {
               CalaveraTrigger.apagarLuces=true;
               yield return new WaitForSeconds(10);
               ApagarLuces();
               StartCoroutine(desaparecerCraneo());
       }
 
 to
 
 
       IEnumerator esperar10Segundos()
       {
               CalaveraTrigger.apagarLuces=false;
               yield return new WaitForSeconds(10);
               ApagarLuces();
               StartCoroutine(desaparecerCraneo());
       }
 
                  You solved my life ... thank you, all the bugs were solved, it is incredible how I did not see these things. I guess experience will help me. Thank you. :)
You are welcome, if it worked please accept the answer as correct for future readers
Your answer