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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Yield not working with onClick.AddListener.

Discussion in 'UGUI & TextMesh Pro' started by Diablo404, Aug 28, 2014.

  1. Diablo404

    Diablo404

    Joined:
    Mar 15, 2013
    Posts:
    136
    Here is a strange behaviour that I found:

    Code (JavaScript):
    1. function Start()
    2. {
    3.     button.GetComponent(UI.Button).onClick.AddListener( BtnFunction );
    4. }
    5.  
    6. function BtnFunction()
    7. {
    8.     print("test 1");
    9.     yield WaitForSeconds(1);
    10.     print("test 2");
    11. }

    Neither "test 1" nor "test 2" will appear on the console, the code seems not to be executed. But, as a workaround, this would work:

    Code (JavaScript):
    1. function Start()
    2. {
    3.     button.GetComponent(UI.Button).onClick.AddListener( Temp );
    4. }
    5.  
    6. function Temp()
    7. {
    8.     BtnFunction();
    9. }
    10.  
    11. function BtnFunction()
    12. {
    13.     print("test 1");
    14.     yield WaitForSeconds(1);
    15.     print("test 2");
    16. }

    Due to the fact that I don't have a good knowledge of how closure or event or callback should work, I don't know if it is totally normal or not. But if it is, it would be good to maybe at least throw a Warning to tell that yield are not working inside this function? Because if it is the right behaviour, I'm afraid this question/answer will pop a lot in the future.
     
  2. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,614
    My guess is that it's because BtnFunction is a coroutine, but under the hood none of the button code is calling StartCoroutine to start it so it doesn't run properly. When you call Temp instead, Temp's call to BtnFunction generates a StartCoroutine call (as per The Magic Of UnityScript) which is why it works.

    Unfortunately I think it's going to be impossible for addListener to detect when the thing you're adding is a coroutine.
     
  3. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    557
    I don't know if UnityScript supports the delegate{} construct, but if it does you might be able to wrap it like that.

    Code (csharp):
    1. button.GetComponent(UI.Button).onClick.AddListener( delegate{ StartCoroutine( BtnFunction() ); } );
     
  4. illustir

    illustir

    Joined:
    Dec 12, 2014
    Posts:
    24
    But what if you need to yield within a delegate? Unity won't let me.
     
  5. ThieLz

    ThieLz

    Joined:
    Jan 4, 2013
    Posts:
    2
    Still no solution for this problem? I have the same condition, I use delegate and need to yield waitForSeconds, but yield never return.
     
  6. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,614
    The solution is the same as if you need to yield inside of Update: You put your yielding code in a separate function, and in your delegate you only call StartCoroutine.