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 Start and stopping coroutine in Invoked function

Discussion in 'Scripting' started by KitzuGG, Jun 4, 2023.

  1. KitzuGG

    KitzuGG

    Joined:
    Oct 22, 2022
    Posts:
    2
    Hello, sorry if this question was already answered but I could not find anything about it (or I just might be dumb)

    Context:
    Using Unity 2022.3.0f1
    I was using the new Input System, using Actions (System Action, not UnityAction) and Invokes when buttons are pressed (using the generated Input System cs file and a personal Input Manager), until I noticed an Invoked function started a coroutine only once.


    I tried in a separate project if I made a coding error myself or it doesn't work to begin with (without Input System)

    The problem encountered:
    Invoked Function starts a coroutine (by IEnumerator) only the first time Invoked, and then just doesn't (despite the function is always Invoked normally)

    This is (somewhat) how I replicated/isolated the problem

    Code (CSharp):
    1.  
    2. private Action myAction;
    3. private IEnumerator coroutine;
    4.  
    5. private void Awake(){
    6.    coroutine = myCoroutineFunc();
    7. }
    8.  
    9. private void OnEnable(){ myAction += InvokedFunction; }
    10. private void OnDisable(){ myAction -= InvokedFunction; }
    11.  
    12. private void Update(){
    13.    if(Input.GetKeyDown(KeyCode.Space))
    14.       myAction?.Invoke();
    15. }
    16.  
    17. private void InvokedFunction(){
    18.    Debug.Log("Function Called");
    19.    StopCoroutine(coroutine);
    20.    StartCoroutine(coroutine);
    21. }
    22.  
    23. private IEnumerator myCoroutineFunc(){
    24.    Debug.Log("Coroutine started");
    25.  
    26.    while(true){
    27.       yield return new WaitForSeconds(1);
    28.       // this is where I will handle the code and exit conditions
    29.    }
    30. }
    31.  
    What I think this (should) do is
    - invoke the Action's function
    - stop the coroutine if it's running
    - start the coroutine (so there is only one running)

    What does it do:
    - (first) invoke the Action's function
    - run the coroutine correctly
    - (next) invoke the Action's function again
    - doesn't stop coroutine if it's still running
    - doesn't start coroutine

    What else did I try:
    - Calling StartCoroutine and StopCoroutine with (myCoroutineFunc()) instead of IEnumerator value. This way StartCoroutine started new coroutines but StopCoroutine couldn't stop the previous ones (unless I used StopAllCoroutines, but I prefer not since I would like to use other coroutines)

    - Tested the coroutine number with an incremental value
    Code (CSharp):
    1.  
    2. private int test = 0;
    3. private IEnumerator coroutine;
    4. // ...
    5.  
    6. private void Awake{ coroutine = myCoroutineFunc(test);}
    7.  
    8. // ...
    9.  
    10. private void InvokedFunction(){
    11.    test++;
    12.    StopCoroutine(coroutine);
    13.    StartCoroutine(coroutine);
    14. // also tested with Stop/StartCoroutine(myCoroutineFunc(test));
    15. }
    16. private void myCoroutineFunc(int num){
    17.    while(true){
    18.       Debug.Log("This is coroutine number " + num);
    19.       yield return new WaitForSeconds(1);
    20.    }
    21. }
    22.  
    These just confirmed my mistakes before: I can't start a new one (with StartCoroutine(coroutine)) or I can't stop previous coroutine and starting a new one (with StartCoroutine(myCoroutineFunc())


    Question:
    - Am I doing something wrong? Like I am not getting how Coroutines work?
    - Is this a bug or simply wasn't intended to happen?
    - Am I trying to do something so stupid and need to rework my codebase?
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,834
    Code (CSharp):
    1. Coroutine coroutine = StartCoroutine(SomeIEnumeratorFunction());
    2.  
    3. // ...
    4.  
    5. StopCoroutine(coroutine);
    And if I have to restart it, I would use the first line again. Now, I think what you're doing is supposed to be legit, but I think of the return value of StartCoroutine as a token to the actual running coroutine. That's why the return value is of Coroutine type, not IEnumerator type.
     
    KitzuGG likes this.
  3. KitzuGG

    KitzuGG

    Joined:
    Oct 22, 2022
    Posts:
    2
    I tested quickly and it seems to be working, thank you so much!