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;
}