Home > Enterprise >  How to exit from coroutine in unity in specific condition?
How to exit from coroutine in unity in specific condition?

Time:03-28

i have some problems with coroutines in unity. I want that my player when he gets to the door (when a collision occurs) to enter in the tower after 3 seconds, and if he moves within less than 3 seconds from the door to close the door and not load a new scene. I tried most of things but doesn't work. Can somebody help or give me some hint?

Here is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Door : MonoBehaviour
{
[SerializeField] private Animator animator;
bool open = false;
// Start is called before the first frame update
void Start()
{
    animator = GetComponent<Animator>();
}

// Update is called once per frame
void Update()
{

}

public void OnTriggerStay2D(Collider2D collider)
{
    if (collider.gameObject.tag == "Player")
    {
        animator.SetBool("opening", true);
        StartCoroutine("LoadLevelTowerAfterDelay");
    }
    else
    {
        animator.SetBool("opening", false);
        StopCoroutine("LoadLevelTowerAfterDelay");
    }
}
IEnumerator LoadLevelTowerAfterDelay()
{

    if (GameManager.sharedInstance != null)
    {
        yield return new WaitForSeconds(3);
        GameManager.sharedInstance.LoadLevelTower();
    }
}

}

CodePudding user response:

One option is: If something happens that makes you want to cancel the operation, set a boolean somewhere and check for it immediately before the LoadLevelTower() line in the coroutine.

Another option is to keep a reference to the coroutine (e.g. Coroutine c = StartCoroutine("LoadLevelTowerAfterDelay");), then if something happens that makes you want to abort it, use StopCoroutine(c);.

I think your larger problem might be in your use of OnTriggerStay2D though. To me it looks like you’re calling StartCoroutine every frame while a player is within the collider, and StopCoroutine every frame while something other than a player is within the collider. Probably you instead want to be using OnTriggerEnter2D to check for a player entering, and OnTriggerExit2D to check for a player exiting?

CodePudding user response:

OnTriggerStay2D is called every physics update frame!

You definitely do NOT want to start a new coroutine every physics frame!

What you rather want to do is using OnTriggerEnter2D and OnTriggerExit2D like e.g.

private void OnTriggerEnter2D(Collider2D collider)
{
    if (!collider.gameObject.CompareTag("Player")) return;
    
    animator.SetBool("opening", true);
    StartCoroutine(LoadLevelTowerAfterDelay());
}

private void OnTriggerExit2D(Collider2D collider)
{
    if (!collider.gameObject.CompareTag("Player")) return;
    
    animator.SetBool("opening", false);
    StopCoroutine(LoadLevelTowerAfterDelay());
}

in general this should already work but to be save you could store the started routine as also mentioned here

private Coroutine currentRoutine;

private void OnTriggerEnter2D(Collider2D collider)
{
    if (!collider.gameObject.CompareTag("Player")) return;
    
    // This should actually not happen
    if(currentRoutine != null)
    {
        Debug.LogError("Huh?!", this);
        return;
    }

    animator.SetBool("opening", true);
    currentRoutine = StartCoroutine(LoadLevelTowerAfterDelay());
}

private void OnTriggerExit2D(Collider2D collider)
{
    if (!collider.gameObject.CompareTag("Player")) return;
    
    // This should actually not happen
    if(currentRoutine == null)
    {
        Debug.LogError("Huh?!", this);
        return;
    }

    animator.SetBool("opening", false);
    StopCoroutine(currentRoutine);
    currentRoutine = null;
}
  • Related