Beginning Unity 3D for iOS: Part 3/3

This is a post by Tutorial Team Member Christine Abernathy, an Engineer on the Developer Advocacy team at Facebook. You can also find her on Google+. Welcome to the third and final part the Beginning Unity 3D for iOS tutorial series! In the first part of this series, you toured the basic Unity tools, created […] By Christine Abernathy.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 6 of this article. Click here to view the first page.

It’s Always Play Time!

Next, create an in-game button that will control the start of the game and allow the player to restart after a success or failure. You'll display the button whenever the game is not running. Recall that you defined a gameRunning flag that you can use to control the button's visibility.

To create the play button and related functionality, you must modify the GameController script. First define a private variable that controls the play button text:

private var playButtonText = "Play";

Then add a new function called startGame() that sets up a new game:

function startGame() {
    // Reset if starting a new game
    gameTimeRemaining = gameTimeAllowed; 
    timedOut = false;
    missionCompleted = false;
       
    // Change button text after the initial run
    playButtonText = "Play Again";
    
    // Kick off the game
    gameRunning = true;
}

Now modify OnGUI() to show the button when the game is not running by adding the following code to the end of OnGUI() (after all the existing code):

    // The menu button
    if (!gameRunning) {
        var xPos = Screen.width / 2 - 100;
        var yPos = Screen.height / 2 + 100;
        if( GUI.Button( new Rect( xPos, yPos, 200, 50 ), playButtonText ) ) {
            startGame();
        }
    }   

Finally, set the gameRunning flag to false. Just modify the existing line for the variable to switch the initial value from true to false:

static var gameRunning : boolean = false;

OnGUI() places a button using the GUI.Button() function. The button text is a variable, so it says "Play" initially and "Play Again" every subsequent time.

GUI.Button() is wrapped in an if statement. This returns true if the button is clicked. When the user clicks the button, you kick off the game. startGame() first initializes the game, changes the play button text and finally sets the gameRunning flag to true.

Preview the game in the Unity Editor. Verify that the play button is initially visible and is hidden after you click on it. Verify also that when a run is completed, the play button becomes visible once again and that the text has changed from "Play" to "Play Again". Note that each time you click on the play button after the first time, the time is reset and the countdown starts afresh.

But also notice that the player can move even before the play button is tapped. That's a little annoying, isn't it? Don’t let your Heroic Cube get a head start!

To take care of that detail, make use of the gameRunning variable, which is a global variable by virtue of the static modifier. Add the following code to the top of Update() in the MoveAround script:

   if (GameController != null && !GameController.gameRunning)
       return;

You should also disable the launcher from dropping obstacles when the game is not running. Add the following code at the top of Update() in the ObstacleLauncher script:

   if (GameController != null && !GameController.gameRunning)
       return;

Preview the game to ensure that when the game is not running, the player can’t move and obstacles are not launched.

Every Cube Deserves a Fresh Start

While the play button works correctly now, you may notice that even though the timer is reset when a new game is started, other aspects of the game are not reset.

The obstacles stop falling, as they've probably reached the maximum spawn count, but they don't disappear. Nor does the Heroic Cube revert back to its original position. A true reset requires that the game start fresh, i.e., the obstacles are cleared and reloaded and the player position is reset.

The ideal way to accomplish this is to send a message to all interested parties to reset themselves. The Heroic Cube would then slink back to its original position and the launcher would reload.

One way to do this is to have a reset function defined in a script that handles the reset behavior. GameObject.SendMessage() can then be used to call this reset function in the hope that a component (a script) attached to the GameObject handles the function call.

Here's how you'll implement this:

  1. You'll define a function called resetGame() in the MoveAround script that resets the player's position to the original position when the game started.
  2. You'll define a function called resetGame() in the ObstacleLauncher script to reset the obstacle count to zero.
  3. You'll loop through a given list of GameObjects that include the player and launcher GameObjects, calling GameObject.SendMessage("resetGame", …) to initiate the reset.
  4. You'll add the reset logic in GameController when the user resets the game.

But code speaks louder than words. First, open the MoveAround script and add the following variables and functions to it:

var originalPosition : Vector3;
var originalRotation : Quaternion;

function Awake() {
    originalPosition = transform.position;
    originalRotation = transform.rotation;
}

function resetGame() {
    // Reset to original position
    transform.position = originalPosition;
    transform.rotation = originalRotation;
}

Then open the ObstacleLauncher script and add this new function:

function resetGame() {
    // Reset to original data
    numObstaclesLaunched = 0;
}

Next open the GameController script and add the following variable:

var gameObjectsToReset : GameObject [];

The above line defines an array of GameObjects that will have the resetGame function called on them to initiate a reset.

Now replace the existing startGame() function with the following (or just update the code to match):

function startGame() {
    // Reset if starting a new game
    gameTimeRemaining = gameTimeAllowed; 
    timedOut = false;
    missionCompleted = false;
       
    // Change button text after the initial run
    playButtonText = "Play Again";
    
    // Clean out any enemy objects
    var enemies = GameObject.FindGameObjectsWithTag("Enemy");
    for (var enemy : GameObject in enemies) {
        Destroy ( enemy);
    }
    // Call all game reset methods
    for (var gameObjectReceiver : GameObject in gameObjectsToReset) {
        gameObjectReceiver.SendMessage("resetGame", null, SendMessageOptions.DontRequireReceiver);
    }
    
    // Kick off the game
    gameRunning = true;
}

The new code clears out all enemy instances by looking for GameObjects with the Enemy tag. Destroy() is called on the enemy GameObjects. This clears out the obstacles in the scene.

Then the code processes the gameObjectsToReset array and sends a message to each GameObject to call resetGame(). It is not mandatory for a component in the array to have implemented resetGame(). You need to assign the objects to process.

Now select the Main Camera object and note the new public variable for Game Objects To Reset:

Game Objects To Reset variable created.

Set the Size to 2. The array elements will expand. Assign the Player GameObject to Element 0 and the Launcher GameObject to Element 1.

Game Objects To Reset array variables assigned.

Preview the game and verify that the game fully resets itself after a success or failure. Verify that the player position resets to the original one, that the obstacles are cleared, and that the obstacles start falling once more when the game is restarted.

Christine Abernathy

Contributors

Christine Abernathy

Author

Over 300 content creators. Join our team.