I’m new to loading scenes. The scenario is this; on a field level, I bump into a monster. OnCollisionEnter sends a message to a GameManager that is on a Don’t Destroy on Load gameobject.
The GameManager’s coroutine that is called is as following:
public IEnumerator StartBattle(List<GameObject> enemies)
{
UnityEngine.SceneManagement.SceneManager.LoadScene("Battle Scene");
yield return new WaitForSecondsRealtime(.5f);
Debug.Log("Does the app reach here?"); // Doesn't reach here
BattleSystem battleSystem = GameObject.FindGameObjectWithTag("Battle System").GetComponent<BattleSystem>();
yield break;
}
It will execute the Load Scene, and the wait. If I remove the wait it will give me a bug that it can’t find the BattleSystem (presumably because the new scene hasn’t quite loaded yet). So, I added the wait.
However, the coroutine does not continue running after that. The Debug.Log(“Does the app reach here”) is never called. I’m stumped; this thing is on a DDOL object yet stops.
I saw some video’s on scene loading and I can’t work with constants here, nor playerprefs as it’s a Windows program. Do I really have to save things in between scenes or am I missing a way that this coroutine can keep running?
I got the wanted behaviour without a coroutine. I now use an enumerator that keeps the state of the Game.
public enum GameState { FIELD, BATTLEINIT, BATTLE}
I use an update function to check the state in the gamemanager.
If the state is BATTLEINIT, it will call a function. The function first checks whether the active scene is the battle scene, otherwise it returns.
When the function has properly executed it sets its state to Battle.
Update Method:
private void Update()
{
switch (GameState)
{
case GameState.FIELD:
break;
case GameState.BATTLEINIT:
SendToBattle();
break;
case GameState.BATTLE:
break;
default:
break;
}
}
It’s definitely not the best way to do it as SendToBattle will get called many times… But it’s the best solution I came up with. Found a lot of ‘answers’ including using OnEnable and OnDisable, which doesn’t work. This does.
I suspect you’ve used the OnCollisionEnter’s script’s StartCoroutine instead of the GameManager’s.
i.e. the difference between
void OnCollisionEnter(Collision collision)
{
// This starts the coroutine on the current script
StartCoroutine(GameManager.Instance.SendToBattle());
// This starts the coroutine on the game manager
GameManager.Instance.StartCoroutine(GameManager.Instance.SendToBattle());
}
In doesn’t matter which class the coroutine method is defined on, it only matters which MonoBehaviour’s StartCoroutine is called. If you start the coroutine on a script that is then unloaded during scene load, the coroutine will be stopped silently.
Thanks, I will try that out as well! I find it quite weird behaviour though, that apparently the program remembers where something started. I thought that as soon as it was fired it just keeps to itself. Thank you!