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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Beginning Unity 3D for iOS: Part 3/3
50 mins
- Getting Started: The End in Sight!
- Connect the Dots
- Create the Launcher
- Create the Obstacles
- Release the Krak… Err, Obstacles
- The Final Countdown
- Sometimes You Win, Sometimes You Lose
- Transformer-ing the Display Font
- It’s Always Play Time!
- Every Cube Deserves a Fresh Start
- This Message Won’t Self-Destruct
- Every Brave Cube Deserves a Soundtrack
- The Sounds of Victory and Defeat
- Thud in 3D
- A Little Cube Music
- Where To Go From Here?
The Final Countdown
Create a new script asset and name it GameController. Open the script, delete the stub functions and add the following code:
static var gameRunning : boolean = true;
var gameTimeAllowed : float = 20.0;
private var gameMessageLabel = "";
private var gameMessageDisplay : Rect;
private var timedOut : boolean = false;
private var gameTimeRemaining : float = gameTimeAllowed;
function Awake() {
gameMessageDisplay = Rect(10, 10, Screen.width - 20, 40);
}
function OnGUI() {
GUI.color = Color.yellow;
GUI.backgroundColor = Color.black;
var text : String = "";
if (timedOut) {
gameMessageLabel = "Time's up!!";
} else {
text = String.Format( "{0:00}:{1:00}", parseInt( gameTimeRemaining / 60.0 ), parseInt( gameTimeRemaining % 60.0 ) );
gameMessageLabel = "Time left: " + text;
}
GUI.Box(gameMessageDisplay, gameMessageLabel);
}
function Update() {
if (!gameRunning)
return;
// Keep track of time and display a countdown
gameTimeRemaining -= Time.deltaTime;
if (gameTimeRemaining <= 0) {
timedOut = true;
gameRunning = false;
}
}
Unity provides GUI controls that make it easy to add text labels and button functionality. The gameMessageDisplay variable controls where the display is shown. Here you set up the countdown timer to display across the top of the screen.
OnGUI() is called when an event occurs such as a mouse click, or at least once a frame. GUI.Box() creates a Box Control using the dimensions you set up initially and with the current game message, which consists of the countdown time info, a success message or a failure message.
The gameTimeAllowed variable represents the game timer and is set to 20 seconds. The gameTimeRemaining variable tracks the currently remaining time. It is initially set to the gameTimeAllowed value and is decremented by Time.deltaTime in Update().
Time.deltaTime is the time in seconds that the last frame took to complete. Keep in mind that the frame rate may vary and so this value may also vary. When the gameTimeRemaining value is below zero, the timedOut flag is set to true and the player is shown a timeout message.
The code also sets up a gameRunning flag to track if – you guessed it – the game is running. This is useful to stop the countdown logic and you’ll use it later on to control object behavior when the game is not running.
Attach the script to your Main Camera object:
Play the game and dawdle around until time runs out in order to test the countdown display and the failure case. It’s a little hard to see, but don’t worry, you’ll change that soon. Stop the game.
Sometimes You Win, Sometimes You Lose
You should display a success message when the Heroic Cube crosses the finish line, or rather the invisible wall – it deserves some encouragement for finishing the challenge! The message will include the time it took to complete the challenge.
You should also let the player know when time’s up!
The best place to set these messages is the GameController script. However, the finish line detection code is in another script: FinishLineDetection.
One way you can handle this is to define a function in GameController that the FinishLineDetection script can call when the player crosses the line. This function can then trigger the desired message display via the OnGUI() function.
Add two private variables to the GameController script. One will track the time to complete the challenge and the other will flag a successful mission (the following code can go below the other existing private variables):
private var missionCompleted : boolean = false;
private var missionCompleteTime : float = gameTimeAllowed;
Then add the following code to the end of the GameController script:
function MissionComplete() {
if (!gameRunning)
return;
missionCompleted = true;
gameRunning = false;
missionCompleteTime = gameTimeAllowed - gameTimeRemaining;
}
MissionComplete() checks if the game is running. If it is, it sets a private missionCompleted flag to true and the gameRunning flag to false. The time it took to complete the mission is then saved.
Now modify OnGUI() and add the success case (as shown below) to show the time it took to complete the message. The new code goes just after the var text : String = ""; line and alters the existing if condition:
if (missionCompleted) {
text = String.Format( "{0:00}:{1:00}", parseInt( missionCompleteTime / 60.0 ), parseInt( missionCompleteTime % 60.0 ) );
gameMessageLabel = "Mission completed in: " + text;
} else if (timedOut) {
gameMessageLabel = "Time's up!!";
...
Switch to the FinishLineDetection script and modify it as follows (the additions are marked with comments):
#pragma strict
var gameControllerScript : GameController; // 1: new
function OnTriggerEnter(other : Collider) {
if (other.gameObject.tag == "Player")
{
Debug.Log("You made it!!!");
gameControllerScript.MissionComplete(); // 2: new
}
}
@script RequireComponent(Collider)
The new code is numbered and does the following:
- Defines a public variable that points to the GameController script. You'll assign this shortly.
- Calls MissionComplete() in the GameController script to trigger the success case.
To assign the gameControllerScript variable, select the Goal GameObject, then select Inspector\Finish Line Detection and click the circular icon next to the Game Controller Script. In the pop-up dialog, select the Main Camera GameObject and close the dialog.
Play the game and dash to the finish line, dodging those nefarious blocks. Check that the correct message is displayed when you make it in time.
Stop the game and click Play once more. Test the failure case to make sure that that logic still works.
Transformer-ing the Display Font
You may have noticed, particularly if you have tested the game using Unity Remote or your iOS device, that the font displaying the game messages is very small. This is as good an excuse as any to learn about importing fonts into Unity.
There are a wealth of fonts you can get from sites such as http://dafont.com. The sample you’re going to use was built with the free Transformers Font. Yes, it’s the original font from the Transformers movie! Maybe your Cube and blocks are hiding alternate personalities. :]
I added the above font (and a few other resources you'll need later) to a Resources.zip file that you can here.
Download the resource archive and extract its contents. Find the font file and drag the Transformers Movie.ttf into your Project View\Assets folder to import it. Select the Transformers Movie asset in the Project View. The Inspector shows the import settings. Change the Font Size setting to 36. Click Apply.
You've just imported your custom font and it's ready for use in your project.
Open the GameController script to modify the message font. Define a public variable to set the font:
var gameMessageFont : Font;
Change the font used for display labels by modifying OnGUI(), as shown below:
function OnGUI() {
GUI.skin.font = gameMessageFont;
GUI.color = Color.yellow;
...
You assign the gameMessageFont public variable to GUI.skin.font to change the font.
Now select the Main Camera GameObject. Assign gameMessageFont to your newly imported font by dragging the font asset into the gameMessageFont variable.
Preview the game and verify that the messages are displayed using the new font.
Ah, much better!