Unity 3D Game Development: Don't Be a Clock Blocker

Exclusive offer: get 50% off this eBook here
Unity 3D Game Development by Example Beginner's Guide

Unity 3D Game Development by Example Beginner's Guide — Save 50%

A seat-of-your-pants manual for building fun, groovy little games quickly

$26.99    $13.50
by Ryan Henson Creighton | September 2010 | Beginner's Guides Web Graphics & Video

One cheap, effective way of amping up the game experience is to add a clock. Games have used clocks to make us nervous for time immemorial, and it's hard to find a video game in existence that doesn't include some sort of time pressure—from the increasing speed of falling Tetris pieces, to the countdown clock in every Super Mario Bros. level, to the egg timers packaged with many popular board games like Boggle, Taboo, and Scattergories.

This article by Ryan Henson Creighton, author of Unity 3D Game Development by Example Beginner's Guide, shows you how to build three different game clocks: a number-based clock, a depleting bar clock, and a cool pie wedge clock, all of which use the same underlying code. You can then reuse the code in a game of your own.

 

Unity 3D Game Development by Example Beginner's Guide

Unity 3D Game Development by Example Beginner's Guide

A seat-of-your-pants manual for building fun, groovy little games quickly

  • Build fun games using the free Unity 3D game engine even if you've never coded before
  • Learn how to "skin" projects to make totally different games from the same file – more games, less effort!
  • Deploy your games to the Internet so that your friends and family can play them
  • Packed with ideas, inspiration, and advice for your own game design and development
  • Stay engaged with fresh, fun writing that keeps you awake as you learn

Read more about this book

(For more resources on Unity 3D, see here.)

We've taken a baby game like Memory and made it slightly cooler by changing the straight-up match mechanism and adding a twist: matching disembodied robot parts to their bodies. Robot Repair is a tiny bit more interesting and more challenging thanks to this simple modification.

There are lots of ways we could make the game even more difficult: we could quadruple the number of robots, crank the game up to a 20x20 card grid, or rig Unity up to some peripheral device that issues a low-grade electrical shock to the player every time he doesn't find a match. NOW who's making a baby game?

These ideas could take a lot of time though, and the Return-On-Investment (ROI) we see from these features may not be worth the effort. One cheap, effective way of amping up the game experience is to add a clock.

Apply pressure

What if the player only has x seconds to find all the matches in the Robot Repair game? Or, what if in our keep-up game, the player has to bounce the ball without dropping it until the timer runs out in order to advance to the next level? In this article let's:

  • Program a text-based countdown clock to add a little pressure to our games
  • Modify the clock to make it graphical, with an ever-shrinking horizontal bar
  • Layer in some new code and graphics to create a pie chart-style clock

That's three different countdown clocks, all running from the same initial code, all ready to be put to work in whatever Unity games you dream up. Roll up your sleeves—it's time to start coding!

Time for action – prepare the clock script

Open your Robot Repair game project and make sure you're in the game Scene. We'll create an empty GameObject and glue some code to it.

  1. Go to GameObject | Create Empty.
  2. Rename the empty Game Object Clock.
  3. Create a new JavaScript and name it clockScript.
  4. Drag-and-drop the clockScript onto the Clock Game Object.

No problem! We know the drill by now—we've got a Game Object ready to go with an empty script where we'll put all of our clock code.

Time for more action – prepare the clock text

In order to display the numbers, we need to add a GUIText component to the Clock GameObject, but there's one problem: GUIText defaults to white, which isn't so hot for a game with a white background. Let's make a quick adjustment to the game background color so that we can see what's going on. We can change it back later.

  1. Select the Main Camera in the Hierarchy panel.
  2. Find the Camera component in the Inspector panel.
  3. Click on the color swatch labeled Back Ground Color, and change it to something darker so that our piece of white GUIText will show up against it. I chose a "delightful" puce (R157 G99 B120).
  4. Select the Clock Game Object from the Hierarchy panel. It's not a bad idea to look in the Inspector panel and confirm that the clockScript script was added as a component in the preceding instruction.
  5. With the Clock Game Object selected, go to Component | Rendering | GUIText. This is the GUIText component that we'll use to display the clock numbers on the screen.
  6. In the Inspector panel, find the GUIText component and type whatever in the blank Text property.

    In the Inspector panel, change the clock's X position to 0.8 and its Y position to 0.9 to bring it into view. You should see the word whatever in white, floating near the top-right corner of the screen in the Game view..

Right, then! We have a Game Object with an empty script attached. That Game Object has a GUIText component to display the clock numbers. Our game background is certifiably hideous. Let's code us some clock.

Still time for action – change the clock text color

Double-click the clockScript. Your empty script, with one lone Update() function, should appear in the code editor. The very first thing we should consider is doing away with our puce background by changing the GUIText color to black instead of white. Let's get at it.

  1. Write the built-in Start function and change the GUIText color:

    function Start()
    {
    guiText.material.color = Color.black;
    }
    function Update() {
    }

  2. Save the script and test your game to see your new black text.

