• No results found

2.2 Building the Core Framework Scripts

2.2.1 BaseGameController.cs

The game controller acts as a hub for active game activity and a place where scripts that may not be directly connected can send messages to each other. By routing scripts through the game controller, they remain independent, and changing their behavior is a straight- forward process of changing how messages are dealt with here rather than across multiple scripts.

The core functions of the game controller are as follows:

1. Tracking game state

a. Storing the game state

b. Providing functions for changing the game state

c. Changing the game state based on calls to functions such as EndGame(), StartGame(), or PauseGame()

2. Creating any player object(s)

3. Setting up the camera (any specifics such as telling the camera which player to follow, etc.)

4. Communicating between session manager, user manager, and game actions (such as score, etc.)

5. Handling any communications between scripts that we would like to keep as standalone and not have to recode to talk directly to each other

Game controller is the core of gameplay, where overall game functions are defined and dealt with and where the current game state is held. Keeping track of the game state is important, as some elements will need to change their behavior based on this. If the game is paused, for example, we may want to suspend all input, freeze game time, and show a pop-up. When the game ends, we will need to disable player input and so on. Tracking game states is the job of the game controller script.

A typical game may have several different core states, such as

1. Game running

2. Game paused

3. Loading

13 2.2 Building the Core Framework Scripts

There may also be several custom states that are applicable to particular types of games, such as a state for showing a cutscene or perhaps a state for playing a special audio clip. I recommend creating a new state for any game action that affects how one or more of your scripts work. That way, you can always have the scripts rely on the game controller to know how to behave.

The base game controller script, found in Scripts/BASE, looks like this:

public class BaseGameController : MonoBehavior {

bool paused;

public GameObject explosionPrefab; public virtual void PlayerLostLife () {

// deal with player life lost (update U.I. etc.) }

public virtual void SpawnPlayer () {

// the player needs to be spawned }

public virtual void Respawn () {

// the player is respawning }

public virtual void StartGame() {

// do start game functions }

public void Explode ( Vector3 aPosition ) {

// instantiate an explosion at the position passed into this function Instantiate( explosionPrefab,aPosition, Quaternion.identity ); }

public virtual void EnemyDestroyed( Vector3 aPosition, int pointsValue, int hitByID )

{

// deal with enemy destroyed }

public virtual void BossDestroyed() {

// deal with the end of a boss battle }

public virtual void RestartGameButtonPressed() {

// deal with restart button (default behavior re-loads the // currently loaded scene)

Application.LoadLevel(Application.loadedLevelName); }

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

2.2.1.1 Script Breakdown

Many of the key functions in BaseGameController.cs are virtual, included to serve as an established protocol for dealing with different types of game activity. That is, they contain no code in this particular file, but the intention is that you override them in your own derived versions of a game controller later on.

The BaseGameController class derives from MonoBehavior so that it can tap into automatically called system functions such as Awake(), Start(), Update(), and FixedUpdate():

public class BaseGameController : MonoBehavior {

The functions are here as placeholders. The intention is that game controller scripts for use in actual game projects will derive from this class and populate these interface functions with functionality:

bool paused;

public GameObject explosionPrefab; public virtual void PlayerLostLife () {

// deal with player life lost (update U.I. etc.) }

public virtual void SpawnPlayer () {

// the player needs to be spawned }

public virtual void Respawn () {

15 2.2 Building the Core Framework Scripts

// the player is respawning }

public virtual void StartGame() {

// do start game functions }

Other functions in BaseGameController are there to help turn games around quickly. If there are things that you use in many different games, it may save time to include them all in a script like this from which you can derive all other game controllers. It saves having to rewrite the same code over and over again across multiple projects. One such example is the Explode() function, which does just that:

public void Explode ( Vector3 aPosition ) {

// instantiate an explosion at the position passed into this // function

Instantiate( explosionPrefab,aPosition, Quaternion.identity ); }

All Explode() does is instantiate a gameObject at a position passed in by the function caller. Later versions of game controller scripts will use a separate spawn manager to deal with instantiation, although at this stage, it is there simply to be as generic as possible by not being reliant on any other scripts.

After Explode, we see two more of those empty functions, used to tell the game con- troller when regular enemies are destroyed and when a boss is destroyed:

public virtual void EnemyDestroyed( Vector3 aPosition, int pointsValue, int hitByID )

{

// deal with enemy destroyed }

public virtual void BossDestroyed() {

// deal with the end of a boss battle }

All games will need some functions, such as a restart button and pause functions. In their simplest form:

public virtual void RestartGameButtonPressed() {

// deal with restart button (default behavior re-loads the // currently loaded scene)

Application.LoadLevel(Application.loadedLevelName); }

RestartGameButtonPressed() uses Unity’s Application.LoadLevel function to reload the current scene. Application.loadedLevelName returns a string referring to the name of the scene the game currently has loaded in memory. You can also get an index number

referring to the scene with Application.levelName. This index number ties up to how scenes are organized in the Build Settings (File → Build Settings), meaning that moving things around in build settings can affect how your game works if you choose to use index numbers to refer to specific scenes later on. To avoid any confusion, I prefer to stick to names whenever I deal with level loading.

The final part of the BaseGameController deals with the mechanics of pausing and unpausing a game:

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

A Boolean variable named paused holds the game pause state internally. Rather than provide direct access to this, a getter–setter function is used so that we can act when- ever the state of paused changes without having to monitor it.

The Get part simply returns the Boolean variable paused.

The Set part sets the Boolean variable paused and goes on to set Time.timeScale to either 0 (paused) or 1 (unpaused). Setting Time.timeScale affects how time passes. For example, setting timescale to 0.5 would mean that time passes 2× slower than real time. The Unity documentation states:

Except for realtimeSinceStartup, timeScale affects all the time and delta time measuring variables of the Time class.

If you lower timeScale it is recommended to also lower Time.fixedDeltaTime by the same amount.

FixedUpdate functions will not be called when timeScale is set to zero.

A regular videogame would display some sort of message to tell players whenever the game is paused, but at this stage, the script is purely providing the mechanics of pausing, and we will save concerning ourselves too much with user interface until Chapter 14.

17 2.2 Building the Core Framework Scripts