Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Unity 2017 Mobile Game Development
Unity 2017 Mobile Game Development

Unity 2017 Mobile Game Development: Build, deploy, and monetize games for Android and iOS with Unity

eBook
$27.98 $39.99
Paperback
$48.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Table of content icon View table of contents Preview book icon Preview Book

Unity 2017 Mobile Game Development

Building Your Game

As we start off on our journey building mobile games using the Unity game engine, it's important that readers are familiar with the engine itself before we dive into the specifics of building things for mobile platforms. Although there is a chance that you've already built a game and want to transition it to mobile, there will also be readers who haven't touched Unity before, or may have not used it in a long time. This chapter will act as an introduction to newcomers, a refresher for those coming back, and will provide some best practices for those who are already familiar with Unity.

In this chapter, we will build a 3-D endless runner game in the same vein as Imangi Studios, LLC's Temple Run series. In our case, we will have a player who will run continuously in a certain direction, and will dodge obstacles that come in their way. We can also add additional features to the game easily, as the game will endlessly have new things added to it.

Chapter overview

Over the course of this chapter, we will create a simple project in Unity, which we will be modifying over the course of this book to make use of features commonly seen in mobile games. While you may skip this chapter if you're already familiar with Unity, I find it's also a good idea to go through the project so that you know the thought processes behind why the project is made in the way that it is, so you can keep it in mind for your own future titles.

Your objectives

This chapter will be split into a number of topics. It will contain a simple, step-by-step process from beginning to end. Here is the outline of our tasks:

  • Project setup
  • Creating the player
  • Improving scripts using attributes
  • Having the camera follow the player
  • Creating a basic tile
  • Making the game endless
  • Creating obstacles

Setting up the project

Now that we have our goals in mind, let's start building our project:

  1. To get started, open Unity on your computer. For the purpose of this book, we will use Unity 2017.2.0f3, but the steps should work with minimal changes in future versions.
If you would like to download the exact version used in this book, and there is a new version out, you can visit Unity's download archive at https://unity3d.com/get-unity/download/archive.
  1. From startup, we'll opt to create a new project by clicking on the New button.
  2. Next, under Project name* put in a name (I have chosen MobileDev) and make sure that 3D is selected. If Enable Unity Analytics is enabled (the check to the left of it says On), click on the Enable Unity Analytics button again in order to disable it for the time being; we will add it ourselves later on when we go through Chapter 5, Advertising with Unity Ads. Afterwards, click on Create project and wait for Unity to load up:
  1. After it's finished, you'll see the Unity Editor pop up for the first time:
  1. If your layout doesn't look the same as in the preceding screenshot, you may go to the top-right section of the toolbar and select the drop-down menu there that reads Layers. From there, select Default from the options presented.
If this is your first time working with Unity, then I highly suggest that you read the Learning the Interface section of the Unity Manual, which you can access at https://docs.unity3d.com/Manual/LearningtheInterface.html.

Creating the player

Now that we have Unity opened up, we can actually start building our project. To get started, let's build a player that will always move forward. Let's start with that now:

  1. Let's create some ground for our player to walk on. To do that, let's go to the top menu and select GameObject | 3D Object | Cube.
  2. From there, let's move over to the Inspector window and change the name of the object to Floor. Then, on the Transform component, set the Position to (0, 0, 0), which we can either type in, or we can right-click on the Transform component and then select the Reset Position option.
  3. Then, we will set the Scale to (7, 0.1, 10):

In Unity, by default, 1 unit of space in Unity is representative of 1 meter in real life. This will make the floor longer than it is wide (X and Z), and we have some size on the ground (Y), so the player will collide and land on it because we have a Box Collider component attached to it.

  1. Next, we will create our player, which will be a sphere. To do this, we will go to Game Object | 3D Object | Sphere.
  1. Rename the sphere to Player and set the Transform component's Position to (0, 1, -4):

This will place the ball slightly above the ground, and shifts it back to near the starting point. Note that the camera object (you can see a camera icon to point it out) is pointing toward the ball by default because it is positioned at 0, 1, -10.

  1. We want the ball to move, so we will need to tell the physics engine that we want to have this object react to forces, so we will need to add a Rigidbody component. To do so, go to the menu and select Component | Physics | Rigidbody. To see what happens now, let's click on the Play button that can be seen in the middle of the top toolbar:

As you can see in the preceding screenshot, you should see the ball fall down onto the ground when we play the game.

