Home / Legacy / Lesson 10: The Game Manager

Lesson 10: The Game Manager

/
/
/
1091 Views
This entry is part 13 of 15 in the series Unity 3d Fundamentals Course

In the previous lesson we created the Stage Manager to deal with the stage state. Before continuing with this lesson don’t forget to add the remaining stage beacons and stage managers.

Lesson 10: The Game Manager

In this lesson we are going to create a Game Manager to coordinate the different stages and also to store the game statistics.

Lesson Outline

Create the Game Manager

The Game Manager will be responsible for controlling the game flow, managing the stages and storing the player statistics.

The best solution to implement the Game Manager would be the Singleton Pattern. However I won’t get into design patterns on this series. If you want to know more about design patterns and the Singleton check the Source Making.

Since we need to access the GameManager from different entities in our game lets use the unity tag system. Create an empty GameObject with a GameManager script and assign a new tag “Game Manager” to it.

Lesson 10: The Game Manager

Manage the Stages

The GameManager is responsible for coordinating the different stages. Each stage is being activated by the corresponding stage beacon. At the beginning all stage beacons  are disabled. When the Player picks up the weapon we will activate the first beacon allowing to activate the first stage. So our GameManager will need access to the different beacons on the scene.

Lets create a public reference to store all beacon objects.

Assign all beacon objects to the script array.

Assign the stage beacons in the correct order.

Lesson 10: The Game Manager

Now when the Player picks up the weapon we want to activate the first beacon. Since all beacons are inside the array in the correct order we can use a control variable to know which beacon to activate and use it to iterate the array. Create a private variable to hold the current beacon index.

Now we need a public method to activate a new beacon.

When this method is called we will activate the current beacon using the index variable and then increment its value. The next time this method is called, the next beacon will be activated and so forth.

To activate the first beacon we need to call this method as soon as the Player has the weapon. On the TriggerWeapon  script add the following code.

The first beacon is ready. The other ones will be active when the previous stage is completed. So we need to know when it happens. This is a responsibility of the StageManager. Each Stage will be completed when all targets are destroyed.

But right now the StageManager knows nothing about the targets being destroyed. So we need to make the TargetController tell his StageManager that he was destroyed. Lets create a new public method on the StageManager script to get this information.

When the number of destroyed targets equals the length of the initial array it means that all targets are destroyed.  First we need private variable to hold the number of destroyed targets.

We will increment this variable each time the method is called. When this variable equals the array length all targets are destroyed and the stage is clear.

Now when this happens we want to activate the next stage. Lets call it just like we did before. Also disable the Stage Manager object when done.

The TargetController will call this method when its being destroyed.

To finish lets add the code to verify if all stages were completed. This will happen when the current beacon index reaches the array length. In the Activate Stage Beacon method verify if we still have beacons to activate – the current index is less then the total length – and run the code we had before. If the current beacon index reached the array length we don’t have anymore beacons and the game is over. We will deal with this later.

Game Statistics

At the end of the game the Player will be presented with the following statistics:

  • Elapsed time;
  • Accuracy (ratio between the shots fired and the targets destroyed);

The Game Manager will be responsible for storing these statistics. Lets create the necessary variables to hold these values.

Make these variables of public access so we can check their value on the Inspector. Later they will be displayed on the screen for the Player.

Now lets deal with each value.

Elapsed Time

To measure each Player performance we will count the elapsed time since the Player picks up the weapon until all stages are completed. To get the total time duration we need to store the initial time so we can use it later to calculate the total one. Create a variable to hold the initial time.

This variable will hold the time value of the exact moment the Player picks up the weapon. On that exact moment the method Activate Stage Beacon is called to activate the first beacon so we will use it to assign the value. We just need to make sure that it only runs when the first beacon is activated.

Now that we have the initial time value we can get the total elapsed time by subtracting this value from the exact moment when all stages are clear. On the exact same method we already have access to that moment. So lets assign the total elapsed time.

Lesson 10: The Game Manager

 

The total elapsed time iis given in the total number of seconds. We will format this later to show it properly to the user.

Accuracy

The accuracy is another measure we will show the Player at the end of the game. It consists in the ratio between the number of destroyed targets and the total number of shots fired.

Lets create two new methods to increment these values.