If you feel comfy, you can change the game background color back to white by clicking on the Main Camera Game Object and finding the color swatch in the Inspector panel. The white whatever GUIText will disappear against the white background in the Game view because the color-changing code that we just wrote runs only when we test the game (try testing the game to confirm this). If you ever lose track of your text, or it's not displaying properly, or you just really wanna see it on the screen, you can change the camera's background color to confirm that it's still there.

If you're happy with this low-maintenance, disappearing-text arrangement, you can move on to the Prepare the clock code section. But, if you want to put in a little extra elbow grease to actually see the text, in a font of your choosing, follow these next steps.

Time for action rides again – create a font texture and material

In order to change the font of this GUIText, and to see it in a different color without waiting for the code to run, we need to import a font, hook it up to a Material, and apply that Material to the GUIText.

  1. Find a font that you want to use for your game clock. I like the LOLCats standby Impact. If you're running Windows, your fonts are likely to be in the C:\Windows\Fonts directory. If you're a Mac user, you should look in the \Library\Fonts\ folder.
  2. Drag the font into the Project panel in Unity. The font will be added to your list of Assets.
  3. Right-click (or secondary-click) an empty area of the Project panel and choose Create | Material. You can also click on the Create button at the top of the panel.
  4. Rename the new Material to something useful. Because I'm using the Impact font, and it's going to be black, I named mine "BlackImpact" (incidentally, "Black Impact" is also the name of my favorite exploitation film from the 70s).
  5. Click on the Material you just created in the Project Panel.
  6. In the Inspector panel, click on the color swatch labeled Main Color and choose black (R0 G0 B0), then click on the little red X to close the color picker.

  7. In the empty square area labeled None (Texture 2D), click on the Select button, and choose your font from the list of textures (mine was labeled impact - font texture).
  8. At the top of the Inspector panel, there's a drop-down labeled Shader. Select Transparent/Diffuse from the list. You'll know it worked when the preview sphere underneath the Inspector panel shows your chosen font outline wrapped around a transparent sphere. Pretty cool!

  9. Click on the Clock Game Object in the Hierarchy panel.
  10. Find the GUIText component in the Inspector panel.
  11. Click and drag your font—the one with the letter A icon—from the Project panel into the parameter labeled Font in the GUIText component. You can also click the drop-down arrow (the parameter should say None (Font) initially) and choose your font from the list.
  12. Similarly, click-and-drag your Material—the one with the gray sphere icon—from the Project panel into the parameter labeled Material in the GUIText component. You can also click on the drop-down arrow (the parameter should say None (Material) initially) and choose your Material from the list.

Just as you always dreamed about since childhood, the GUIText changes to a solid black version of the fancy font you chose! Now, you can definitely get rid of that horrid puce background and switch back to white. If you made it this far and you're using a Material instead of the naked font option, it's also safe to delete the guiText.material.color = Color.black; line from the clockScript.

Time for action – what's with the tiny font?