You can disable/enable having the Game tab take the entire screen when being played by clicking on the Maximize On Play button at the top, or by right-clicking on the Game tab and then selecting Maximize.
  1. Click on the Play button again to turn the game off and go back to the Scene tab, if it doesn't happen automatically.

We want to have the player move, so in order to do that, we will create our own piece of functionality in a script, effectively creating our own custom component in the process.

  1. To create a script, we will go to the Project window and select Create | Folder on the top-left corner of the menu. From there, we'll name this folder Scripts. It's always a good idea to organize our projects, so this will help with that.
If you happen to misspell the name, go ahead and select the object and then single-click on the name and it'll let you rename it.
  1. Double-click on the folder to enter it, and now you can create a script by going to Create | C# Script and renaming this to PlayerBehaviour (no spaces).
The reason I'm using the "behaviour", "spelling" instead of "behavior" is that all components in Unity are children of another class called MonoBehaviour, and I'm following Unity's lead in that regard.
  1. Double-click on the script to open up the script editor (IDE) of your choice and add the following code to it:
using UnityEngine; 

public class PlayerBehaviour : MonoBehaviour
{
// A reference to the Rigidbody component
private Rigidbody rb;

// How fast the ball moves left/right
public float dodgeSpeed = 5;

// How fast the ball moves forwards automatically
public float rollSpeed = 5;

// Use this for initialization
void Start ()
{
// Get access to our Rigidbody component
rb = GetComponent<Rigidbody>();
}

// Update is called once per frame
void Update ()
{
// Check if we're moving to the side
var horizontalSpeed = Input.GetAxis("Horizontal") * dodgeSpeed;
rb.AddForce(horizontalSpeed, 0, rollSpeed);
}
}

In the preceding code, we have a couple of variables that we will be working with. The rb variable is a reference to the game object's Rigidbody component that we added previously. It gives us the ability to make the object move, which we will use in the Update function. We also have two variables dodgeSpeed and rollSpeed, which dictates how quickly the player will move when moving left/right, or when moving forward, respectively.

Since our object has only one Rigidbody component, we assign rb once in the Start function, which is called when the game starts, as long as the game object attached to this script is enabled.

Then, we use the Update function to check whether our player is pressing keys to move left or right as based on Unity's Input Manager system. By default, the Input.GetAxis function will return to us a negative value moving to -1 if we press A or the left arrow. If we press the right arrow or D, we will get a positive value up to 1 returned to us, and the input will move toward a 0 if nothing is pressed. We then multiply this by dodgeSpeed in order to increase the speed so that it is easier to be seen.

For more information on the Input Manager, check out https://docs.unity3d.com/Manual/class-InputManager.html.

Finally, once we have that value, we will apply a force to our ball's horizontalSpeed units on the X-axis and rollSpeed in the Z-axis.

  1. Save your script, and return to Unity.
  1. We will now need to assign this script to our player by selecting the Player object in the Hierarchy window, and then in the Inspector window, drag and drop the PlayerBehaviour script from the Project window on top of the Player object. If all goes well, we should see the script appear on our object, as follows:

Note that when writing scripts if we declare a variable as public, it will show up in the Inspector window for us to be able to set it. We typically set a variable as public when we want designers to tweak the values for gameplay purposes.

  1. Save your scene by going to File | Save Scene. Create a new folder called Scenes and save your scene as Gameplay. Afterward, play the game and use the left and right arrows to see the player moving according to your input, but no matter what, moving forward by default:

Improving our scripts with attributes and XML comments

We could stop working with the PlayerBehaviour class script here, but I want to touch on a couple of things that we can use in order to improve the quality and style of our code. This becomes especially useful when you start building projects in teams, as you'll be working with other people--some of them will be working on code with you, and then there are designers and artists who will not be working on code with you, but will still need to use the things that you've programmed.

When writing scripts, we want them to be as error-proof as possible. Making the rb variable private starts that process, as now the user will not be able to modify that anywhere outside of this class. We want our teammates to modify dodgeSpeed and rollSpeed, but we may want to give them some advice as to what it is and/or how it will be used. To do this in the Inspector window, we can make use of something called an attribute.

Using attributes

Attributes are things we can add to the beginning of a variable, class, or function declaration, which allow us to attach an additional functionality to them. There are many of them that exist inside Unity, and you can write your very own as well, but, right now, we'll talk about the ones that I use most often.

The Tooltip attribute

