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

Resolved Can you Subscribe to Events with lambdas in Coroutines?

Discussion in 'Scripting' started by BenevolenceGames, Apr 13, 2023.

  1. BenevolenceGames

    BenevolenceGames

    Joined:
    Feb 17, 2021
    Posts:
    128
    I am having an issue where my Event is firing but the subscribed function pointed to in the lambda does not execute. Any ideas here?

    What I Want - I want a script that can count down a timer while waiting for the form to be answered, but I want it done asynchronously if possible. I do not want the whole thread waiting for the timer funcction.

    What I have tried - I have googled the answer and watched a few videos on events and lamda expressions. I have tried the scripts you see below as well as a timer and update function approach. I can't seem to get this to work appropriately.

    What I'd like from you - Any information on why this current set up isn't working so I can get a better understanding of why it's wrong and how to code in the future to be right.


    Code (CSharp):
    1. public IEnumerator WaitForFormResponse(InputForm form){
    2.     bool response = false;
    3.     form.OnSubmit += () => {
    4.         Debug.Log("Clicked Me!!");
    5.         response = true;
    6.     };
    7.     while (!response)
    8.     {
    9.         Debug.Log("Waiting..." + response.ToString());
    10.         yield return new WaitForEndOfFrame();
    11.     }
    12.     Debug.Log("Response Logged!");
    13. }
    Code (CSharp):
    1. public class PlayerNameForm : MonoBehaviour, InputForm{
    2.  
    3.     public event InputForm.OnClickEvent OnSubmit;
    4.     [SerializeField] public TMPro.TMP_InputField inputField;
    5.     public void OnClickSubmit(){
    6.         string [] words = inputField.text.Split(" ", StringSplitOptions.None);
    7.         foreach (string word in words){
    8.             Debug.Log(word);
    9.         }
    10.         if (OnSubmit != null){
    11.             OnSubmit();
    12.         }
    13.     }
    14.     public void OnClickCancel(){
    15.  
    16.     }
    17. }
     
    Last edited: Apr 13, 2023
  2. BenevolenceGames

    BenevolenceGames

    Joined:
    Feb 17, 2021
    Posts:
    128
    For added clarity...


    Code (CSharp):
    1.     public InputForm PresentForm(FormType type, Canvas parentCanvas){
    2.         switch (type){
    3.             case FormType.PlayerName:
    4.                 GameObject form = Instantiate(playerNameFormPrefab, parentCanvas.gameObject.transform.position, Quaternion.identity);
    5.                 form.transform.SetParent(parentCanvas.transform);
    6.                 return form.GetComponent<InputForm>();
    7.         }
    8.         return null;
    9.     }
    10.  
    11.     public void OnClickNameMe(){
    12.         InputForm form = PresentForm(FormType.PlayerName, activeCanvas);
    13.         currentAction = StartCoroutine(WaitForFormResponse(form));
    14.     }
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Did you hook up OnClickSubmit()? If so are you seeing the list of split-up words come out?
     
    Bunny83 likes this.
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    While there are many potential issues with closures inside coroutines, your code should work just fine. I used such a pattern quite often. Are you sure you subscribed to the "correct" InputForm?

    I would recommend adding some Debug.Log statement with a context object to your code. This one to your coroutine
    Code (CSharp):
    1. Debug.Log("WaitForFormResponse", (UnityEngine.Object)form));
    And those two to your OnClickSubmit method
    Code (CSharp):
    1. Debug.Log("OnClickSubmit object", gameObject);
    2. Debug.Log("OnClickSubmit inputField", inputField);
    With those log statements you can simply click on one of the logs in the console and Unity would "ping" / highlight the passed "context" object that was passed to Log. That helps identifying the actual objects you're working with.
     
  5. BenevolenceGames

    BenevolenceGames

    Joined:
    Feb 17, 2021
    Posts:
    128
    Looking more closely at the prefab, I guess I changed the name slightly from "OnSubmit" to "OnClickSubmit" and the stored prefab had a missing reference. Thank you both!
     
    Kurt-Dekker likes this.
  6. BenevolenceGames

    BenevolenceGames

    Joined:
    Feb 17, 2021
    Posts:
    128
    I'm not sure I'm following you all the way, but I'll implement it and see what happens. It would be nice to have deeper insight in the debugging phase, so I'll def try it.
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    Well, Debug.Log simply has a second optional argument which is a UnityEngine.Object reference. You can pass any tracked object inside Unity to this context argument. This context argument is stored with the log message internally. Just "select" the log message in the console and you will see that Unity will highlight that object in the hierarchy or the project view. So you know the exact object.

    Common issues are that events, callbacks or links are wrongly setup and may refer to a prefab instead to an instance in the scene. It's totally possible to call methods on prefab objects. Though the code would probably not behave the way you'd expect. Those are quite common mistakes. Though it looks like this should not be an issue in your case. However in a situation where you expect some code to run when it's not, it never hurts to temporarily add some more Debug.Logs to follow the execution trail to the point where it fails. Also I would always recommend to use a proper log message that is unique, so you can actually distinguish the messages clearly. Just logging a boolean value is bad. You may log boolean values at more than one place. That just causes confusion and you may think that you see your log statement but it may actually be from a completely different place. Your messages are actually quite good