While Unity is amazingly easy for developers to set up new projects in and start hacking a prototype, eventually a developer realizes there are common elements to the games he or she creates. Such a developer then begins to develop a manager script containing the very basic components a game might require in the hopes that this will speed up the development of prototypes. As of recently, I am such a developer.

The BaseGameManager

The main argument for setting up a game in a manager -> controller system is modularity. If games are built using managers and controllers, moving objects between projects becomes very easy. As an indie game developer, there are a lot of objects I tend to reuse, thus developing in this method becomes very useful for testing how something in a previous project might work in a new project, and vice versa.

The core functions of a game manager (not specifically the BaseGameManager) are as follows:

  • Tracking game state.
  • Creating player objects.
  • Setting up the main camera.
  • Communicating between different managers (I will make additional blog posts later about other generic managers, stay tuned).
  • Handling communications between scripts that we want to keep isolated (indirect communication between such scripts).

The manager is where overall game functions are defined and dealt with. In addition, this would handle core states of the game, such as running, paused, loading, ended, etc. Each game will have specific states depending on project requirements, so this script will initially only provide states that are universal to almost every game genre. Note that I am not advocating a Playmaker approach here – states are useful, but not every game (outside the main menu; even this could have exceptions) needs a state machine. However, states are useful for a variety of things, such as showing a cutscene (disabling player movement during a cutscene state), or a state in which a particular sound might be played in world space.

BaseGameManager.cs

using UnityEngine;
using System.Collections;

public class BaseGameManager : MonoBehaviour {
                
    bool paused;
    
    public virtual void PlayerLostHealth () {
        // deal with player health lost (update U.I. etc.)
    }
    
    public virtual void SpawnPlayer () {
        // spawn the player
    }
    
    public virtual void Respawn () {
        // respawn the player, possibly in a respawn location
    }
    
    public virtual void StartGame () {
        // handle start of game
    }

    public virtual void RestartCurrentLevel () {
        // Reload current scene.
        Application.LoadLevel(Application.loadedLevelName);
    }
    
    public virtual void EnemyDestroyed (Vector3 aPosition, int pointsValue, int hitByID) {
        // handle what happens (score update, etc.) when an enemy is destroyed
    }
    
    public bool Paused {
        get { 
            // get paused
            return paused; 
        } set {
            // set paused 
            paused = value;

            if (paused) {
                // pause time
                Time.timeScale= 0f;
            } else {
                // unpause Unity
                Time.timeScale = 1f;
            }
        }
    }
    
}

The Case for Virtual

Most of the functions are placeholders and declared ‘virtual’ for the developer to extend later on. The idea is we should be able to drop the BaseGameManager script into any new project and then create a specific GameManager script that extends the BaseGameManager. The BaseGameManager by itself provides two useful functions for testing: Paused and RestartCurrentLevel. In production, a game would display a message to the player or provide a menu when the game is paused (and possibly provide options for restarting the current level), but having these ready from the outset is often invaluable for testing.

Other extensible functions such as Spawn and Respawn are included because they are often necessary at some point. While Unity is easy enough to drag and drop the player character into a level so that it is already in the scene upon game start, it is often necessary to include a Spawn function to instantiate the player on the fly. This becomes incredibly useful during the QA phase – many developers tend to test their games manually, but an increasing trend in game development is to move toward test-driven development (and in particular, automated testing) to stress test scenes. For example, if we were creating a platforming game, it would be invaluable for us to create a platforming AI behavior at some point so we are able to do hundreds of tests on a particular scene automatically.

Up Next: The Scene Manager

This wraps up the BaseGameManager. You can find the next post covering the Scene Manager here: https://www.zesix.com/2015/02/unity-scenemanager-c-sharp/