If you've used Unity for a period of time, you may have noted that some components in the Inspector window, such as the Rigidbody, have a nice feature--if you move your mouse over a variable name, you'll see a description of what the variables are and/or how to use them. The first thing you'll learn is how we can get the same effect in our own components by making use of the Tooltip attribute. If we do this for the dodgeSpeed and rollSpeed variables, it will look something like this:

[Tooltip("How fast the ball moves left/right")] 
public float dodgeSpeed = 5;

[Tooltip("How fast the ball moves forwards automatically")]
public float rollSpeed = 5;

Save the preceding script and return to the editor:

Now, when we highlight the variable using the mouse and leave it there, the text we placed will be displayed. This is a great habit to get into, as your teammates can always tell what it is that your variables are being used for.

For more information on the Tooltip attribute, check out, https://docs.unity3d.com/ScriptReference/TooltipAttribute.html.

The Range attribute

Another thing that we can use to protect our code is the Range attribute. This will allow us to specify a minimum and maximum value for a variable. Since we want the player to always be moving forward, we may want to restrict the player from moving backward. To do that, we can add the following highlighted line of code:

    [Tooltip("How fast the ball moves forwards automatically")] 
[Range(0, 10)]
public float rollSpeed = 5;

Save your script, and return to the editor:

We have now added a slider beside our value, and we can drag it to adjust between our minimum and maximum values. Not only does this protect our variable, it also makes it so our designers can tweak things easily by just dragging them around.

The RequireComponent attribute

Currently, we are using the Rigidbody component in order to create our script. When working as a team member, others may not be reading your scripts, but are still expected to use them when creating gameplay. Unfortunately, this means that they may do things that have unintended results, such as removing the Rigidbody component, which will cause errors when our script is run. Thankfully, we also have the RequireComponent attribute, which we can use to fix this.

It looks something like this:

using UnityEngine; 

[RequireComponent(typeof(Rigidbody))]
public class PlayerBehaviour : MonoBehaviour

By adding this attribute, we state that when we add this component to a game object and it doesn't have a Rigidbody attached to its game object, the component will be added automatically. It also makes it so that if we were to try to remove the Rigidbody from this object, the editor will warn us that we can't, unless we remove the PlayerBehaviour component first. Note that this works for any class extended from MonoBehaviour; just replace Rigidbody with whatever it is that you wish to keep.

Now, if we go into the Unity editor and try to remove the Rigidbody component by right-clicking on it in the Inspector and selecting Remove Component, the following message will be seen:

This is exactly what we want, and this ensures that the component will be there, allowing us not to have to include if-checks every time we want to use a component.

XML comments

Note that previously we did not use a Tooltip attribute on the private rb variable. Since it's not being displayed in the editor, it's not really needed. However, there is a way that we can enhance that as well, making use of XML comments. XML comments have a couple of nice things that we get when using them instead of traditional comments, which we were using previously. When using the variables/functions instead of code in Visual Studio, we will now see a comment about it. This will help other coders on your team have additional information and details to ensure that they are using your code correctly.

XML comments look something like this:

/// <summary> 
/// A reference to the Rigidbody component
/// </summary>
private Rigidbody rb;

It may appear to be a lot more writing is needed to use this format, but I did not actually type the entire thing out. XML comments are a fairly standard C# feature, so if you are using MonoDevelop or Visual Studio and type ///, it will automatically generate the summary blocks for you (and the param tags needed, if there are parameters needed for something like a function).

Now, why would we want to do this? Well, now, if you select the variable in Intellisense, it will display the following information to us:

This is a great help for when other people are trying to use your code and it is how Unity's staff write their code. We can also extend this to functions and classes to ensure that our code is more self-documented.

Unfortunately, XML comments do not show up in the Inspector, and the Tooltip attribute doesn't show info in the editor. With that in mind, I used Tooltips for public instructions and/or things that will show up in the Inspector window, and XML comments for everything else.

If you're interested in looking into XML comments more, feel free to check out: https://msdn.microsoft.com/en-us/library/b2s063f7.aspx.

Putting it all together

With all of the stuff we've been talking about, we can now have the final version of the script, which looks like the following:

using UnityEngine; 

/// <summary>
/// Responsible for moving the player automatically and
/// reciving input.
/// </summary>
[RequireComponent(typeof(Rigidbody))]

