I’m really struggling with coming up with the most elegant way to sequence a very simple chain of events in my GameManager.
The problem is similar but what is discussed here but involves the overall sequence of game events.
I’d like to do some cleanup (disable all enemies and player), then display a “Level Starting” with a level number for 3 seconds, then spawn everything. My GameManager script is on the same object as a UIManager script and I’d like to keep the UI separate from the game logic. I can easily achieve what I want by using events or C# Action, the GameManager invoking an event and the UIManager responding to it. But it seems too convoluted for what I need (the UIManager is the only script interested in displaying a “Level Starting” message). So I’m trying this by coupling the UIManager to the GameManager script, like this:
void Awake()
{
// Check for unconnected prefabs
Assert.IsNotNull(PrefabAsteroid);
Assert.IsNotNull(PrefabUFO);
Assert.IsNotNull(player);
// Reset the count variable
AsteroidController.countAsteroids = 0;
// Connect to the UIManager
UIManager = GetComponent<UIManager>();
// Set the level number
level = 0;
}
Then I start the game sequence as a coroutine, like this:
void Start()
{
// Instantiate the player
// This GameObject is persistent and doesn't get
// destroyed until the end of the game.
player = Instantiate(player, Vector2.zero, Quaternion.identity);
player.Lives = 3;
StartCoroutine(GameSequence());
}
Now I can tell the UI to display the message I need and do the next steps after some time:
IEnumerator GameSequence()
{
// Disable player & enemies
// Some function here
// Display the level number
UIManager.AnnounceLevel(level);
yield return new WaitForSeconds(3);
// Spawn asteroid
// Start the UFO spawner
// Spawn player
// etc...
// Restart when level is clear
}
However this way of sequencing stuff presents many problems, at least the way I see it:
-
The UIManager is responsible for displaying the “Starting Level” message but it also handles its duration on the screen (3 seconds, set in UIManager). If I ever need to change it I have to do it in two places. If I pass the required duration to the UIManager and use the same variable in the yield statement I’m essentially making the GameManager decide how long the UI displays the message. What I if I want later to have the UI do a flashy 12-second animation when the level starts?
-
Again, this can be solved with events but then I’d need the UIManager to invoke an event saying “I’ve finished”, which is going to make the GameManager coroutine too complex in handling that event (at least for me).
-
It seems weird to have the entire game sequence inside a coroutine.
How would you achieve something as simple as that without over-engineering everything? Seems like a trivial thing to do, and I more or less managed to make it work, but it seems over-engineered to me.
Thanks a lot for your help.