Scripting Game Mechanics

We're jumping now...

Enumerations are super powerful tools in C#. In the Hero Born PlayerBehavior code, we use an enumeration to get keyboard input using the KeyCode enum. Without the use of a layer mask, the player can hit the key repeatedly. If we set the program to use the space bar as the jump key, as it stands we could hit the space bar over and over again and the player would continue to get higher and higher in the game.

A layer mask is like an invisible group that GameObjects can belong to. They are used by the physics system to check anything from movement to collider components. They can also be used to check if the player is touching the ground.

Ok so jumping in Unity/book, uses a layer mask that we've defined as the ground layer to test against the player to see if he is touching it. If the player is touching the ground, a Boolean true is returned from the created method. This is then feed into the jumping mechanism using the && operator in if statement allowing the jump action to complete. If the Boolean value is set to false the if statements && operation fails preventing the infinite jumping hack.

if (IsGrounded() && _isJumping)
{
    _rb.AddForce(Vector3.up * JumpVelocity, ForceMode.Impulse);
}
_isJumping = false;
private bool IsGrounded()
{
    Vector3 capsuleBottom = new Vector3(_col.bounds.center.x,
        _col.bounds.min.y, _col.bounds.center.z);

    bool grounded = Physics.CheckCapsule(_col.bounds.center,
        capsuleBottom, DistanceToGround, GroundLayer,
        QueryTriggerInteraction.Ignore);

    return grounded;
}

Pew Pew Pew ... We're shooting

So the shooting mechanic involves creating a bullet prefab. This is done by creating a sphere 3d object and adding a RigidBody to the bullet. In the book we're using the left mouse button to fire the bullet and that is done using the Input.GetMouseButtonDown(0) code; 0 is the left button and 1 is the right button. This works but then calling the Instantiate() method creating a new bullet and launching it in the direction the player is facing. There is a draw back to this as it causes a build up of spent Bullet objects which could cause performance issues in the game. What we need to do is destroy the spent bullets after a certain amount of time. This is done using the Destroy call and providing it a float parameter to use as a delay.

Game Management

Game management in this context is about managing who can access what variables and methods in a safe manner. This is done using a manager class. A manager class is used as a single contact point to keep things from getting messy during communications and updates between different classes.

** Fun Fact ** GameManager is a reserved name in Unity. If you name your game manager GameManager you will get a cogwheel icon next to your script instead of the C# icon.

The get and set properties are used in C# to allow access to a private variable from other classes. To interact with the private variables you need to create a public variable counter part that contains the set and get properties. In these functions you use get to get the value of the private variable and use set to set the value of the private variable.

UI - User Interface

What good is a game if there isn't a UI to track all the cool things you are doing. In the Hero Born game, we have a Lives variable and a Item variable that we can display out to the user through the user interface.

Unity - Scripting API: GUI
GUI items in upper left and progress text centered on the bottom.

Ok, so to generate the above UI elements, a new namespace was needed called UnityEngine.UI which gives us access to the Text variable type. Next we needed a variable to set the max numbers of items in our level which helps to determine when the level has been won. Then we needed three text variables to hold the player health, items collected, and progress text.

When an item is collected the Items Collected text variable is changed to reflect the number of items collected and the progress bar is changes to show how many items remain to be collected or if we've collected all of the items it tells us we've won. Every time a player is damaged the Player Health text will be modified showing the remaining health.

Winning or Losing

So now we need to figure out how to create the conditions for winning or losing. This is done through subtracting from the Player Health. If a player has collected all the items and the player health is one or greater the player wins. If the Player Health reaches 0 then you lose. So to show the player that they have won, a button is used. So that the button doesn't always show You Won!, its been hidden. At some point I guess we'll reactivate it using code when the player wins.

How do you pause this thing

My kids always tell me they can't pause the games they are playing on their tablets. I'm about to figure out how to do that so I can shut them down next time they tell me that.

So in the game after the player wins a screen pops up telling the player they won. However the player still has control of the capsule and can move about the level. This is fixed using the Time.timeScale method with a value set to 0. This effectively freezes the game. Now to restart the game we use a new Unity namespace called SceneManagement. SceneManagement has a function called LoadScene that takes a paramenter of the scene you want to reload too. In my case, I only have one scene so my restart scene function looks like this:

public void RestartScene()
    {
        SceneManager.LoadScene(0);
        Time.timeScale = 1f;
    }

Now to get this to work in Unity we have to add the game behavior script to the win condition object. This allows me to use a function from Game_Manager to call GameBehavior.RestartScene.

That's all for chapter 8 of the book. That one took me a little longer than I expected. It was a really good chapter on game mechanics.

See ya later.

Don