Megabite #7 - An Android Game From Scratch (part 3)

Continuing on from the last lesson, in this article we will make our game much more finalized and playable.  What we should currently have is a sphere as a game piece, a board for the sphere to roll on, and a hole for the ball to fall into.  All in all, what we have is quite basic, but it's the framework that will allow us to really customize things how we like.

Before anything else, let's apply a more realistic set of physics to the ball and be sure it isn't going to fly through the walls of our level.  A basic speed should be declared, and we're going to make it a variable in case we want to change it.  (as a side note, I would suggest doing this as often as you can in case you want to change these things in-game based on things such as options or even power-ups).

In our movement script, lets add this line outside of the functions:

private var ballSpeed : int = 30;

A base speed of 30 should be about average because we're going to be multiplying it by accelerometer numbers, which are going to be less than 1.  We've covered a few basics of AddForce in previous tutorials, but this will give you an idea of how versatile the function really can be.  Our old movement script went something like this:

transform.position.x = (transform.position.x - (dir.y - calibrateY));
transform.position.y = (transform.position.y + (dir.x - calibrateX));

This was good enough when we didn't have physics, but we now want our GameObject to really interact and react to colliders.  What we can replace these lines with will be something more like this:

rigidbody.AddForce (Vector3.left * ballSpeed * (dir.y - calibrateY));
rigidbody.AddForce (Vector3.up * ballSpeed * (dir.x - calibrateX));

Instead of moving the ball around the universe, we're now effectively "pushing" it into the right direction.  This way, if it hits something it will react accordingly.

While we're in this script, let's also make sure we know where the ball is going to be on the Z-axis while playing.  This can be done by just adding the following to the Update function:

print(transform.position.z);

Now, go ahead and test the game in the player.  When the ball is settled, make sure to take note of the debug line in the console (at the bottom of your screen).  The number there (for me it was 14.48) will be the exact Z position of the ball after settling on the level base, and we can now establish victory if that ball falls into a hole.  Based on my design, I know that if the Z-position of the ball is anything OVER 14.48, I've "won" the game by getting the ball into the goal.  so in my movement script, Ive added these lines:

Outside of functions: private var victory = false;
Within Update() if (transform.position.z > 14.50) {
victory = true;
} else {
victory = false;
Within OnGUI() (NOT inside of the overlay we created - we don't want to have to hit the back button to see if we win) if (victory == true) {
GUI.Box (Rect(Screen.width /2 - 100, Screen.height /2 -50, 200, 100), "You Win!");
}

Play your game to be sure your own measurements line up and "win" the game if your ball falls into the hole.  In the next section, we'll work on adding obstacles and such to the level itself.

To get your level working properly, you'll want to establish borders and obstacles.  I'll go over a few basics, but this is really a section that you can use to make the game your own unique product.  Before anything, there's a quick addition we can make that will allow our game to expand as much as we would like.  Create a new javascript file and add the following:

var theBall : Transform;
function Update () {
transform.position.x = theBall.transform.position.x;
transform.position.y = theBall.transform.position.y;
}

Save it however you like and then drop it onto the main camera.  Now, wherever the ball goes, the camera will follow along.  What this will allow is a whole new capacity for level expansion.  Instead of a board that is only the size of your device's screen, we can make it as complex as we want.  Have fun with it, but my only warning is that if you stretch the level, you'll stretch the victory zone along with it.  Though theres no limit to how many different ways you can expand on what we have, just make sure you aren't ruining the work you've already done.  Also remember that our world has gravity, which can allow for fun things such as stairs, tubes, or other complex additions... eventually.

I'm a firm believer in starting with something simple before going into a massive undertaking.  Allow yourself to complete something easier before you decide to expand.  As the example here, I'm not going to go too crazy.  We're going to start with some basic walls, and I'll leave them untextured so they can be easily seen in the images.

Start by creating some cubes.  Remember, cubes have colliders and everything needed by default.  Scale them to fit along the walls of your level, and be sure they are tall enough to really prevent the ball from escaping.  (Since the camera is overhead, taller is likely better.)

Make good use out of the right-click -> duplicate feature within the hierarchy, and save yourself time.  Before long, you can take a simple plane and make it into something much more interesting.

Yes, my level is boring.  Yours doesn't have to be.   In fact, you can get creative and use some basic scripts to literally put some of the pieces in motion.  I won't go into these more advanced features here because my aim is to deliver the basics and allow you to really let the project take off on your own steam.

For convenience, here are all the files needed to get everything going:  The fully-built APK for Android, the UnityPackage that contains the scene, prefabs, scripts and materials, or just the scripts themselves: CubeMover.js and CameraFollow.js.  Hopefully it makes things much easier to get started or aids in giving you a point of reference.