Yield Script Update Error (69619)

Hi, I’m making Sparky Konga, an interactive game application using the DK Bongo controllers (You can watch my Beta test Video Here: Sparky Konga - Beta Test). My problem right now is that the internal microphone for the controller, meant to hear clapping, is reacting to hearing and feeling the vibration of me hitting the other parts of the bongo controller. I coded my project so that the mic value = 0 whenever the button is pressed. However, it didn’t work as well as I wanted to because sound and vibration tend to linger a tiny bit. So, I want to make the mic = 0 function last for more than a single frame. I found out about the yield function and tried to use it to make mic = 0 for about 5 seconds as a test (in the end, I only want it to last for around 1/10 or 2/10 of a second).

if (Input.GetKeyDown(KeyCode.JoystickButton0) || Input.GetKeyDown(KeyCode.JoystickButton1) || Input.GetKeyDown(KeyCode.JoystickButton2) || Input.GetKeyDown(KeyCode.JoystickButton3)) {
							mic = 0;
							yield return new WaitForSeconds(5.0f);
					}

It worked… However then there began to be problems. I stopped my game play test and changed 5.0f to 0.2f. The problem is that now, I get this error.

Assets/Scripts/UnityOSC-master/BoncoClapScript.cs(35,14): error CS1624: The body of BoncoClapScript.Update()' cannot be an iterator block because void’ is not an iterator interface type

I don’t understand why it’s saying this. I changed it back to 5.0f, but I still got this error and I keep getting this error every time I try to run my game (if I remove the yield statement, it works as normal). I seems like it has some problem with the Update function, but I can’t seem to figure it out why considering I didn’t touch anything and it seemingly worked once before.

Does anyone have any idea what the issue is here?

FYI, there are huge numbers of questions on all the details of yield on here, (When I was a new Unity user I must have asked 20.) Just search for your faster convenience. Also read at unityGEMS.com Also, for extremely simple timers in Unity, just use Invoke() or InvokeRepeating(). There is absolutely no reason to have any involvement with coroutines for very simple Unity programming, no more than you need to be able to write shaderlab for very simple Unity programming.

I did before I asked this. Couldn't find anything seemingly similar to my problem.

No, there are perhaps 100 question exactly about this. There are even (incredibly long) excellent tutorials on the topic, since you've started with no knowledge of coroutines etc.

2 Answers

2

So you can’t yield inside an Update function because that is called every frame, guaranteed, and you would end up with lots of copies running. You have to start a coroutine to be able to yield from there. This feels like a case where you shouldn’t use Update and should instead use a coroutine for all of your updating. A good way of doing that is just to make your Start function a coroutine by declaring it as IEnumerator Start and then have that be like your pausable Update function. You could also create any other named coroutine and start it with StartCoroutine(YourFunction()).

 IEnumerator Start()
 {
      while(true)
      {
           //The code here acts like an Update function, but you can yield different amount in 
           //it if you want to.

           if(Input.GetKeyDown(KeyCode.JoystickButton0)) 
                  yield return new WaitForSeconds(5);

           yield return null;
      }
 }

Oh yeah - I didn't mean to embed that code :S Wait one.

No Update function at all - this gives you more control

If you don't mind, could you explain the lack of an update function? What changes does this create as opposed to when I had one? Isn't an Update function required?

In order to use a yield statement, you have to be in a function that returns type IEnumerator. So you could do:

    IEnumerator DisableBongoMic()
    {
         mic = 0;
         yield return new WaitForSeconds(5.0f);
         mic = 1;
    }