public class PlayerBehaviour : MonoBehaviour
{
/// <summary>
/// A reference to the Rigidbody component
/// </summary>
private Rigidbody rb;

[Tooltip("How fast the ball moves left/right")]
public float dodgeSpeed = 5;


[Tooltip("How fast the ball moves forwards automatically")]
[Range(0, 10)]
public float rollSpeed = 5;

/// <summary>
/// Use this for initialization
/// </summary>
void Start ()
{
// Get access to our Rigidbody component
rb = GetComponent<Rigidbody>();
}

/// <summary>
/// Update is called once per frame
/// </summary>
void Update ()
{
// Check if we're moving to the side
var horizontalSpeed = Input.GetAxis("Horizontal") *
dodgeSpeed;

// Apply our auto-moving and movement forces
rb.AddForce(horizontalSpeed, 0, rollSpeed);
}
}

I hope that you also agree that this makes the code easier to understand and better to work with.

Having the camera following our player

Currently, our camera stays in the same spot while the game is going on. This does not work very well for this game, as the player will be moving more the longer the game is going on. There are two main ways that we can move our camera. We can just move the camera and make it a child of the player, but that will not work due to the ball's rotation. Due to that, we will likely want to use a script instead. Thankfully, we can modify how our camera looks at things fairly easily, so let's go ahead and fix that next:

  1. Go to the Project window and create a new C# script called CameraBehaviour. From there, use the following code:
using UnityEngine; 

/// <summary>
/// Will adjust the camera to follow and face a target
/// </summary>
public class CameraBehaviour : MonoBehaviour
{
[Tooltip("What object should the camera be looking at")]
public Transform target;

[Tooltip("How offset will the camera be to the target")]
public Vector3 offset = new Vector3(0, 3, -6);

/// <summary>
/// Update is called once per frame
/// </summary>
void Update ()
{
// Check if target is a valid object
if (target != null)
{
// Set our position to an offset of our target
transform.position = target.position + offset;

// Change the rotation to face target
transform.LookAt(target);
}

}
}
  1. Save the script and dive back into the Unity Editor. Select the Main Camera object in the Hierarchy window. Then, go to the Inspector window and add the CameraBehaviour component to it. You may do this by dragging and dropping the script from the Project window onto the game object or by clicking on the Add Component button at the bottom of the Inspector window, typing in the name of our component, and then clicking on Enter to confirm once it is highlighted.
  1. Afterward, drag and drop the Player object from the Hierarchy window into the Target property of the script in the Inspector window:
  1. Save the scene, and play the game:

The camera now follows the player as it moves. Feel free to tweak the variables and see how it effects the look of the camera to get the feel you'd like best for the project.

Creating a basic tile

We want our game to be endless, but in order to do so, we will need to have pieces that we can spawn to build our environment; let's do that now:

  1. To get started, we will first need to create a single piece for our runner game. To do that, let's first add some walls to the floor we already have. From the Hierarchy window, select the Floor object and duplicate it by pressing Ctrl + D in Windows or command + D on Mac. Rename this new object as Left Wall.

  1. Change the Left Wall object's Transform component by adjusting the Scale to (1, 2, 10). From there, select the Move tool by clicking on the button with arrows on the toolbar or by pressing the W key.
For more information on Unity's built-in hotkeys, check out: https://docs.unity3d.com/Manual/UnityHotkeys.html.
  1. We want this wall to match up with the floor, so hold down the V key to enter the Vertex Snap mode.

In the Vertex Snap mode, we can select any of the vertices on a mesh and move it to the same position of another vertex on a different object. This is really useful for making sure that objects don't have holes between them.

  1. With the Vertex Snap mode on, select the inner edge and drag it until it hits the edge of the floor.
For more info on moving objects through the scene, including more details on Vertex Snap mode, check out https://docs.unity3d.com/Manual/PositioningGameObjects.html.
  1. Then, duplicate this wall and put an other on the other side, naming it Right Wall:

As you can see in the preceding screenshot, we now protect the player from falling off the left and right edges of the play area. Due to how the walls are set up, if we move the floor object, the walls will move as well.

For info on moving Unity's camera or navigating to the scene view, check out: https://docs.unity3d.com/Manual/SceneViewNavigation.html.

The way this game is designed, after the ball rolls past a single tile, we will no longer need it to be there anymore. If we just leave it there, the game will get slower over time due to us having so many things in the game environment using memory, so it's a good idea to remove assets we are no longer using. We also need to have some way to figure out when we should spawn new tiles to continue the path the player can take.

  1. Now, we also want to know where this piece ends, so we'll add an object with a Trigger collider in it. Select GameObject | Create Empty and name this object Tile End.
  2. Then, we will add a Box Collider component to our Tile End object. Under the Box Collider in the Inspector window, set the Size to (7, 2, 1) to fit the size of the space the player can walk in. Note that there is a green box around that space showing where collisions can take place. Set the Position property to (0, 1, 10) to reach past the end of our tile. Finally, check the Is Trigger property so that the collision engine will turn the collider into a trigger, which will be able to run code events when it is hit, but will not prevent the player from moving:

