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. Dismiss Notice

how to make a function loop continuously

Discussion in 'Scripting' started by Zaffer, Dec 4, 2014.

  1. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Hi,
    I have a set of musical sounds I would like to have play randomly and at random intervals as background music. Here's the code I have so far (attached to the camera):
    Code (CSharp):
    1. public void startIEnumPlayMusic(){
    2.         StartCoroutine(PlayMusic());
    3.     }                          
    4.  
    5.     private IEnumerator PlayMusic(){
    6.         yield return new WaitForSeconds(Random.Range(1, 10));
    7.         audio.PlayOneShot(flowerNotes[Random.Range(0, 9)]);
    8.         Debug.Log ("play music");
    9.     }
    This is called from a GUI script attached to a game object using "musicOn" and "musicOff" buttons
    Code (CSharp):
    1. if (GUI.Button(new Rect(4, 344, 16, 16), new GUIContent(music_on), B_chooseButtonGUIStyle)){
    2.     musicOn = true;
    3.     CallPlayMusic();
    4. }
    I would like to have the PlayMusic function repeat in a continuous loop while the "musicOn" button is pressed and stop when the "musicOff" button is pressed. I tried setting up a flag in the GUI script: musicOn = false and then I set up a while loop: while (musicOn == true) {CallPlayMusic()}, but unity froze. I would greatly appreciate suggestions. Thanks.
    Zaffer
     
  2. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    Code (csharp):
    1. private IEnumerator PlayMusic () {
    2.     yield return new WaitForSeconds (Random.Range (1, 10));
    3.  
    4.     while (musicOn) {
    5.         audio.PlayOneShot (flowerNotes[Random.Range (0, 9)]);
    6.         Debug.Log ("play music");
    7.         yield return new WaitForSeconds (Random.Range (1, 10));
    8.     }
    9. }
     
  3. Sbizz

    Sbizz

    Joined:
    Oct 2, 2014
    Posts:
    250
    Code (csharp):
    1. private IEnumerator PlayMusic () {
    2.     while (musicOn) {
    3.         yield return new WaitForSeconds (Random.Range (1, 10));
    4.         audio.PlayOneShot (flowerNotes[Random.Range (0, 9)]);
    5.         Debug.Log ("play music");
    6.     }
    7. }
    ? :p
     
  4. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    The sole difference between the code I posted and Sbizz's is that Sbizz's has the possibility of the sound playing 1-9 seconds after musicOn is set to false.
     
  5. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Thank you so much, DanielQuick and Sbizz. Your code works! I just have one little (I hope) problem. I can start the music, but not stop it. I can get the PlayMusic (bool) set to false, but the while loop doesn't seem to get the false message. It stays true. Can you help? Again, thanks so much. Here's my code:
    Code (CSharp):
    1. public void startIEnumPlayMusic(bool musicSwitch){
    2.         if (musicSwitch == true){
    3.             StartCoroutine(PlayMusic(musicSwitch));
    4.         }
    5.         if (musicSwitch == false){
    6.             StartCoroutine(PlayMusic(musicSwitch));
    7.  
    8.         }
    9.     }                        
    10.  
    11.     private IEnumerator PlayMusic(bool musicSwitch){
    12.         Debug.Log(musicSwitch);
    13.         yield return new WaitForSeconds(Random.Range(1, 6));
    14.  
    15.         while (musicSwitch == true){
    16.             audio.PlayOneShot(flowerNotes[Random.Range(0, 9)]);
    17.             yield return new WaitForSeconds(Random.Range(1, 10));
    18.         }
    19.     }
     
  6. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    You are passing a copy of the bool to your PlayMusic coroutine, not the actual value. Because your copy starts out as true (I assume), it will always be true.
     
  7. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Thanks DanielQuick, Could you please explain "copy of the bool" or point me to a link with an explanation? Thanks.
     
  8. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
  9. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Thanks DanielQuick, Sorry I still don't get it. What do you mean by "passing a copy?" How would I pass in the bool "false," copy or not. Thanks.
     
  10. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    489
    When passing variables to functions it makes a copy of them. Unless you specify it as a ref (reference).
    Code (CSharp):
    1. bool playMusic = false;
    2.  
    3. void MyFunction(ref bool playMyMusic){
    4.  
    5. }
    6.  
    7. void Start(){
    8. MyFunction(ref playMusic);
    9. }
    10.  
     
  11. novashot

    novashot

    Joined:
    Dec 12, 2009
    Posts:
    373
    First question: What is the result of your debug log in the play music function?
    Next: Are you trying to kill the music immediately? ( the way your code is now, it will finish playing what ever it is playing but it shouldn't grab a new song when false)


    for your current code I'd probably do something like:

    Code (CSharp):
    1. bool musicSwitch = false;
    2.  
    3. void ToggleMusic(){
    4.      musicSwitch=!musicSwitch;
    5.      CheckMusic();
    6. }
    7.  
    8. void CheckMusic(){
    9.  
    10.      if(musicSwitch){
    11.           int i = Random.Range(0, flowerNotes.Length); // EDIT: took out the -1 Daniel is correct with Random.Range(int,int)
    12.           audio.Play(flowerNotes[i]);
    13.           Invoke("CheckMusic", Random.Range(1, 10)); // you do this
    14.           // I'd use something like
    15.           Invoke("CheckMusic", (flowerNotes[i].length + 0.5f)); //just added a constant .5 sec between... can do anything here
    16.      }
    17.      else {
    18.           CancelInvoke(CheckMusic()); // make sure the cycle stops
    19.           audio.Stop();  // stop the current audio
    20.      }
    21. }
    22.  
     
    Last edited: Dec 5, 2014
  12. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    You wouldn't want to subtract 1, Random.Range (int, int) is [inclusive, exclusive)
     
    novashot likes this.
  13. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Hi Novashot,
    To answer your first question, the Debog.Log shows "true" or "false" correctly according to the button pushed, but the while loop just doesn't get the message and keeps playing as though "true" is still pressed. Thanks for the new code, but before I start over, I'm going to see if I can get some help with the "ref" word.

    Hi Aaro4130,
    Here's the path followed by my code:
    1) button press in ColorCubeGUI calls CallPlayMusic() function-- also in ColorCubeGUI.
    Code (CSharp):
    1. if (GUI.Button(new Rect(4, 344, 16, 16), new GUIContent(music_on), B_chooseButtonGUIStyle)){
    2.                 musicOn = true;
    3.                 CallPlayMusic(ref musicOn);
    4.             }
    5.             if (GUI.Button(new Rect(28, 344, 16, 16), new GUIContent(music_on), B_chooseButtonGUIStyle)){
    6.                 musicOn = false;
    7.                 CallPlayMusic(ref musicOn);
    8.             }
    2) CallPlayMusic() function calls StartIEnumPlayMusic() in PlaySounds script.
    Code (CSharp):
    1. void CallPlayMusic(ref bool musicOn){
    2.         GameObject cameraMain = GameObject.Find("Camera");
    3.         PlaySounds otherScript = (PlaySounds) cameraMain.GetComponent(typeof(PlaySounds));
    4.         if (musicOn == true){
    5.             otherScript.StartIEnumPlayMusic(ref musicOn);
    6.         }
    7.         if (musicOn == false){
    8.             otherScript.StartIEnumPlayMusic(ref musicOn);
    9.         }
    10.     }
    3)StartIEnumPlayMusic() calls IEnumerator PlayMusic() also in PlaySounds script
    Code (CSharp):
    1. public void StartIEnumPlayMusic(ref bool musicOn){
    2.         if (musicOn == true){
    3.             StartCoroutine(PlayMusic(true));
    4.         }
    5.         if (musicOn == false){
    6.             StartCoroutine(PlayMusic(false));
    7.         }
    8.     }  
    4) Finally, IEnumerator PlayMusic() has the while loop and actually plays the sounds.
    Code (CSharp):
    1. private IEnumerator PlayMusic(bool musicOn){
    2.         yield return new WaitForSeconds(Random.Range(1, 6));
    3.         Debug.Log(musicOn);
    4.         while (musicOn == true){
    5.      
    6.             audio.PlayOneShot(flowerNotes[Random.Range(0, 9)]);
    7.             yield return new WaitForSeconds(Random.Range(1, 10));
    8.         }
    9.     }
    I managed to use the "ref" word all through this chain, but the IEnumerator PlayMusic() function won't take the "ref" word. Any suggestions will be greatly appreated, up to and including just killing the IEnumerator function when I want the music to stop. Thanks.
    Zaffer
     
  14. Zaffer

    Zaffer

    Joined:
    Oct 21, 2010
    Posts:
    266
    Hi NovaShot,

    I finally wrapped my head around your code and it worked! Thanks so much. Here's what I did:
    Code (CSharp):
    1. void CheckMusic(){      
    2.         if(musicSwitch){
    3.             //int i = Random.Range(0, flowerNotes.Length); // EDIT: took out the -1 Daniel is correct with Random.Range(int,int)
    4.             audio.PlayOneShot(flowerNotes[Random.Range(0, 11)]);
    5.             Invoke("CheckMusic", Random.Range(0.2f, 2.0f)); // you do this
    6.             // I'd use something like
    7.             //Invoke("CheckMusic", (flowerNotes[i].length + 0.5f)); //just added a constant .5 sec between... can do anything here
    8.         }
    9.         else {
    10.             CancelInvoke("CheckMusic"); // make sure the cycle stops
    11.             audio.Stop();  // stop the current audio
    12.         }
    13.     }
    I was afraid of commands I hadn't heard before. I'm new to C# and hanging on my my fingernails. Thanks again.
    Zaffer
     
  15. novashot

    novashot

    Joined:
    Dec 12, 2009
    Posts:
    373
    No problem.