The Impact font, or any other font you choose, won't be very… impactful at its default size. Let's change the import settings to biggify it.

  1. Click on your imported font—the one with the letter A icon—in the Project panel.
  2. In the Inspector panel, you'll see the True Type Font Importer. Change the Font Size to something respectable, like 32, and press the Enter key on your keyboard.
  3. Click on the Apply button. Magically, your GUIText cranks up to 32 points (you'll only see this happen if you still have a piece of text like "whatever" entered into the Text parameter of the GUIText of the Clock Game Object component).

What just happened - was that seriously magic?

Of course, there's nothing magical about it. Here's what happened when you clicked on that Apply button:

When you import a font into Unity, an entire set of raster images is created for you by the True Type Font Importer. Raster images are the ones that look all pixelly and square when you zoom in on them. Fonts are inherently vector instead of raster, which means that they use math to describe their curves and angles. Vector images can be scaled up any size without going all Rubik's Cube on you.

But, Unity doesn't support vector fonts. For every font size that you want to support, you need to import a new version of the font and change its import settings to a different size. This means that you may have four copies of, say, the Impact font, at the four different sizes you require.

When you click on the Apply button, Unity creates its set of raster images based on the font that you're importing.

Unity 3D Game Development by Example Beginner's Guide A seat-of-your-pants manual for building fun, groovy little games quickly
Published: September 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Read more about this book

(For more resources on Unity 3D, see here.)

Time for action – prepare the clock code

Let's rough in a few empty functions and three variables that we'll need to make the clock work.

  1. Open up the clockScript by double-clicking it. Update the code:

    var isPaused : boolean = false;
    var startTime : float; //(in seconds)
    var timeRemaining : float; //(in seconds)
    function Start()
    {
    }

    function Update() {
    if (!isPaused)
    {
    // make sure the timer is not paused
    DoCountdown();
    }
    }

    function DoCountdown() {
    }

    function PauseClock()
    {
    isPaused = true;
    }

    function UnpauseClock()
    {
    isPaused = false;
    }

    function ShowTime()
    {
    }

    function TimeIsUp()
    {
    }

What just happened – that's a whole lotta nothing

Here, we've created a list of functions that we'll probably need to get our clock working. The functions are empty, but that's okay—roughing them in like this is a really valid and useful way to program. We have a doCountdown() function that we call on every update, as long as our isPaused flag is false. We have pauseClock() and unpauseClock() functions—each of them needs only one simple line of code to change the isPaused flag, so we've included that. In the showTime() function, we'll display the time in the GUIText component. Finally, we'll call the timeIsUp() function when the clock reaches zero.

At the top of the script are three hopefully self-explanatory variables: a Boolean to hold the clock's paused state, a floating point number to hold the start time, and another to hold the remaining time.

Now that we have the skeleton of our clock code and we see the scope of work ahead of us, we can dive in and flesh it out.

Time for action – create the countdown logic

Let's set the startTime variable, and build the logic to handle the counting-down functionality of our clock.

  1. Set the startTime variable:

    function Start() {
    startTime = 5.0;
    }

    Note: five seconds to beat the game is a bit ridiculous. We're just keeping the time tight for testing. You can crank this variable up later

  2. Decrease the amount of time on the clock:

    function DoCountdown()
    {
    timeRemaining = startTime - Time.time;
    }

  3. If the clock hits zero, pause the clock and call the TimeIsUp() function:

    timeRemaining = startTime - Time.time;
    if (timeRemaining < 0)
    {
    timeRemaining = 0;
    isPaused = true;
    TimeIsUp();
    }

  4. Add some Debug statements so that you can see something happening:

    function DoCountdown()
    {
    // (other lines omitted for clarity)
    Debug.Log("time remaining = " + timeRemaining);
    }
    function TimeIsUp()
    {
    Debug.Log("Time is up!");
    }

  5. Save the script and test your game.

You should see the Debug statements in the Console window (Window | Console) or in the information bar at the bottom of the screen. When the clock finishes ticking down through five seconds, you'll see the Time is up! message... if you're a mutant with super-speed vision. The Time is up! message gets wiped out by the next "time remaining" message. If you want to see it with normal-people vision, open the Console window (Window | Console in the menu and watch for it in the list of printed statements.

(Move the mouse over the image to enlarge.)

Time for action – display the time on-screen

We know from the Debug statements that the clock is working, so all we need to do is stick the timeRemaining value into our GUIText. But, it won't look very clock-like unless we perform a tiny bit of math on that value to split it into minutes and seconds so that five seconds displays as 0:05, or 119 seconds displays as 1:59.

  1. Call the ShowTime() function from within the DoCountdown() function (you can delete the Debug.Log statement):

    {
    timeRemaining = startTime - Time.time;
    // (other lines omitted for clarity)
    ShowTime();
    Debug.Log("time remaining = " + timeRemaining);
    }

  2. Create some variables to store the minutes and seconds values in the ShowTime() function, along with a variable to store the string (text) version of the time:

    function ShowTime() {
    var minutes : int;
    var seconds : int;
    var timeStr : String;
    }

  3. Divide the timeRemaining by 60 to get the number of minutes that have elapsed:

    var timeStr : String;
    minutes = timeRemaining/60;

  4. Store the remainder as the number of elapsed seconds:

    minutes = timeRemaining/60;
    seconds = timeRemaining % 60;

  5. Set the text version of the time to the number of elapsed minutes, followed by a colon:

    seconds = timeRemaining % 60;
    timeStr = minutes.ToString() + ":";

  6. Append (add) the text version of the elapsed seconds:

    timeStr = minutes.ToString() + ":";
    timeStr += seconds.ToString("D2");

  7. Finally, push the timeStr value to the GUIText component:

    timeStr += seconds.ToString("D2");
    guiText.text = timeStr; //display the time to the GUI

  8. To gaze at your clock longingly as it counts down every delectable second, crank up the startTime amount in the Start function:

    startTime = 120.0;

  9. Save and test.

Your beautiful new game clock whiles away the hours in your own chosen font at your own chosen size, formatted with a colon like any self-respecting game clock should be.

What just happened – what about that terrifying code?

There are a few kooky things going on in the code we just wrote. Let's hone in on the new and weird stuff.

minutes = timeRemaining/60;

We set the value of the minutes variable by dividing timeRemaining by 60. If there were 120 seconds left, dividing by 60 means there are two minutes on the clock. If there were only 11 seconds left on the clock, dividing by 60 gives us 0.183 repeating.

The reason why we don't see 0.1833333 in the "minutes" portion of our clock is a sneaky data type trick: timeRemaining is a float (floating point number), so it can remember decimal places. Our minutes variable is an int (integer), which can't remember decimal places. So, when we feed 0.183333 into an int variable, it just snips off everything after the decimal. It can't remember that stuff, so why bother? The result is that minutes is set to 0, which is what we see on the clock.

seconds = timeRemaining % 60;

This unnerving little percent-symbol beastie performs a modulo operation, which is like those exercises you did in grade three math class when you were just about to learn long division. A modulo operation is like a division, except it results in the remainder of your operation. Here are a few examples:

  • 4 % 2 = 0 because 2 goes into 4 twice with no remainder
  • 11 % 10 = 1 because 10 goes into 11 once with 1 as the remainder (10+1 = 11)
  • 28 % 5 = 3 because 5 goes into 28 five times (5*5=25), with a remainder of 3 (25+3 = 28)

timeStr = minutes.ToString() + ":";

The int.ToString() method works exactly as advertised, converting an integer to a String. Many data types have ToString() methods. At the end of this line, we're tacking on a colon (:) to separate the minutes from the seconds.

timeStr += seconds.ToString("D2");

The += operator, you'll remember, takes what we've already got and adds something new to it—in this case, it's seconds.ToString();. We're passing the special argument D2 to the ToString() method to round to the nearest two decimal places so that the clock looks like this:

4:02

instead of this:

4:2

Nifty!

Whatever is the problem?
If you still have whatever as your placeholder text, now's a good time to consider ditching it. It shows up on-screen for a split-second before the numbers appear. Yuck! Click on the Clock GameObject in the Hierarchy panel, and clear out the value marked Text in the GUIText component in the Inspector panel.

Picture it

Number clocks look alright, but graphical clocks really get me revved up and ready for some pressurized pants-wetting. Nothing denotes white-knuckled urgency like a bar that's slowly draining. We don't need to do much extra work to convert our number clock into a picture clock, so let's go for it!

Time for action – grab the picture clock graphics

As per our agreement, all the pretty pictures are pre-drawn for you. Download the Unity assets package from here (ch:8). When you're ready to import it, click on Assets | Import Package… and find the .unitypackage file. Open it up, and thar she be! If only obtaining game graphics in a real production environment were this easy.

Let's get right to work by creating some code to make use of two of the graphics in the package—a blue clock background bar, and a shiny yellow foreground bar that will slowly shrink as time marches on.

  1. Create a variable to store the elapsed time as a percentage:

    var isPaused : boolean = false;
    var startTime : float; //(in seconds)
    var timeRemaining : float; //(in seconds)
    var percent:float;

  2. Create some variables to store the textures, as well as the initial width of the yellow foreground bar:

    var percent:float;
    var clockBG:Texture2D;
    var clockFG:Texture2D;
    var clockFGMaxWidth:float; // the starting width of the foreground
    bar

  3. Save the script and go back to Unity.
  4. Click on the Clock Game Object in the Hierarchy panel.
  5. Find the clockScript component in the Inspector Panel.
  6. The new clockBG and clockFG variables we just created are now listed there. Click-and-drag the clockBG texture from the Project panel to the clockBG slot, and then click-and-drag the clockFG texture into its slot.

What just happened – you can do that?

This is yet another example of Unity's drag-and-drop usefulness. We created the two Texture2D variables, and the variables appeared on the Script component in the Inspector panel. We dragged-and-dropped two textures into those slots, and now whenever we refer to clockBG and clockFG in code, we'll be talking about those two texture images. Handy, yes?

Time for action – flex those GUI muscles

We'll use the GUI techniques to display the two bars, and shrink the foreground bar as time runs out.

  1. In the DoCountdown function, calculate the percentage of time elapsed by comparing the startTime and the timeRemaining values:

    function DoCountdown()
    {
    timeRemaining = startTime - Time.time;
    percent = timeRemaining/startTime * 100;
    if (timeRemaining < 0)
    {
    timeRemaining = 0;
    isPaused = true;
    TimeIsUp();
    }
    ShowTime();
    }

  2. Store the initial width of the clockFG graphic in a variable called clockFGMaxWidth in the Start function:

    function Start()
    {
    startTime = 120.0;
    clockFGMaxWidth = clockFG.width;
    }

  3. Create the built-in OnGUI function somewhere apart from the other functions in your script (make sure you don't create it inside the curly brackets of some other function!)

    function OnGUI()
    {
    var newBarWidth:float = (percent/100) * clockFGMaxWidth; // this
    is the width that the foreground bar should be
    var gap:int = 20; // a spacing variable to help us position the
    clock
    }

  4. Create a new group to contain the clockBG texture. We'll position the group so that the clockBG graphic appears 20 pixels down, and 20 away from the right edge of the screen:


    function OnGUI()
    {
    var newBarWidth:float = (percent/100) * clockFGMaxWidth; // this
    is the width that the foreground bar should be
    var gap:int = 20; // a spacing variable to help us position the
    clock
    GUI.BeginGroup (new Rect Screen.width - clockBG.width - gap,
    gap, clockBG.width, clockBG.height));
    GUI.EndGroup ();
    }

  5. Use the DrawTexture method to draw the clockBG texture inside the group:

    GUI.BeginGroup (new Rect (Screen.width - clockBG.width - gap,
    gap, clockBG.width, clockBG.height));
    GUI.DrawTexture (Rect (0,0, clockBG.width, clockBG.height),
    clockBG);
    GUI.EndGroup ();

  6. Nest another group inside the first group to hold the clockFG texture. Notice that we're offsetting it by a few pixels (5,6) so that it appears inside the clockBG graphic:

    GUI.BeginGroup (new Rect (Screen.width - clockBG.width - gap,
    gap, clockBG.width, clockBG.height));
    GUI.DrawTexture (Rect (0,0, clockBG.width, clockBG.height),
    clockBG);
    GUI.BeginGroup (new Rect (5, 6, newBarWidth, clockFG.height));
    GUI.EndGroup ();
    GUI.EndGroup ();

  7. Now, draw the clockFG texture inside that nested group:

    GUI.BeginGroup (new Rect (5, 6, newBarWidth, clockFG.height));
    GUI.DrawTexture (Rect (0,0, clockFG.width, clockFG.height),
    clockFG);
    GUI.EndGroup ();

    Did you punch that in correctly? Here's what the entire function looks like all at once:

    function OnGUI()
    {
    var newBarWidth:float = (percent/100) * clockFGMaxWidth; // this
    is the width that the foreground bar should be
    var gap:int = 20; // a spacing variable to help us position the
    clock
    GUI.BeginGroup (new Rect (Screen.width - clockBG.width - gap,
    gap, clockBG.width, clockBG.height));
    GUI.DrawTexture (Rect (0,0, clockBG.width, clockBG.height),
    clockBG);
    GUI.BeginGroup (new Rect (5, 6, newBarWidth,
    clockFG.height));
    GUI.DrawTexture (Rect (0,0, clockFG.width, clockFG.height),
    clockFG);
    GUI.EndGroup ();
    GUI.EndGroup ();
    }

Save the script and jump back into Unity. Let's turn off the old and busted number clock so that we can marvel at the new hotness—our graphical clock. Select the Clock GameObject in the Hierarchy panel. Locate the GUIText component in the Inspector panel, and uncheck its check box to turn off its rendering. Now, test your game.

Fantastic! Your new graphical clock drains ominously as time runs out. That'll really put the heat on, without compromising your player's doubtless lust for eye candy.

What just happened – how does it work?

The math behind this magic is simple ratio stuff that I, for one, conveniently forgot the moment I escaped the sixth grade and ran away to become a kid who enjoys watching circus clowns. We converted the time elapsed into a percentage of the total time on the clock. Then, we used that percentage to figure out how wide the clockFG graphic should be. Percentage of time elapsed is to 100, as the width of the clockFG graphic is to its original width. It's simple algebra from there.

The only math you need to know
I often say that this dead-simple ratio stuff is the only math you need to know as a game developer. I'm half-kidding, of course. Developers with a firm grasp of trigonometry can create billiard and pinball games, while Developers who know differential calculus can create a tank game where the enemy AI knows which way to aim its turret, taking trajectory, wind, and gravity into account (hey, kids! Stay in school).
But, when people ask sheepishly about programming and how difficult it is to learn, it's usually because they think you can only create games by using complex mathematical equations. We've hopefully debunked this myth by creating two simple games so far with equally simple math. These ratio calculations are used ALL THE TIME in gaming, from figuring out health bars, to player positions on a mini-map, to level progress meters. If you're arithmophobic like I am, and you relearn only one piece of math from your long-forgotten elementary school days, make it this one.

The incredible shrinking clock

The GUI.BeginGroup() and GUI.EndGroup() functions can wrap our fixed-position UI controls together so that we can move them around as a unit. In the preceding code, we made one group to hold the background bar, and another inside it to hold the foreground bar, offset slightly. The outer group is positioned near the right edge of the screen, using the gap value of 20 pixels to set it back from the screen edges.

When we draw the foreground clock bar, we draw it at its normal size, but the group that wraps it is drawn at the shrinking size, so it cuts the texture off. If you put a 500x500 pixel texture inside a 20x20 pixel group, you'll only see a 20x20 pixel portion of the larger image. We use this to our advantage to display an ever-decreasing section of our clock bar.

Keep your fork—there's pie!

The third type of clock we'll build is a pie chart-style clock. Here's what it will look like when it's counting down:

How they did it

The pie clock involves a little sleight of hand. Here are the pieces that make up the clock:

It's a bit like a sandwich. We start by drawing the blue background. Then, we layer on the two yellow half-moon pieces. To make the clock look pretty, we apply the lovely, shiny gloss picture in front of all these pieces.

We rotate the right half-moon piece halfway around the circle to make the slice of yellow time appear to grow smaller and smaller.

At the halfway point, we slap a half-moon section of the blue background on top of everything, on the right side of the clock. We're all done with the right half-circle, so we don't draw it.

Now, we rotate the left half-moon piece, and it disappears behind the blocker graphic, creating the illusion that the rest of the clock is depleting.

When time is up, we slap the red clock graphic in front of everything.

A little flourish of the wrist, a puff of smoke, and the audience doesn't suspect a thing!

Unity 3D Game Development by Example Beginner's Guide A seat-of-your-pants manual for building fun, groovy little games quickly
Published: September 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Read more about this book

(For more resources on Unity 3D, see here.)

Time for action – rig up the textures

We know most of what we need to get started. There's just a little trick with rotating the textures that we have to learn. But, first, let's set up our clock with the variables we'll need to draw the textures to the screen.

  1. Add variables for the new pie clock textures at the top of the clockScript:

    var clockFGMaxWidth:float; // the starting width of the foreground
    bar

    var rightSide:Texture2D;
    var leftSide:Texture2D;
    var back:Texture2D;
    var blocker:Texture2D;
    var shiny:Texture2D;
    var finished:Texture2D;

  2. In the Hierarchy panel, select the Clock Game Object.
  3. Just as we did with the bar clock, drag-and-drop the pie clock textures from the Project panel into their respective slots in the clockScript component in the Inspector panel. When you're finished, it should look like this:

Time for action – write the pie chart Script

With these Texture2D variables defined, and the images stored in those variables, we can control the images with our script. Let's lay down some code, and pick through the aftermath when we're finished:

  1. Knowing when the clock has passed the halfway point is pretty important with this clock. Let's create an isPastHalfway variable inside our OnGUI function:

    function OnGUI ()
    {
    var isPastHalfway:boolean = percent < 50;

    (Confused? Remember that our percent variable means "percent remaining", not "percent elapsed". When percent is less than 50, we've passed the halfway mark).

  2. Define a rectangle in which to draw the textures:

    var isPastHalfway:boolean = percent < 50;
    var clockRect:Rect = Rect(0, 0, 128, 128);

  3. Draw the background blue texture and the foreground shiny texture:

    var clockRect:Rect = Rect(0, 0, 128, 128);
    GUI.DrawTexture(clockRect, back, ScaleMode.StretchToFill, true,
    0);
    GUI.DrawTexture(clockRect, shiny, ScaleMode.StretchToFill, true,
    0);

  4. Save the script and play the game. You should see your shiny blue clock glimmering at you in the top-left corner of the screen:

  5. Next, we'll add a condition check and draw the red "finished" graphic over the top of everything when percent goes below zero (which means that time is up). Add that bit just above the "shiny" texture draw so that the shiny picture still layers on top of the red "finished" graphic:

    if(percent < 0)
    {
    GUI.DrawTexture(clockRect, finished, ScaleMode.StretchToFill,
    true, 0);
    }
    GUI.DrawTexture(clockRect, shiny, ScaleMode.StretchToFill, true,
    0);

  6. Save the script and play the game again to confirm that it's working. When time runs out, your blue clock should turn red:

  7. Let's set up a rotation variable. We'll use the percent value to figure out how far along the 360 degree spectrum we should be rotating those yellow half-circle pieces. Note that once again, we're using the same ratio math that we used earlier with our bar clock:

    var clockRect:Rect = Rect(0, 0,128,128);
    var rot:float = (percent/100) * 360;

    If you want to see it working, try adding a Debug.Log or print statement underneath to track the value of rot. The value should hit 360 when the clock times out.

  8. We have to set two more variables before the fun begins—a centerPoint and a startMatrix. I'll explain them both in a moment:

    var rot:float = (percent/100) * 360;
    var centerPoint:Vector2 = Vector2(64, 64);
    var startMatrix:Matrix4x4 = GUI.matrix;

What just happened?

One important thing to know is that, unlike 3D Game Objects like the Paddle and Ball from our keep-up game, GUI textures can't be rotated. Even if you apply them to a Game Object and rotate the Game Object, the textures won't rotate (or will skew in a very strange way). We know we need to rotate those two half-circle pieces to make the pie clock count down, but because of this limitation, we'll have to find a creative workaround.

Here's the game plan: we're going to use a method of the GUIUtility class called RotateAroundPivot. The centerPoint value we created defines the point around which we'll rotate. RotateAroundPivot rotates the entire GUI. It's as if the GUI controls were stickers on a sheet of glass, and instead of rotating the stickers, we're rotating the sheet of glass.

So, we're going to follow these steps to rotate those half-circles:

  1. Draw the blue clock background.
  2. Rotate the GUI using the rot (rotation) value we set.
  3. Draw the yellow half-circle pieces in their rotated positions. This is like stamping pictures on a piece of paper with a stamp pad. The background is already stamped. Then, we rotate the paper and stamp the half-circles on top.
  4. Rotate the GUI back to its original position.
  5. Draw or stamp the "finished" graphic (if the timer is finished) and the shiny image.

So, the background, the red "finished" image, and the shiny image all get drawn when the GUI is in its normal orientation, while the half-circle pieces get drawn when the GUI is rotated. Kinda neat, huh? That's what the startMatrix variable is all about. We're storing the matrix transformation of the GUI so that we can rotate it back to its "start" position later.

Time for action – commence operation pie clock

Let's lay down some code to make those half-circle pieces rotate.

  1. Set up a conditional statement so that we can draw different things before and after the halfway point:

    GUI.DrawTexture(clockRect, back, ScaleMode.StretchToFill, true,
    0);
    if(isPastHalfway)
    {
    } else {
    }

  2. If we're not past halfway, rotate the GUI around the centerPoint. Draw the right side half-circle piece on top of the rotated GUI. Then, rotate the GUI back to its start position.

    if(isPastHalfway)
    {
    }
    else
    {
    GUIUtility.RotateAroundPivot(-rot, centerPoint);
    GUI.DrawTexture(clockRect, rightSide, ScaleMode.StretchToFill,
    true, 0);
    GUI.matrix = startMatrix;
    }

  3. Save the script and test your game. You should see the right side half-circle piece rotating around the clock. But, we know it's not really rotating—the entire GUI is rotating, and we're stamping the image on the screen before resetting the rotation.
  4. Draw the left half-circle once the GUI is back into position.

    GUI.matrix = startMatrix;
    GUI.DrawTexture(clockRect, leftSide, ScaleMode.StretchToFill,
    true, 0);

  5. You can save and test at this point, too. The right half-circle disappears behind the left half-circle as it rotates, creating the illusion we're after. It all comes crashing down after the halfway point, though. Let's fix that:

    if(isPastHalfway)
    {
    GUIUtility.RotateAroundPivot(-rot-180, centerPoint);
    GUI.DrawTexture(clockRect, leftSide, ScaleMode.StretchToFill,
    true, 0);
    GUI.matrix = startMatrix;

  6. Save and test. Once we're past the halfway point, the left half-circle does its thing, but the illusion is ruined because we see it rotating into the right side of the clock. We just need to draw that blocker graphic to complete the illusion:

    GUI.matrix = startMatrix;
    GUI.DrawTexture(clockRect, blocker, ScaleMode.StretchToFill,
    true, 0);

  7. Save and test one last time. You should see your pie clock elapse exactly as described in the sales brochure.

What just happened – explaining away the loose ends

Hopefully, the code is straightforward. Notice that in this line:

GUIUtility.RotateAroundPivot(-rot, centerPoint);

We're sticking a minus sign on the rot value—that's like multiplying a number by negativeone. If we don't do this, the half-circle will rotate in the opposite direction (try it yourself! Nix the minus sign and try out your game).

Similarly, in this line:

GUIUtility.RotateAroundPivot(-rot-180, centerPoint);

We're using the negative rot value, and we're subtracting 180 degrees. That's because the left half-circle is on the other side of the clock. Again, try getting rid of the -180 and see what effect that has on your clock.

Another thing that you may want to try is changing the centerPoint value. Our pie clock graphics are 128x128 pixels, so the center point is at 64, 64. Mess around with that value and check out the funky stuff the clock starts doing.

GUI.matrix = startMatrix;

It's worth mentioning that this line locks the GUI back into position, based on the startMatrix value we stored.

GUI.DrawTexture(clockRect, leftSide, ScaleMode.StretchToFill,
true, 0);

Did I catch you wondering what ScaleMode.StretchToFill was all about? There are three different settings you can apply here, all of which fill the supplied rectangle with the texture in a different way.

Time for action – positioning and scaling the clock

The pie clock is pretty neat, but it's sadly stuck to the top-left corner of the screen. It would be great if we could make it any size we wanted, and if we could move it anywhere on the screen.

We're not far off from that goal. Follow these steps to get a dynamically positioned and scaled pie clock:

  1. Create these variables at the top of the OnGUI function:

    var pieClockX:int = 100;
    var pieClockY:int = 50;

    var pieClockW:int = 64; // clock width
    var pieClockH:int = 64; // clock height

    var pieClockHalfW:int = pieClockW * 0.5; // half the clock width
    var pieClockHalfH:int = pieClockH * 0.5; // half the clock
    height

    In this example, 100 and 50 are the X and Y values where I'd like the pie clock to appear on the screen. The clock builds out from its top-left corner. 64 and 64 are the width and height values I'd like to make the clock—that's exactly half the size of the original clock.

    Note: scaling the clock will result in some ugly image artifacting, so I don't really recommend it. In fact, plugging in non-uniform scale values like 57x64 will destroy the illusion completely! But, learning to make the clock's size dynamic is still a worthwhile coding exercise, so let's keep going.

  2. Modify the clockRect declaration to make use of the new x, y, width, and height variables:

    var clockRect:Rect = Rect(pieClockX, pieClockY, pieClockW,
    pieClockH);

  3. Modify the centerPoint variable to make sure we're still hitting the dead-center of the clock:

    var centerPoint:Vector2 = Vector2(pieClockX + pieClockHalfW,
    pieClockY + pieClockHalfH);

  4. Save the script and test your game. You should see a pint-sized clock (with a few ugly pixels here and there) at x100 y50 on your screen.

Have a go hero – rock out with your clock out

There's lots more you could add to your clock to juice it up. Here are a few ideas:

  • Add some logic to the TimeIsUp() method. You could pop up a new GUI window that says Time is up! with a Try Again button, or you could link to another Scene showing your player's character perishing in a blazing inferno… whatever you like!
  • Create a pause/unpause button that starts and stops the timer. The clockScript is already set up to do this—just toggle the isPaused variable.
  • Create a button that says More Time!. When you click on it, it should add more time to the clock. When you get this working, you can use this logic to add power-ups to your game that increase clock time.
  • Use the skills that you've already acquired to tie this clock into any game that you create in Unity, including the keep-up and robot games

Unfinished business

With this article, you've mastered an important step in your journey as a game developer. Understanding how to build a game clock will serve you well in nearly all of the games you venture off to build. Games without some kind of clock or timer are uncommon, so adding this notch to your game developer tool belt is a real victory. Here are some skills you learned in this article:

  • Creating a font material
  • Displaying values on-screen with GUIText
  • Converting numbers to strings
  • Formatting string data to two decimal places
  • Ratios: the only math you'll ever need (according to someone who doesn't know math)!
  • Storing texture images in variables
  • Scaling or snipping graphics based on script data
  • Rotating, and then unrotating, the GUI
  • Converting hardcoded script values to dynamic script values

Summary

In this article we have learnt to:

  • Program a text-based countdown clock to add a little pressure to our games
  • Modify the clock to make it graphical, with an ever-shrinking horizontal bar
  • Layer in some new code and graphics to create a pie chart-style clock

 


Further resources on this subject:


About the Author :


Ryan Henson Creighton

Ryan is the founder of Untold Entertainment Inc., a boutique game development studio in the heart of downtown Toronto. Ryan got his start at a Canadian television broadcaster creating small, simple games for kids and preschoolers. By the time he was through, he had built over fifty games for a wide range of clients including McDonalds, Hasbro, Lego, Proctor and Gamble, Nickelodeon, and the Canadian National Institute for the Blind. These games ran the gamut from simple slider puzzles, memory games, and contest entry mechanics to tile-based graphic adventure games and massively multiplayer virtual worlds. Ryan often leveraged his theatre background to perform on-camera in promotional spots for Microsoft and Nintendo. He spent a number of years moonlighting as a video game journalist under the cartoonish moniker "MrSock".

Ryan founded Untold Entertainment Inc. in 2007 and has continued to develop great kids' content with broadcasters and independent television producers to help extend their on-air brands online. He packs the company's popular blog with tutorials, designer diaries, and insights into the world of independent game development, employing his signature biting wit and ludicrous photo captions.

Through Untold Entertainment, Ryan is developing a number of original properties, which include: Interrupting Cow Trivia, an online multiplayer trivia game; Spellirium, a word puzzle/adventure game hybrid; UGAGS, the Untold Graphic Adventure Game System; and Kahoots, a fun crime-themed puzzle game modeled entirely in clay.

Ryan lives and bikes around downtown Toronto with his wife Cheryl, and his two tiny daughters Cassandra and Isabel.

Books From Packt


Unity Game Development Essentials
Unity Game Development Essentials

XNA 4.0 Game Development by Example: Beginner's Guide
XNA 4.0 Game Development by Example: Beginner's Guide

3D Game Development with Microsoft Silverlight 3: Beginner's Guide
3D Game Development with Microsoft Silverlight 3: Beginner's Guide

Flash Multiplayer Virtual Worlds
Flash Multiplayer Virtual Worlds

Flash 10 Multiplayer Game Essentials
Flash 10 Multiplayer Game Essentials

Blender 3D 2.49 Architecture, Buildings, and Scenery
Blender 3D 2.49 Architecture, Buildings, and Scenery

WordPress and Flash 10x Cookbook
WordPress and Flash 10x Cookbook

Drupal 7
Drupal 7


Your rating: None Average: 5 (2 votes)
Cant assign font texture to material by rushikesh Deshpande
I cant find any font in my texture list. can you tell me whats wrong with my code?

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
D
w
5
x
a
q
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software