Like I mentioned briefly before, this trigger will be used to tell the game that our player has finished walking over this tile. This is positioned past the tile due to the fact that we want to still see tiles until they pass what the camera can see. We'll tell the engine to remove this tile from the game, but we will dive more into that later on in the chapter.

  1. Now that we have all of the objects created, we want to group our objects together as one piece that we can create duplicates of. To do this, let's create an Empty Game Object by going to GameObject | Create Empty and name the newly created object to Basic Tile.
  1. Then, go to the Hierarchy window and drag and drop the Floor, Tile End, Left Wall, and Right Wall objects on top of it to make them children of the Basic Tile object.
  2. Currently, the camera can see the start of the tiles, so to fix that, let's set the Basic Tile's Position to (0, 0, -5) so that the entire tile will shift back.
  3. Finally, we will need to know at what position we should spawn the next piece, so create another child of Basic Tile, give it the name, Next Spawn Point, and set its Position to (0, 0, 5).
Note that when we modify an object that has a parent, the position is relative to the parent, not its world position.

Notice that the spawn point is on the edge of our current title. Now we have a single tile that is fully completed. Instead of duplicating this a number of times by hand, we will make use of Unity's concept or prefabs.

Prefabs, or prefabricated objects, are blueprints of game objects and components that we can turn into files, which can be duplicates. There are other interesting features that prefabs have, but we will discuss them as we make use of them.

  1. From the Project window, go to the Assets folder and then create a new folder called Prefabs. Then, drag and drop the Basic Tile object from the Hierarchy window to the Project window inside the Prefabs folder. If the text on the Basic Tile name in the Hierarchy window becomes blue, we will know that it was made correctly:

With that, we now have a tile prefab that we can create duplicates of the tile through code to extend our environment.

Making it endless

Now that we have a foundation, let's now make it so that we can continue running instead of stopping after a short time:

  1. To start off with, we have our prefab, so we can delete the original Basic Tile in the Hierarchy window by selecting it and then pressing the Delete key.
  1. We need to have a place to create all of these tiles and potentially manage information for the game, such as the player's score. In Unity, this is typically referred to as a GameController. From the Project window, go to the Scripts folder and create a new C# script called GameController.
  2. Open the script in your IDE, and use the following code:
using UnityEngine;

/// <summary>
/// Controls the main gameplay
/// </summary>

public class GameController : MonoBehaviour
{
[Tooltip("A reference to the tile we want to spawn")]
public Transform tile;

[Tooltip("Where the first tile should be placed at")]
public Vector3 startPoint = new Vector3(0, 0, -5);

[Tooltip("How many tiles should we create in advance")]
[Range(1, 15)]
public int initSpawnNum = 10;

/// <summary>
/// Where the next tile should be spawned at.
/// </summary>
private Vector3 nextTileLocation;

/// <summary>
/// How should the next tile be rotated?
/// </summary>
private Quaternion nextTileRotation;

/// <summary>
/// Used for initialization
/// </summary>

void Start()
{
// Set our starting point
nextTileLocation = startPoint;
nextTileRotation = Quaternion.identity;

for (int i = 0; i < initSpawnNum; ++i)
{
SpawnNextTile();
}
}

/// <summary>
/// Will spawn a tile at a certain location and setup the next position
/// </summary>

public void SpawnNextTile()
{
var newTile = Instantiate(tile, nextTileLocation,
nextTileRotation);

// Figure out where and at what rotation we should spawn
// the next item
var nextTile = newTile.Find("Next Spawn Point");
nextTileLocation = nextTile.position;
nextTileRotation = nextTile.rotation;
}
}

This script will spawn a number of tiles, one after another, based on the tile and initSpawnNum properties.

  1. Save your script and dive back into Unity. From there, create a new Empty game object and name it Game Controller. Drag and drop it to the top of the Hierarchy window. For clarity's sake, go ahead and reset the position if you want to. Then, attach the Game Controller script to the object and then set the Tile property by dragging and dropping the Basic Tile prefab from the Project window into the Tile slot:
  1. Save your scene and run the project:

Great, but now we will need to create new objects after these, but we don't want to spawn a crazy number of these at once. It's better that once we reach the end of a tile, we create a new tile and remove it. We'll work on optimizing this more later, but that way we always have around the same number of tiles in the game at one time.

  1. Go into the Project window and create a new script called TileEndBehaviour, using the following code:
using UnityEngine; 

/// <summary>
/// Handles spawning a new tile and destroying this one
/// upon the player reaching the end
/// </summary>
public class TileEndBehaviour : MonoBehaviour
{
[Tooltip("How much time to wait before destroying " +
"the tile after reaching the end")]
public float destroyTime = 1.5f;

void OnTriggerEnter(Collider col)
{
// First check if we collided with the player
if (col.gameObject.GetComponent<PlayerBehaviour>())
{
// If we did, spawn a new tile
GameObject.FindObjectOfType<GameController>().SpawnNextTile();

// And destroy this entire tile after a short delay
Destroy(transform.parent.gameObject, destroyTime);
}
}
}
  1. Now, to assign it to the prefab, we can go to the Project window and then go into the Prefabs folder. From there, click on the arrow beside the Basic Tile to open up its objects and then add a Tile End Behaviour component to the Tile End object:
  1. Save your scene and play.

You'll note now that as the player continues to move, new tiles will spawn as you continue; if you switch to the Scene tab while playing, you'll see that as the ball passes the tiles they will destroy themselves:

Creating obstacles

It's great that we have some basic tiles, but it's a good idea to give the player something to do or, in our case, something to avoid. In this section, you'll learn how to customize your tiles to add obstacles for your player to avoid:

  1. So, just like we created a prefab for our basic tile, we will create a single obstacle through code. I want to make it easy to see what the obstacle will look like in the world and make sure that it's not too large, so I'll drag and drop a Basic Tile prefab back into the world.
  1. Next, we will create a cube by going to GameObject | 3D Object | Cube. We will then name this object Obstacle. Change the Y Scale to 2 and position it above the platform at (0, 1, .025):
  1. We can then play the game to see how this'll work:
  1. As you can see in the preceding screenshot, the player gets stopped, but nothing really happens. In this instance, we want the player to lose when he hits this and then restart the game; so, to do that, we'll need to write a script. From the Project window, go to the Scripts folder and create a new script called ObstacleBehaviour. We'll use the following code:
using UnityEngine; 
using UnityEngine.SceneManagement; // LoadScene