Now that the Game Manager is ready to update these values lets call them. To maintain this simple lets call both methods from the Weapon script.

The Target Was Destroyed could be called from the Target Collider script to become independent of the weapon.

Since we need to access the Game Manager multiple times on the Weapon script lets create a private reference and assign its value at the beginning.

Now lets call the corresponding methods on the right place. The Shot Was Fired should be called right after the Player presses the Input.

The Target Was Destroyed should be called when the hit object is a target. So inside the raycast if block call the method.

Now when all stages are clear we need to calculate the Player accuracy.

Lesson 10: The Game Manager

The statistics are working but we have a problem. We should be gathering the data only when the first stage is enabled and not when the Player picks up the weapon. But right now the GameManager has no idea when it happens. So lets make our beacons tell the GameManager that the stage will be activated. Since we already have references to all beacons we can verify if the message is coming from the first one and then start counting the statistics.

Create a public method on the GameManager called StageWillStart and give it a GameObject beacon as argument.

If the method is being called from the first beacon we will start gathering the statistics. Lets create a control variable to know if we are in game mode.

Now when the first stage is about to start we will set the initial time – remove the already existing code – and make the GameManager turn into game mode.

Change the other statistics variables to only work when on game mode.

To finish we need to make the beacons call this method. Add the following line on the trigger enter method of the StageBeaconCollider.

Create a Game Pause Manager

In addition to the Game Manager we need to create another component to deal with the game pause state. This new component, let’s call it Game Pause Manager, is responsible for detecting when the player presses the Pause button and then toggle between both states.

First let’s create a new button on the Input Manager that we will use as the Pause Input. Create a new entry on the Input section of the Project Settings and call it Pause. I’ve assigned the “p” and the “escape” as primary and alternative buttons.

On a Web Player build, the escape unlocks the cursor by default. I’ve defined it here to also pause the game when the Player presses the escape.

Lesson 10: The Game Manager

 

Lesson 10: The Game Manager

Now create a new script called GamePauseManager.cs.

In the Update method add the necessary code to detect the Input on the Pause Button.

We also need a control variable to store the current game state.

Now lets create a new private method to toggle the game state. This method will be called from Update.

One aspect that must change when the game is paused is the cursor. The cursor should only be visible when the game is paused and always locked otherwise. We will use the method Screen.lockCursor which defines the cursor lock state. When enabled the cursor is automatically hidden, centered on view and made to never leave the view.

Lets start by locking the cursor at the beginning.

The lockCursor state will change with the game pause state.

Another aspect we need to take care is the Time.timeScale. This property defines at what speed the time is passing. By default it equals to 1 which means the game time will pass exactly as realtime. This property can be used to create a slow-motion effect, if we decrease the Time Scale below 1, or a fast-forward effect, if we increase the Time Scale above 1. We can also use it to pause the game by setting the Time Scale to zero.

On the Pause method change the Time Scale accordingly to the game state.

We need to force the cursor to lock again when not in Pause mode. Add the following verification on the Update method.

Add this script to the GameManager object.

Lesson 10: The Game Manager

Now when you start the game the cursor is automatically locked. If you press one of the defined buttons the cursor will be unlocked and the Player won’t be able to move. However the camera is still being controlled by the mouse movement and if we press the mouse button the weapon still fires.

To keep it really simple just add some public references to the MouseLook and the Weapon scripts and toggle their enabled state on the Pause method.

This is not the correct way to implement the Game Pause Manager. In a real game implementation I would probably have some IsPaused(bool isPaused) event on the manager that would be raised each time the game state changes. Then each component interested in the knowing about this event would register and perform its own actions. However this would be somewhat more advanced of what I’m trying to explain here so we will just use this really POOR SOLUTION. I’m sorry about that and I promise to make it right on the next series.

Full Codes

<GameManager>

 <StageManager>

Names to keep

What’s next…

On the following lesson we will work with the Unity GUI system and built-in animations to create our Game Menu and HUD.

 

Series Navigation<< Lesson 9: The Stage ManagerLesson 11: The UI Manager (Unity 3d GUI) >>
  • Facebook
  • Twitter
  • Google+
  • Linkedin
  • Pinterest
  • Reddit

Leave a Comment

Your email address will not be published. Required fields are marked *