Megabite #5 - Designing an Android Game From Scratch (part 1)

Like the rest of the Megabite series, I will be instructing by using Unity3d, which has proved itself to me time and again over the past few projects.  Most recently, I was able to use the trial of Unity Android to get myself published onto the Android Market, and though in my case the game was nearly finished for its format as a web-based game, I merely had to switch platforms within the settings and alter a few lines of code to add things such as accelerometer controls.

In this article, I will be talking about the basics of going from "New Project" to "Hey check out the app I just published".

To begin, you will need a trial copy of Unity3d Android at the minimum, which can be found here.  The licensed copies of the software or the Pro version are $400 or $1500 dollars respectively (which may seem steep until you get an idea of the features and differences), but a trial is enough to get yourself started and even get a working game ready for publication.  If you are on a trial copy, you will see "trial copy" watermarked in small text at the bottom-right portion of the finished product, but the software isn't limited in any other respect that I've come across so far.

You should download and install the Android SDK as well, and update it with the packages you are aiming to target.  While this tutorial will not cover the SDK inner-workings, Google has a great deal of pre-existing documentation on the basics if you choose to use it.  For our purposes, we don't need to spend much more time than to install it.

Getting your game together

If you have existing code, you may see some errors pop up if you were lazy in the way you declared variables (like I was).  if you have a script that contains something like:

var myVariable;

You will likely see a warning that forces you to declare what type of variable you are creating.  Since you should already know what it is you're trying to DO with this variable, this isn't a big issue.  You simply define it as a string, integer, float, game object, or whatever you need.

var myVariable : String;

For me, this was simply a wake-up call that let me know I should be more specific.  Not to mention, it's a good habit to develop anyway and it makes your code more readable when you go back to decipher work from earlier.  Suffice it to say that Android development was just a slight bit pickier in how things are read, but you can see it wasn't a deal-breaker.

If this is your first time using Unity to develop, I suggest reading through earlier posts in this series to get a basic understanding of Unity development as a whole before you dive into the deep end.  In fact, we're going to import the project that is still standing from #2 in the series and use that project to develop our first APK file.

We'll start by switching the platform over to Android, as you can see on the left (File -> Build Settings). Once you've selected it, you simply click the button beneath to begin the automatic process.  Unity converts whatever it needs to behind-the-scenes while you wait.

Once the process is complete, you will see if there are any errors that might need to be handled.  In the case of the Megabite project, there were not - so we can move on.

Because we are now developing for a different resolution and such, you will notice that your "game" tab has some new view switching options.  Obviously Android has many different hardware setups, so you should keep these in mind as you test your game in the player.  Sometimes seeing what the game looks like in a different aspect will remind you about hiccups that may have occurred in your calculations or display setup.

What we're going to do here is a landscape setup, so you will want to open your player settings to choose these options.  Go to Edit -> Project Settings -> Player, and you will see the different options available in the new Android tab.

While you're in here, you can alter things such as your icon (will display on the Android device home screen or within the applications menu), the Product (game) name, and your company name.  Under Resolution and Presentation, I will choose "Landscape Left", which seems the most compatible and common landscape option.

Fair warning: I did attempt to change some of the settings within "Other Settings" when I first published GIRType, and simply ended up crashing my phone.  I would suggest you stick to the default options unless you know specifically what you are choosing, but you should be sure to change these boxes when applicable:

For your first go-round, the Identifier is the important option.  The version number and version code will need to be raised for each publication to the market (or else google will give you an error), but to test things locally you can leave them unchanged for now.

Lastly, the publishing settings.  While the terminology here might be new or seemingly complicated, you really just need to create 2 passwords here.  Check the box for "Create new Keystore" and then browse - Unity will create a file and save it to the system.  Once done, you need to create a password for this keystone and confirm it.

The pull-down box for the "Alias" will have an option to create a new key, which will allow you to put in more information.  Here you will create a second password and re-enter it on the publication tab when finished.

Once all these basic things are accomplished, you will immediately be able to build the project into an APK file.  Open the build settings once more (be sure your scene is in the scene list.  If it isn't, open your scene and hit "add current" and you'll see it listed) and hit the Build button.  You'll be prompted during the process to select your base folder for the Android SDK if Unity doesn't automatically find it, but you can move on once selected.

Follow me onto the next page and we'll get that file up and running.

While you can emulate the file by using the SDK, I personally find it more accurate and fulfilling by testing my builds directly on my device.  Plugging in your USB connection and moving the file onto your phone is a snap, but you can also use methods such as wireless transfer or ftp if you prefer.  Whatever your method, you need simply to execute your file and it will install flawlessly.

Unfortunately, our game is still lame.  Theres nothing in it that will work with the controls that we've created, so we end up with a blue background and a cube.  However, what we DO have is a working application on an Android device, and all of the knowledge needed to do it again - only better.

Making use of the tech

We've got fancy accelerometers and a touch-screen, so we should really put them to use.  In this section, we'll manipulate some of the code to give ourselves the same basic functionality we had before.  In our script containing the movement controls, we need to add this into the Update() section:

	var dir : Vector3 = Vector3.zero;
	dir.z = Input.acceleration.x;
	dir.x = -Input.acceleration.y;
	if (dir.sqrMagnitude > 1) {
		dir.Normalize();
	}

While it may seem complicated, what we're doing here is accounting for the fact that the device is in landscape mode.  Basically, our "z" variable is the up/down tilt and our "x" will be the left/right while the device is on its side.  Accelerometers will read between 1 to -1 where 0 is "flat".  With that in mind, the OLD code was something like this:

function Update () {
	    if (Input.GetKey ("up")) {
		transform.position.x = (transform.position.x + 1);
		}
		if (Input.GetKey ("down")) {
		transform.position.x = (transform.position.x - 1);
		}
		if (Input.GetKey ("left")) {
		transform.position.z = (transform.position.z + 1);
		}
		if (Input.GetKey ("right")) {
		transform.position.z = (transform.position.z - 1);
		}
}

Working in 3 dimensions is complicated enough, so we're going to make sure our project is a bit more traditional.  Double check your main camera object in the Heierarchy and make sure you center your view on the cube.  The following image should help:

Set up like this, you can see that the X axis is now left/right, and the Y axis is up/down.  This makes a little more sense than the X/Z plane we were working with before.  Also, it will allow this code to easily replace the movement script:

var dir : Vector3 = Vector3.zero;
  function Update () {
		//In landscape mode, +X is up, -X is down, +Y is left and -Y is right
	dir.x = Input.acceleration.x;
	dir.y = Input.acceleration.y;
	dir.z = Input.acceleration.z;

	if (dir.sqrMagnitude > 1) {
		dir.Normalize();
	}

	//left/right
	transform.position.x = (transform.position.x - dir.y);

	//up/down
	transform.position.y = (transform.position.y + dir.x);
}

function OnGUI() {
	GUI.Label(Rect(4,4,300,30), "dir.x: " + dir.x);
	GUI.Label(Rect(4,44,300,30), "dir.y: " + dir.y);
	GUI.Label(Rect(4,84,300,30), "dir.z: " + dir.z);
	if (GUI.Button (Rect(Screen.width /2 - 60, Screen.height - 50, 120, 50), "Reset")) {
	transform.position = Vector3(0,0,0);
	}
}

So this code may seem complicated, but it all works together to create a framework.  When launched, the cube will now veer in the direction of whichever way you tilt your device.  At the top left, you will have a readout of the exact measurements that your accelerometers are giving off, and I've also added a reset button in case your cube flies off the viewable screen and gets lost.


A touch on-screen automatically works like the click of a mouse, so there is no need to code anything specific until we want to get much fancier.  The button will work by default.

To take it just one step further, let's add one more button to the bottom.  By adding a few new calculations, we can basically create a new "center" for the accelerometer calculations.   By doing this, you can place your device on a not-so-flat table and account for any tilt.

var dir : Vector3 = Vector3.zero;
private var calibrateX : float = 0;
private var calibrateY : float = 0;

function Update () {

	//In landscape mode, +X is up, -X is down, +Y is left and -Y is right
	dir.x = Input.acceleration.x;
	dir.y = Input.acceleration.y;
	dir.z = Input.acceleration.z;

	if (dir.sqrMagnitude > 1) {
		dir.Normalize();
	}

	//left/right
	transform.position.x = (transform.position.x - (dir.y - calibrateY));

	//up/down
	transform.position.y = (transform.position.y + (dir.x - calibrateX));
}

function OnGUI() {
	GUI.Label(Rect(4,4,300,30), "dir.x: " + dir.x);
	GUI.Label(Rect(4,44,300,30), "dir.y: " + dir.y);
	GUI.Label(Rect(4,84,300,30), "dir.z: " + dir.z);

	//Button to Reset to center position
	if (GUI.Button (Rect(Screen.width /2 - 120, Screen.height - 50, 120, 50), "Reset")) {
	transform.position = Vector3(0,0,0);
	}

 //Button to recalibrate Zeroed control center
 if (GUI.Button (Rect(Screen.width /2 , Screen.height - 50, 120, 50), "Calibrate")) {
 calibrateX = dir.x;
 calibrateY = dir.y;
 }
}

A note regarding OnGUI():

For a good while, I was unable to figure out what was causing lag spiking and slowdown in my Android application.  After some research, I've discovered that OnGUI has a tendency to cause some slowdown on both iOS and Android.  From what I understand, the Unity Development team is working to make OnGUI smoother and improved overall, but be sure not to overuse it.  While Update () will run once for every frame, OnGUI will run twice per frame and any calculations or fancy coding within the function might cause issues.  It's not something to avoid completely, but it's important to be aware of.

Becoming Published:

Using the tutorials and resources available, you can add any APK file you've built into the Android Market.  Signing up to become a developer will simply require a $25 fee (which is much better than Apple's $99 per year fee), a few screenshots, and a Google account.

If you look at the documentation for a regular developer, you will see that the process seems a bit complex.  Fortunately, Unity has taken care of everything for us.  Our APK files are ready for publication as long as you haven't checked the boxes that label it as a development build.  Sign up to become a developer and follow the instructions on the screen.

By following through these basic steps, you should be able to take any application you develop and publish it into the wide audience of the Android Market.  In doing this myself for the first time, I found the process quite painless.  A big thanks needs to be credited to the developers of Unity3d for making this software.  Designing games and scripts has quickly become one of my favorite pastimes, and now I have the potential of even making money from doing something that I love.  Of course, there is credit also due to the wonderful people of Google as well for developing Android as well as the Android Market.

 

The next Megabite will delve deeper into the possibilities of Android - now that we are familiar with the overall setup and basics, we can put focus into the actual game creation and attempt to push the limits of our gaming world.  Stay tuned for next Friday, where we will turn our little test application into something a bit more elegant :)