public class ObstacleBehaviour : MonoBehaviour {

[Tooltip("How long to wait before restarting the game")]
public float waitTime = 2.0f;

void OnCollisionEnter(Collision collision)
{
// First check if we collided with the player
if (collision.gameObject.GetComponent<PlayerBehaviour>())
{
// Destroy the player
Destroy(collision.gameObject);

// Call the function ResetGame after waitTime has passed
Invoke("ResetGame", waitTime);
}
}

/// <summary>
/// Will restart the currently loaded level
/// </summary>
void ResetGame()
{
// Restarts the current level
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
  1. Save the script and return to the editor, attaching the script to the Obstacle property we just created.
  2. Save your scene and try the game:

As you can see in the preceding screenshot, once we hit the obstacle, the player gets destroyed, and then after a few seconds, the game starts up again. You'll learn to use particle systems and other things to polish this up, but at this point, it's functional, which is what we want.

You may note that when the level is reloaded, there are some lighting issues in the editor. The game will still work correctly when exported, but this may be a minor annoyance.

  1. (Optional) To fix this, go to Window | Lighting | Settings. Uncheck the Auto Generate option from there, and click on Generate Lighting--once it is finished, our issue should be solved.
It isn't an issue with our game, but if you employ the fix above in your own titles, you must remember to go here every time you alter a game level and rebuild the lightmap for it to be updated correctly.
  1. Now that we know it works correctly, we can make it a prefab. Just as we did with the original tile, go ahead and drag and drop it from the Hierarchy into the Project tab and into the Prefabs folder:
  1. Next, we will remove the Obstacle, as we'll spawn it upon creating the tile.
  1. We will make markers to indicate where we would possibly like to spawn our obstacles. Duplicate the Next Spawn Object object and move the new one to (0, 1, 4). We will then rename the object as Center. Afterwards, click on the icon on the top left of the blue box and then select the blue color. Upon doing this, you'll see that we can see the text inside the editor, if we are close to the object (but it won't show up in the Game tab by default):
  1. We want a way to get all of the potential spawn points we will want in case we decide to extend the project in the future, so we will assign a tag as a reference to make those objects easier to find. To do that at the top of the Inspector window, click on the tag dropdown and select Add Tag. From the menu that pops up, press the + button and then name it ObstacleSpawn.
For more information on tags and why we'd want to use them, check out https://docs.unity3d.com/Manual/Tags.html.
  1. Go ahead and duplicate this twice and name the others Left and Right, respectively, moving them 2 units to the left and right of the center to become other possible obstacle points:
  1. Note that these changes don't affect the original prefab, by default; that's why the objects are currently black text. To make this happen, select Basic Tile, and then in the Inspector window under the Prefab section, click on Apply.
  2. Now that the prefab is set up correctly, we can go ahead and remove it by selecting it and pressing Delete.
  3. We then need to go into the GameController script and modify it to have the following code:
using UnityEngine;
using System.Collections.Generic; // List

/// <summary>
/// Controls the main gameplay
/// </summary>

public class GameController : MonoBehaviour
{
[Tooltip("A reference to the tile we want to spawn")]
public Transform tile;

[Tooltip("A reference to the obstacle we want to spawn")]
public Transform obstacle;

[Tooltip("Where the first tile should be placed at")]
public Vector3 startPoint = new Vector3(0, 0, -5);

[Tooltip("How many tiles should we create in advance")]
[Range(1, 15)]
public int initSpawnNum = 10;

[Tooltip("How many tiles to spawn initially with no obstacles")]
public int initNoObstacles = 4;

/// <summary>
/// Where the next tile should be spawned at.
/// </summary>
private Vector3 nextTileLocation;

/// <summary>
/// How should the next tile be rotated?
/// </summary>
private Quaternion nextTileRotation;

/// <summary>
/// Used for initialization
/// </summary>
void Start()
{
// Set our starting point
nextTileLocation = startPoint;
nextTileRotation = Quaternion.identity;

for (int i = 0; i < initSpawnNum; ++i)
{
SpawnNextTile(i >= initNoObstacles);
}
}

/// <summary>
/// Will spawn a tile at a certain location and setup the next
position
/// </summary>
public void SpawnNextTile(bool spawnObstacles = true)
{
var newTile = Instantiate(tile, nextTileLocation,
nextTileRotation);

// Figure out where and at what rotation we should spawn
// the next item
var nextTile = newTile.Find("Next Spawn Point");
nextTileLocation = nextTile.position;
nextTileRotation = nextTile.rotation;

if (!spawnObstacles)
return;

// Now we need to get all of the possible places to spawn the
// obstacle
var obstacleSpawnPoints = new List<GameObject>();

// Go through each of the child game objects in our tile
foreach (Transform child in newTile)
{
// If it has the ObstacleSpawn tag
if (child.CompareTag("ObstacleSpawn"))
{
// We add it as a possibilty
obstacleSpawnPoints.Add(child.gameObject);
}
}

// Make sure there is at least one
if (obstacleSpawnPoints.Count > 0)
{
// Get a random object from the ones we have
var spawnPoint = obstacleSpawnPoints[Random.Range(0,
obstacleSpawnPoints.Count)];

// Store its position for us to use
var spawnPos = spawnPoint.transform.position;

// Create our obstacle
var newObstacle = Instantiate(obstacle, spawnPos,
Quaternion.identity);

// Have it parented to the tile
newObstacle.SetParent(spawnPoint.transform);
}
}
}

Note that we modified the SpawnNextTile function to now have a default parameter set to true, which will tell us if we want to spawn obstacles or not. At the beginning of the game, we may not want the player to have to start dodging immediately, but we can tweak the value to increase or decrease the number we are using.

  1. Save the script and go back to the Unity editor. Then, assign the Obstacle variable in the Inspector with the obstacle prefab we created previously.
  2. It's a bit hard to see things currently due to the default light settings, so let's go to the Hierarchy window and select the Directional Light object.

A directional light acts similarly to how the sun works on earth, shining everywhere from a certain rotation.

  1. With the default settings the light is too bright, making it difficult to see, so we can just change the Color to be darker. I used the following:
  1. Save your scene and play the game:
For more information on directional lights and the other lighting types that Unity has, check out: https://unity3d.com/learn/tutorials/topics/graphics/light-types?playlist=17102.

As you can see in the preceding screenshot, we now have a number of obstacles for our player to avoid, and due to how the player works, he will gradually get faster and faster, causing the game to increase in difficulty over time.

Summary

There we have it! A solid foundation, but just that, a foundation. However, that being said, we covered a lot of content in this chapter. We discussed how to create a new project in Unity, we built a player that will move continuously, as well as take inputs to move horizontally. We then discussed how we can use Unity's attributes and XML comments to improve our code quality and help us when working with teams. We also covered how to have a moving camera. We created a tile-based level design system, where we created new tiles as the game continued, randomly spawning obstacles for the player to avoid.

Throughout this book, we will explore more that we can do to improve this project and polish it, while adapting it to being the best experience possible on mobile platforms. However, before we get to that, we'll actually need to figure out how to deploy our projects.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • • One-stop solution to becoming proficient in mobile game development using Unity 2017
  • • Port your Unity games to popular platforms such as iOS and Android
  • • Unleash the power of C# scripting to create realistic gameplay and animations in Unity 2017.

Description

Unity has established itself as an overpowering force for developing mobile games. If you love mobile games and want to learn how to make them but have no idea where to begin, then this book is just what you need. This book takes a clear, step-by-step approach to building an endless runner game using Unity with plenty of examples on how to create a game that is uniquely your own. Starting from scratch, you will build, set up, and deploy a simple game to a mobile device. You will learn to add touch gestures and design UI elements that can be used in both landscape and portrait mode at different resolutions. You will explore the best ways to monetize your game projects using Unity Ads and in-app purchases before you share your game information on social networks. Next, using Unity’s analytics tools you will be able to make your game better by gaining insights into how players like and use your game. Finally, you’ll learn how to publish your game on the iOS and Android App Stores for the world to see and play along.

Who is this book for?

If you are a game developer and want to build mobile games for iOS and Android, then this is the book for you. Previous knowledge of C# and Unity is helpful, but not required.

What you will learn

  • • Use Unity to build an endless runner game
  • • Set up and deploy a project to a mobile device
  • • Create interesting gameplay elements using inputs from your mobile device
  • • Monetize your game projects with Unity ads and in-app purchases
  • • Design UI elements that can be used well in Landscape and Portrait mode at different resolutions, supporting phones, tablets, and PCs.
  • • How to submit your game to the iOS and Android app stores
Estimated delivery fee Deliver to Turkey

Standard delivery 10 - 13 business days

$12.95

Premium delivery 3 - 6 business days

$34.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Nov 30, 2017
Length: 360 pages
Edition : 1st
Language : English
ISBN-13 : 9781787288713
Vendor :
Unity Technologies
Languages :
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Estimated delivery fee Deliver to Turkey

Standard delivery 10 - 13 business days

$12.95

Premium delivery 3 - 6 business days

$34.95
(Includes tracking information)

Product Details

Publication date : Nov 30, 2017
Length: 360 pages
Edition : 1st
Language : English
ISBN-13 : 9781787288713
Vendor :
Unity Technologies
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 152.97
Mastering Unity 2017 Game Development with C#
$54.99
Unity 2017 Mobile Game Development
$48.99
Unity 2017 Game Optimization
$48.99
Total $ 152.97 Stars icon

Table of Contents

10 Chapters
Building Your Game Chevron down icon Chevron up icon
Setup for Android and iOS Development Chevron down icon Chevron up icon
Mobile Input/Touch Controls Chevron down icon Chevron up icon
Resolution Independent UI Chevron down icon Chevron up icon
Advertising Using Unity Ads Chevron down icon Chevron up icon
Implementing In-App Purchases Chevron down icon Chevron up icon
Getting Social Chevron down icon Chevron up icon
Using Unity Analytics Chevron down icon Chevron up icon
Making Your Title Juicy Chevron down icon Chevron up icon
Game Build and Submission Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Half star icon Empty star icon Empty star icon 2.5
(2 Ratings)
5 star 0%
4 star 50%
3 star 0%
2 star 0%
1 star 50%
Christina Myers Jul 12, 2019
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
Pretty good book for beginners in Unity that have some programming experience. My one criticism is just that the game design choices made were often pretty cheesy and unfinished, so the work just wasn’t that impressive; however, I did glean enough knowledge through this to apply things that made for a much cleaner product that I had fun with.
Amazon Verified review Amazon
BE81 Mar 13, 2019
Full star icon Empty star icon Empty star icon Empty star icon Empty star icon 1
The book is very overpriced for what is inside. I returned the book after realising that it was inadequate for what I needed. There is only development for one project in the book. I feel online videos on YouTube were better than this and cheaper Udemy courses.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela