Introduction: Make a 2D Video Game With Unity

Picture of Make a 2D Video Game With Unity


In this Instructable, I will show you to make a really simple 2D Video game. It is an infinite runner style game, like "Fly with Me' or "DoodleJump".

Try it out here!!

I have provided a zip of the exe of the game I will be showing you how to make. Download it and give it a try.

It is wholly incomplete as far as a game goes, but served me as a fantastic opportunity to learn a little bit of C# scripting and to solidify the knowledge of Unity I have picked up since having downloaded it two weeks ago. For the purpose of sharing , I decided to use Instructables very own lovable Robot as the main character. I went for a simplistic look in homage to those cartoons of yore done in the same style. I always loved when the pencil interacted with the cartoon.

I have to say that Unity is an incredible tool. There is a wealth of information available in learning section of the Unity site, I highly recommend giving it a look through once you have seen how simple it is to start making 2D games.

Everything I am showing you here, I learned from the Unity site, they have some great tutorials and video training sessions.

I am new to Unity as you may or may not be, so this is just to share my love of the environment and my learning experience thus far. 

I will provide the sprite assets for each step so that you can follow along, and make the game yourself. I recommend not using my code as is, but rather following along and writing your own version of the same scripts.

I have little to no experience programming in C, and yet was scripting in C# pretty quickly....it reminds me an awful lot of Arduino and Processing, which I am familiar with.

So even if you have no familiarity with programming, I believe you could do this too. At least follow along with my adventure to see how easy it was.

Step 1: Download the Free Unity Software

Picture of Download the Free Unity Software

Bascillay Unity is kind enough to let those of us who wish we could get into game dev, take a stab at learning it for free, so long as we don't make any money with products we make using their software. Awesome. Thank you so much Unity, for the encouragement and freedom to try it out, and for the incredible software.

If you are planning on following along, you will need to go to the Unity Homepage and download the free version of the software.
You will also need to create a Unity Login, just follow the steps after installing.

Step 2: Open Up Unity

Picture of Open Up Unity

If it your first time opening Unity, you will be presented with a dialog box to create a new project. Browse to a suitable location, and give your project a name, something like "Iblejump".
It is very important to check the 2D selection at the bottom of the form where it says "Setup Defaults For". 

You will not need to import any of the packages for the game we will be making. I would advise not bothering with them unless you need them for your game. No sense in including extra bulk to our build files.

When you have made the proper selections, go ahead and hit 'create'.

Now the Unity Editor will open our new empty project and present us with a nice welcome popup. Let's close that for now and  explore the interface a little bit.

The work area is divided into four different sections, which you can organize to suit your workflow.

The hierarchy window on the left side shows you all the objects that are currently in your scene. The scene window is where we will build and place our game objects. 

Down below we have another work area where you can dock an undock different tabs. Most of the tabs can be docked into an area that you find convenient. This is how I have my area set up, you might do things a bit differently. The main thing to be aware of is that you can access all of these windows from the window pull down menu, and add or subtract them as need be. you needn't worry if your window doesn't look identical. I will show you each of the areas we will use in more detail as we go.

For now just click on your "Main Camera" so you can see what happens over to the right in the Inspector and scene windows.
Notice how you now have a preview of your empty scene in the bottom corner of the scene window, and all of the components and property values for the camera are exposed.




Step 3: Create Your First Game Object

Picture of Create Your First Game Object


First you'll need the Sprites folder that I have included as a zipped file. Extract the folder to somewhere you can find it.

In Unity, down in the project work area, under the project tab, with Assets selected, drag the unzipped folder into the gray area on the right. All of the sprites that you will need to duplicate my project are in this folder.

Navigate to the new Sprites folder and find a sprite named "navbar". Drag that up into the Scene window. Drop it somewhere near the bottom of your scene, as I have done in the image.

If you click Main Camera in your hierarchy window after placing it, you can already see how it will look in your game.

We will need to add some components, let's start with a box colllider, to make our box solid.

With your new object selected, in the Inspector, click on "Add Component" and then add a Box Collider 2D, found under Physics2D

Go Ahead and add a second 2D Box Collider to your object, this one we will use to block the player from accidentally falling off the side of the navbar right at the begining of the game.

Because I wanted Robot to start about where he is on the Instructables web page ,I shrunk the main collider a little. And the second collider is actually sitting in open space, which will prevent our player from running off the left side when the game begins.

Set up your box colliders to match the sizes in the image, also set the x and y size of the transform parameter to 1.5. Watch the changes take place in the scene window.

Step 4: Add a Player

Picture of Add a Player

Now that we have a platform for our player to stand on, we will need a player.

Click on GameObject in the top menu bar, select create empty.

Select your new empty game object in the Hierarchy window, and over in the Inspector, change it's name to Player.
Next add a Sprite Renderer Component, found under Rendering.

In the project assets/sprites folder, find the Idle_Sprite, click the little triangle beside it and then drag one of the images into the Sprite value of the sprite renderer component.

We'll need a few more components for our Player. First add a Rigidbody2D from the Physics2D choices.

If you press the play button now, our Player will fall through the navbar. Go on try it out.

We will fix that by adding a few colliders. Somewhat counter intuitively, we will add a circle collider to our feet and body, and a box collider to our head.

Now, if we press play, our little robot will roll over onto his back as any circle bottomed robot would. Fix that by checking the Fixed Angle check box, and then when you press play, your robot should fall to the navbar and rest there nicely.

He is a little big for my liking, so I changed his size in transform to .75 x and .75 y.

Then I fiddled with the positioning of the navbar and robot until I was happy.

Now is a good time to save your scene, give it a name that feels good to you and save it.

Step 5: Add Some Life to Robot

Picture of Add Some Life to Robot

Okay, now that we have the player object in place, we can start to add some animation and functionality to it.

With the Player Object selected, add a Animator Component. Add Component-->Miscellaneous-->Animator.
Uncheck "Apply Root Motion", and check the "Animate Physics" box.

Now open your Animator window. You can do this via the Window pull down if it is not already open in the project work area. I like to dock mine at the bottom.

With Player still selected in Hierarchy, Open the Animation window. It can also be found in the Window pull down. I like to dock mine in the same area as my scene and game windows.

In the Animation window, click the tiny little triangles beside "sample" to create a new clip.

Down below, open your asset/sprites folder and open up the idle sprite again. Shift select the entire series of images and drag them up to the animation window.

Because the animator (me) was cheap on frames, reset the sample size to 10.

Now look at  your Animator, you should automatically have two states added, an any state, and a new default state, Idle. The orange colour tells us that it is the default animation state.

If you have followed these steps correctly, you should have an animated Robot now when you press play.

Create another animation and call it drive. Use the Drive sprite sheet. Again, lower the frame rate. I am putting it at 20 for now. You can tweek it later to your liking.

In the Animator window, you will see that a second state has automatically been created. Great! Let's a add a float parameter named "Speed" to our Animator before we create the transitions.

Now right click on the Idle state, and select "make Transition". Then drag to the drive state. This should make a little arrow bar. select the triangle in the center of the transition bar. Change the transition condition in the inspector to be when Speed is greater than 0.01. Now create a transition from drive back to idle with the condition that Speed  is less than 0.01.

Next we'll need to build a controller script for Robot.

Step 6: The Robot Controller Script

Picture of The Robot Controller Script
Now that we have a Player with some animation states, we need a script to control the character. We'll add a simple C# script to our project to control our Player.

In the Project window, create a new folder and call it Scripts. Open that folder and create a new C# script, call it RobotController.

Double Click the script to launch MonoDevelop. It can take a moment to open up, be patient.
Enter the following code to begin
using UnityEngine;
using System.Collections;

public class RobotController : MonoBehaviour {
//This will be our maximum speed as we will always be multiplying by 1
public float maxSpeed = 2f;
//a boolean value to represent whether we are facing left or not
bool facingLeft = true;
//a value to represent our Animator
Animator anim;
// Use this for initialization
void Start () {
  //set anim to our animator
  anim = GetComponent<Animator>();

}

// Update is called once per frame
void FixedUpdate () {

  float move = Input.GetAxis ("Horizontal");//Gives us of one if we are moving via the arrow keys
  //move our Players rigidbody
  rigidbody2D.velocity = new Vector3 (move * maxSpeed, rigidbody2D.velocity.y);
  //set our speed
  anim.SetFloat ("Speed",Mathf.Abs (move));
  //if we are moving left but not facing left flip, and vice versa
  if (move < 0 && !facingLeft) {
  
   Flip ();
  } else if (move > 0 && facingLeft) {
   Flip ();
  }
}

//flip if needed
void Flip(){
  facingLeft = !facingLeft;
  Vector3 theScale = transform.localScale;
  theScale.x *= -1;
  transform.localScale = theScale;
}
}

Save the script and return to the Unity window. Drag the new RobotController script from the project work are onto the Player object in the Hierarchy window. Press the play button to run the game and you should be able to control the robot with the left and right arrow keys. If you open the Animator window below the game, you should see the animation changing states from drive to idle depending on whether or not Robot is moving.

Step 7: Get Jumping - Player Controller Script Continued

Picture of Get Jumping - Player Controller Script Continued
Just a few steps to implement in order to get our Player jumping.
We will need an animation state for Jumping and falling, and also some more code to control things.

Let`s start by adding two more parameters to our Player Animator. Add a float called `vSpeed``and a Bool called `Ground`. We will use vSpeed to hold our vertical speed, and Ground will be in place to help us detect when our character is on the ground, allowing for a more realistic jump. (Jumping through air without touching the ground is more like flying).

Back in the scene window, create a new empty Game Object. Call it groundcheck and add a 2D Circle Collider to it.
Drag the new Collider into the Player object in the Hierarchy window. Change the radius of groundcheck's collider to 0.1, and change it's y transform position to -1. This puts a little tiny circle right under Robots feet. Also tag it as Player and put in on the Player Layer.

Now let's update our scrip to use our new parameters and put the code in place to make Robot jump when space bar is pressed.

Update your RobotController script to be as follows.

using UnityEngine;
using System.Collections;

public class RobotController : MonoBehaviour {
	//This will be our maximum speed as we will always be multiplying by 1
	public float maxSpeed = 2f;
	//a boolean value to represent whether we are facing left or not
	bool facingLeft = true;
	//a value to represent our Animator
	Animator anim;
        //to check ground and to have a jumpforce we can change in the editor
	bool grounded = false;
	public Transform groundCheck;
	float groundRadius = 0.2f;
	public LayerMask whatIsGround;
	public float jumpForce = 700f;

	// Use this for initialization
	void Start () {
		//set anim to our animator
		anim = GetComponent <Animator>();

	}
	
	
	void FixedUpdate () {
                //set our vSpeed
		anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
                //set our grounded bool
		grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius, whatIsGround);
		//set ground in our Animator to match grounded
		anim.SetBool ("Ground", grounded);


		float move = Input.GetAxis ("Horizontal");//Gives us of one if we are moving via the arrow keys
		//move our Players rigidbody
		rigidbody2D.velocity = new Vector3 (move * maxSpeed, rigidbody2D.velocity.y);	
		//set our speed
		anim.SetFloat ("Speed",Mathf.Abs (move));
		//if we are moving left but not facing left flip, and vice versa
		if (move < 0 && !facingLeft) {
			
			Flip ();
		} else if (move > 0 && facingLeft) {
			Flip ();
		}
	}

	void Update(){
                //if we are on the ground and the space bar was pressed, change our ground state and add an upward force
		if(grounded && Input.GetKeyDown (KeyCode.Space)){
			anim.SetBool("Ground",false);
			rigidbody2D.AddForce (new Vector2(0,jumpForce));
		}
		
		
	}

	//flip if needed
	void Flip(){
		facingLeft = !facingLeft;
		Vector3 theScale = transform.localScale;
		theScale.x *= -1;
		transform.localScale = theScale;
	}
}

Return again to the Robot Controller Script in the Inspector, and make sure to set What Is Ground to everything except player. Select everything, then open the dialog again, and deselect Player.(Thanks c0)

In the next step we will create an Animator blend tree to handle jumping and falling.



Step 8: Make a Blend Tree Animation

Picture of Make a Blend Tree Animation

Let's make a blend tree to hold our different falling/jumping states. We could do separate animations for both, but this is more efficient and requires less bulk for our little game. Plus it is cool. (Did I mention that Unity hosts some great learning material?)

Go back to your player animation window, with your Player object selected create 5 new animation clips, name them jump1 -jump5.

For each clip, drag one frame from jumpsheet, in order. i.e jumpsheet first image to jump1, and so on.

Open the Animator window again, right click, create...new from bland tree. Name it JumpFall.
Double click on the new JumpFall state, opening the blend tree in the inspector.

Click the little plus sign and Add Motion field, do this five times.

Change the Threshold to range from -13 until 10, and change the threshold parameter to be vSpeed.

If you are dissatisfied with the animation, you can tweak the values by unchecking Automate Threshold. For this simple game, it seems good enough. (Animator got lazy ...again)

Now return to the Animator window, you will see the blend tree opened, click Base Layer in the upper left corner to go back to our base states.

You should delete all the auto generated jump states, Jump1 through Jump5  now as well. (Thanks c0)

Creat a Transition from the Any State to the new JumpFall state, and then one from JumpFall over to idle. This means that we can go into the jump animation from any state , i.e. if we fall.

Set the transition from Any State to JumpFall to be for when Ground is false, and the transition from JumpFall to idle to when ground is true. 

All done, run the game again and you should be able to make Robot jump and animate with the space bar. The animation is a little jerky for lack of frames, you can play with the motion field to change it a little if you like.

Step 9: Destroyers

Picture of Destroyers
In the coming steps, we will be creating objects that spawn more objects and without some clean up going on, our game will quickly become bogged down. With that in mind, we will take care of clean up by placing some objects off screen to destroy objects as they leave the play area.

Our game will be a side scroller, so we will place one beneath the scene to catch falling objects (like the Player) and one offscreen to the left to clean up anything that has already scrolled by.

Start by creating a quad. Click GameObject--.Create other-->Quad. Change it's transform position to x to -25 and y to 0. Then set the transform scale so X is 1 and y is 25.

Give the quad object a cool name, like Destroyer Remove the Mesh Collider component and add a box collider 2D, but this time check the box marked "Is Trigger".

Also add a rigidbody 2D to it, but set the gravity scale in the Inspector window to zero.

In the Project work area, open your Scripts folder, and add a new C# script, name it Destroyer. Double click it and open Monodevelop.

Enter the following code into the new script and save it.

using UnityEngine;
using System.Collections;

public class Destroyer : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	void OnTriggerEnter2D(Collider2D other){
		//if the object that triggered the event is tagged player
		if (other.tag == "Player") {
			
						Debug.Break ();
						return;
				}
			if (other.gameObject.transform.parent) {
				Destroy (other.gameObject.transform.parent.gameObject);
			} else {
				Destroy (other.gameObject);		
			}
	}

}

Drag the Destroy script onto the Destroyer object. 
Now right click on the Destroyer object in the Hierarchy window, and select Duplicate. Change the transform of the new Destroyer to be at position x = 0, y = -15, and the scale to x=50 and y = 1.

If you run your game now, and walk off the platform (remember, there is an invisible barrier on the left), it should pause the play and bring you back to the editor.

We will fix that in a later step.

The last thing to do with our Destroyer objects is to make them children off the camera object, as we will want them to follow along or they won`t be doing much at all. To do this, select them and drag them into the Main Camera object.

Step 10: The Hand

Picture of The Hand

The hand that draws the line is pretty simple. Let`s make it.

First drag the hand sprite into your scene window, position it by using your camera object to see where in the scene it is sitting.

Transform the scale so x=2 and y=2.

Create a new empty game object, and name it Penciltip. Use the scene editor to position it at the very tip of the pencil. 

Give it a little tag so that you can find it easily if need be. Do this by clicking on the little cube icon in the Inspector.

Now drag Penciltip into the hand object to pair them together. Finally drag the hand object into the Main Camera in the Hierarchy window.

It doesn`t do anything yet, but the pieces are in place. lets set up some other bits that we will need.

Step 11: Pencil Line

Picture of Pencil Line
A prefab is like a recording of an object, you make the object into a prefab and can use it at will in your scene.
We will be using them for a lot of the rest of the game, as the level is programmatically generated.

Start by creating a new folder in the Assets folder, and call it Prefabs. Create a new Prefab by right clicking and selecting Prefab. Name the new Prefab pencilline.

Find the sprite called pencilline in the sprite folder, and drag it into the new gameObject in the hierarchy window.

Add a box collider 2D and resize it to fit the pencilline image.0.03 by 0.05 works.

Open your Prefab folder, then drag the GameObject onto the prefab. The icon will change to match the new prefab.

Delete the game object once you have placed it into your prefab. We won`t need the original anymore.

Now add a new C# script to your Scripts folder, call it pencilline. Open it up and enter the following script.

using UnityEngine;
using System.Collections;

public class pencilline : MonoBehaviour {

	//to refer to our prefab pencilline
	public GameObject obj;
	
	float lastx = 0f;
	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
		
		//if we have moved far enough make a new pencilline
		
		if (transform.position.x > (lastx+0.02f)) {
			
			
			Instantiate (obj,transform.position,Quaternion.identity);
			lastx = transform.position.x;
			
			lastx = transform.position.x;
			
		}
		
	}
}
Drag the script onto the penciltip object in Hand. Then with penciltip still selected, open your prefab folder and drag your pencilline prefab over to the new obj parameter on your script controller.

Our Camera still has no control script, but if you run the game, you should see one pencilline object generated at the tip of the pencil. You can see it because the background is blue and the line was made for a white background.

Step 12: Roll Camera!

Picture of Roll Camera!
Let''s get the Camera rolling.
The Camera object is all made, so we really just need a controller script.

Just one little change before we write the script. The background colour. It needs to be white, the line will look crumby if not, not to mention the post it notes should you decide to use them.

Just select the main camera in the hierarchy window, and click the colour swatch in the Inspector, a colour selector will pop up. Choose white.

 Okay, new script, i called mine pancam. Create one in your script folder and open it in Monodevelop, and enter the following.

using UnityEngine;
using System.Collections;

public class pancam : MonoBehaviour {

	float ydir = 0f;
	public GameObject player;

	// Use this for initialization

	// Update is called once per frame
	void Update () {
		//check that player exists and then proceed. otherwise we get an error when player dies
		if (player) {
			//if player has passed the x position of -1 then start moving camera forward with a randomish Y position
			if (player.transform.position.x > -1) {

				
				float randy = 0f;
				randy = Random.Range (0f, 100f);
				if (randy < 20) {
					ydir = ydir + .005f;
				} else if (randy > 20 && randy < 40) {
					ydir = ydir - .005f;
				} else if (randy > 80) {
					ydir = 0f;
				}
				transform.position = new Vector3 (transform.position.x + 0.03f, transform.position.y + ydir, -10);
			}
		}
	}
}

Now you just need to apply the script to your Main Camera in hierarchy, and then drag the Player object onto the script parameter.

Try the game again, you have just made an infinite runner!!! Well, almost. We still need a few things, but it is getting close now.

My hand is just a little bit higher than I want it, but I will just nudge it down a little in the scene editor.

Step 13: Add a Score

Picture of Add a Score
Add a new GUIText object from the GameObject menu and name it Score.

Change the Text value to Score and the color to black in the Inspector.
Open the Game window, if it is not available, you can find it under the Window pull down at the top.

Adjust the Transform position, it works weird for GUI objects for some reason, think of it as percent of the viewable screen, where 0.5 is 50% and 0,0 is bottom left corner.
X=0.3 and y=0.97 puts it right up near the top in the left corner.

Now we need to add a bit more code to our Camera script. Update the script with theses changes.
using UnityEngine;
using System.Collections;

public class pancam : MonoBehaviour {

	float ydir = 0f;
	public GameObject player;
	//for our GUIText object and our score
	public GUIElement gui;
	float playerScore = 0;

	//this function updates our guitext object
	void OnGUI(){
		gui.guiText.text = "Score: " + ((int)(playerScore * 10)).ToString ();
	}
	//this is generic function we can call to increase the score by an amount
	public void increaseScore(int amount){
		playerScore += amount;
	}

	// Update is called once per frame
	void Update () {
		//check that player exists and then proceed. otherwise we get an error when player dies
		if (player) {

			//if player has passed the x position of -1 then start moving camera forward with a randomish Y position
			if (player.transform.position.x > -1) {

				//update our score every tick of the clock
				playerScore += Time.deltaTime;
				
				float randy = 0f;
				randy = Random.Range (0f, 100f);
				if (randy < 20) {
					ydir = ydir + .005f;
				} else if (randy > 20 && randy < 40) {
					ydir = ydir - .005f;
				} else if (randy > 80) {
					ydir = 0f;
				}
				transform.position = new Vector3 (transform.position.x + 0.03f, transform.position.y + ydir, -10);
			}
		}
	}
}


Save the pancam script and return to unity.

Select the Main Camera again, and you will see that a new parameter is available in the Script component in the Inspector. Drag the Score GuiText object onto the Gui parameter.

Try playing again, you should now have a score going up.

Step 14: Bombs Away

Picture of Bombs Away
There is no real danger yet for our hero. We'll fix that. Lets make some cartoon bombs drop from the sky and break the line.

Create a new empty game object, and name it Bomb. In the sprite folder, find the bomb sprite, open it and add the first frame to Bomb. Adjust the transform scale to X=0.5, Y=0.5.

Add a circle collider 2D and change it's scale and position to look good. We want the bombs to fall, so we will also need a rigidbody 2D, add that component as well.

We'll also need an Animator to control our bomb states, so add that as well. Uncheck Apply Root Motion and check the Animate Physics box in the Inspector.

Open the animation window, make sure that you still have Bomb_0 of bomb still selected. Add an animation and call it bombidle, this will create a new default state in our Animator. Use the first 3 frames of the sprite sheet (drag and drop) and then reduce the frame rate by dropping Sample down to around 20.

Create another new clip, call this one bombexplode and use the remaining frames of the bomb sprite sheet. Again, reduce the framerate to about 20.

Down in the Animator window, creat a transition from bombidle to bombexplode, leave the condition for exit time and change the value to 5.00. This means our bomb will stay idle(fuse lit) for 5 seconds before switching states to explode.

Create a third animation in the Animation window, call it bombdead and leave it blank. In the Animator, create a transition from bombexplode to bombdead.

Create a new script called bomb in your script folder. 

using UnityEngine;
using System.Collections;

public class bomb : MonoBehaviour {
	//a holder for our Animator
	Animator anim;
	//a public float for the explosion radius
	public float explodeRadius = 1f;
	
	// Use this for initialization
	void Start () {
		anim = GetComponent <Animator>();
	}
	
	// Update is called once per frame
	void Update () {
		//if we are done exploding
		if (anim.GetCurrentAnimatorStateInfo (0).IsName ("bombdead")) {
			//destroy all the objects in a radius unless they are tagged Player or hand
			Collider2D[] colliders = Physics2D.OverlapCircleAll (transform.position,explodeRadius);
			foreach(Collider2D col in colliders){
				if (col.tag != "Player" && col.tag != "hand"){
					Destroy(col.collider2D.gameObject);
					
				}
			}
			Destroy(this.gameObject);
			
		}
	}
}

Finally, drag the bomb script into your bomb_0 object. 

One small thing that I almost forgot, is to tag hand as hand. to do this, select your hand object in the hierarchy window, and then under tag, select add tag. Create a new tag at element0 named hand, then with your hand object selected, change the tag to hand.  Also change the penciltip object tag to hand.

Try running the game, the bomb should drop, explode and take out the navbar. (depending of course where you have positioned it)

Step 15: Bomb Spawning

Picture of Bomb Spawning
Kind of hard to play the game now, what we will do is make a spawn object to spawn the bombs, very much like the penciltip spawns the pencilline.

The first thing we need is a Prefab of our bomb. Navigate to the prefab folder and create a new prefab, name it bomb. Drag the Bomb object into the bomb prefab. Delete the original Bomb Object in the hierarchy once you have it as a Prefab.

Create a new quad object name it BombSpawn. Position it above the camera verify in Main Camera view or in the Game window.

Create a new script in your script folder called BombSpawner, and give it the following code.

using UnityEngine;
using System.Collections;

public class BombSpawner : MonoBehaviour {
	// a public object array for which objects to spawn
	public GameObject[] obj;
	//min and max times for another spawn
	public float spawnMin = 3f;
	public float spawnMax = 2f;
	
	void Start () {
		//start spawn 
		Spawn ();
	}
	
	void Spawn(){
		//get random number
		float rand = Random.Range (0, 1000);
		//if random number is greater than 700 make a bomb
		if (rand > 700) {
			Instantiate (obj [Random.Range (0, obj.GetLength (0))], transform.position, Quaternion.identity);
		}
		//invoke spawn at random time interval between min and max
		Invoke ("Spawn", Random.Range (spawnMin, spawnMax));
	}
	
}

First make the BombSpawn object a child of the Main Camera by dragging it into the camera via the hierarchy window.
Now drag the script onto the BombSpawn object in the Hierarchy window. Now with BombSpawn opened in the Inspector, drag the Bomb prefab to the little triangle labelled Obj in the script component.

We have to add an if statement back in our Bomb script (from last step) to delay the bombs falling until after the player has started to walk on the line. A quick check in my scene shows the hand sitting at 7.something so I will delay the drops until the bombs are past 12.
Here is the modified Bomb script.

public class bomb : MonoBehaviour {
	//a holder for our Animator
	Animator anim;
	//a public float for the explosion radius
	public float explodeRadius = 1f;
	
	// Use this for initialization
	void Start () {
		anim = GetComponent <Animator> ();
	}
	
	// Update is called once per frame
	void Update () {
		//if this bomb is spawned after the spawner reaches a position past x = 12
		if (transform.position.x > 12) {
			this.gameObject.SetActive (true);
		}
		//otherwise bomb no worky
		else{
			this.gameObject.SetActive (false);
		}
		//if we are done exploding
		if (anim.GetCurrentAnimatorStateInfo (0).IsName ("bombdead")) {
			//destroy all the objects in a radius unless they are tagged Player or hand
			Collider2D[] colliders = Physics2D.OverlapCircleAll (transform.position,explodeRadius);
			foreach(Collider2D col in colliders){
				if (col.tag != "Player" && col.tag != "hand"){
					Destroy(col.collider2D.gameObject);
					
				}
			}
			Destroy(this.gameObject);
			
		}
	}
}

Now Robot can jump on the line and walk a little bit before the bombs start falling...try it out. Still not very challenging. Let's duplicate the BombSpawn object!! Then just move it over a little bit and we have two bomb spawners, let's play.

Step 16: Platforms(or Doodles)

Picture of Platforms(or Doodles)

To generate the doodle platforms, we start by creating a few prefabs. Create a new folder in the Prefab folder and call it Doodles.

Create 10 new prefabs named doodle1 though to doodle10.

Create a new empty game object, no need to name it.

Open the sprites folder and find the doodles sheet, open it and select the first doodle. Drag it into the empty game object in the hierarchy window.

Add a box collider 2D to it in the inspector, then play with the scale and center to get it sitting nicely on the doodle. Remember, this is what Robot will be landing on.

Open your Prefabs/Doodles folder with the empty prefabs in it, and then drag the new GameObject  into the doodle1 prefab.

Now, rather than repeating this entire process, just navigate back to the sprite folder, grab the next doodle, and drag it into the Sprite Renderer component of the Game Object, adjust the positioning of the collider and put it into the next doodle prefab.

Repeat this for the remaining doodle prefabs. Once they are all recorded as prefabs, you can delete the GameObject we made to create them.

Now Duplicate a BombSpawn object under our Main camera, and move it off screen to the right. Give it a new name in the Inspector, something like DoodleSpawn.

Then drag each of the new prefabs into the Obj parameter of our script component. Drag the first into element 0 to replace the bomb, and the others to the little triangle beside Obj to add them to the list.

Play with the min/max parameter in the script component to change how often they are generated. Duplicate the DoodleSpawn object and move it up if you want another set of levels.

One thing I noticed while playing is that Robots max speed was too low, I increased it over here. Go to your Player object and adjust the maxSpeed variable in the Script component if you find the same issue.

Step 17: Bonus Point Pickups

Picture of Bonus Point Pickups
Making the Pickups is very similar to making the doodles. A few small differences. Start by creating a new folder in the Prefabs folder called Bonus, and populate it with 6 blank prefabs.

We will need a script to handle adding the bonus points to the GUIText object, so in the scripts folder, create a new script called BonusPoints. Here is the script to enter in Monodevelop.


using UnityEngine;
using System.Collections;

public class BonusPoints : MonoBehaviour {
	//make a container for the heads up display
	pancam hud;

	void OnTriggerEnter2D (Collider2D col) {
		if (col.tag == "Player") {
			hud = GameObject.Find ("Main Camera").GetComponent<pancam>();
			hud.increaseScore(10);
			Destroy (this.gameObject);
		}
		
	}
}

Now return to the scene and create a new empty GameObject. Find powerups in the sprites folder, and drag the first sprite into the new GameObject.

Transform the scale to x=2,y=2 over in the inspector, then add a box collider 2D. This time we want to check the box marked Is Trigger.

Now drag the BonusPoints script into powerups_0.  Open the prefabs/bonus folder and drag the GameObject into the prefab.

As in the previous step, just replace the Sprite Renderer Sprite for each prefab and save them.

Once the six Bonus Prefabs are made, we can delete the GameObject that we used to construct them.

To spawn our bonuses, we will just duplicate the DoodleSpawn object, rename it BonusSpawn, move it up a little bit and replace the object that it spawns.

Step 18: Game Over

Picture of Game Over
The home stretch!! All we need now is for the player to die rather than a break in the code. That, and we'll need a second scene, to display that the game has ended and offer the chance to play again.

Lets add this scene to the build before we start the new scene. In the File pulldown menu, select Build Settings.
In the dialog box that opens up, click the Add Current button, and verify that the scene has a scene # of zero. Close the dialog box.

Make sure you save your current scene and then select New Scene. Name the scene GameOver and put it in the Assets folder.

Add a GUIText object from the GameObject pulldown menu. In the inspector, change Anchor to upper center and alignment to center. Also change the font size to 20 and the color to black.

Back in the scene, drag the sticky note called notes_score to the scene and position it roughly center, use the Game window to see how it will look. Do the same with the Game Over sprite, just drop it where it looks good.

Create a gameOver script in the script folder, like this one.

using UnityEngine;
using System.Collections;

public class GameOver : MonoBehaviour {
	int score = 0;
	public GUIElement gui;
	
	// Use this for initialization
	void Start () {
		//get our score from playerprefs
		score = PlayerPrefs.GetInt ("Score");
		//multiply by 10 as we did on displayed score
		score = score * 10;
	}
	
	void OnGUI(){
		//set our text to our score
		gui.guiText.text = score.ToString ();
		//if retry button is pressed load scene 0 the game
		if(GUI.Button(new Rect(Screen.width/2-50,Screen.height/2 +150,100,40),"Retry?")){
			Application.LoadLevel(0);
		}
               //and quit button
               if(GUI.Button(new Rect(Screen.width/2-50,Screen.height/2 +200,100,40),"Quit")){
                  Application.Quit();
               }
	}

}

Save it and drag it onto the Main Camera in our new scene.

Almost all finished, we need to add a function to our camera script to pass the score forward, and we need to alter our destroyer script where we have the code break to send us to the GameOver scene.

The new Camera script.

using UnityEngine;
using System.Collections;

public class pancam : MonoBehaviour {

	float ydir = 0f;
	public GameObject player;
	//for our GUIText object and our score
	public GUIElement gui;
	float playerScore = 0;

	//this function updates our guitext object
	void OnGUI(){
		gui.guiText.text = "Score: " + ((int)(playerScore * 10)).ToString ();
	}
	//this is generic function we can call to increase the score by an amount
	public void increaseScore(int amount){
		playerScore += amount;
	}
	//Camera will be disabled when we load a level, set the score in playerprefs
	void OnDisable(){
		PlayerPrefs.SetInt ("Score",(int)(playerScore));
	}

	// Update is called once per frame
	void Update () {
		//check that player exists and then proceed. otherwise we get an error when player dies
		if (player) {

			//if player has passed the x position of -1 then start moving camera forward with a randomish Y position
			if (player.transform.position.x > -1) {

				//update our score every tick of the clock
				playerScore += Time.deltaTime;
				
				float randy = 0f;
				randy = Random.Range (0f, 100f);
				if (randy < 20) {
					ydir = ydir + .005f;
				} else if (randy > 20 && randy < 40) {
					ydir = ydir - .005f;
				} else if (randy > 80) {
					ydir = 0f;
				}
				transform.position = new Vector3 (transform.position.x + 0.03f, transform.position.y + ydir, -10);
			}
		}
	}
}


The fixed Destroyer script

using UnityEngine;
using System.Collections;

public class Destroyer : MonoBehaviour {

	
	void OnTriggerEnter2D(Collider2D other){
		//if the object that triggered the event is tagged player
		if (other.tag == "Player") {
			Application.LoadLevel(1);
				}

		if (other.gameObject.transform.parent) {
				Destroy (other.gameObject.transform.parent.gameObject);

		} else {
				Destroy (other.gameObject);		
			}
	}

}


Guess what? You just made a game! I did too!! woot for us!
Ok, so it is not the best game in the world, but that is hardly the point is it. At least it wasn't for me. I was shocked at how simple it has all become, and I had to share. Go get making, I can't wait to play some new cool games!

Step 19: Files, Etc

i included this last step to make the scripts we just wrote together a little easier to access. 
So here are the scripts we just went through.

Thanks so much for stopping by, I hope you enjoyed it as much as I did.
Share and enjoy.

Oh and......vote fjordcarver?

Comments

jonathany66 made it! (author)2017-07-21

Hi! I was able to use this guide to recreate your game, and I also made a new version of it, complete with new obstacles and a second player!

Check it out here: https://www.dropbox.com/s/uui79jknpkd7sze/Game1.4.zip?dl=0

JamesD413 (author)2017-02-10

I have looked through all the comments and tried to fix the Rigidbody.Velocity.y error but it will not correct and I've had someone who knows how to code say that they can't figure this out without modifying the base coat given to us through this instructable can anyone help

JamesD413 (author)2017-02-08

I fixed the rigidbody2d error but i still have the velocity error. Any help?

Mr Danger (author)2017-01-14

On step six, there is an error that says this: UnityEngine.Component' does not contain a definition for `velocity' and no extension method `velocity' of type `UnityEngine.Component' could be found. Are you missing an assembly reference?

The error is on line 23

rigidbody2D.velocity = new Vector3 (move * maxSpeed, rigidbody2D.velocity.y);

JamesD413 (author)Mr Danger2017-02-08

Did you ever fix the velocity definition issue

Mr Danger (author)Mr Danger2017-01-15

I found that the problems were leaving out the definition of rigidbody2D and calling it rigidbody2D. Calling it rigid2D works.

JamesD413 (author)2017-02-08

Nevermind

JamesD413 (author)2017-02-08

I just downloaded the file and there is no sprites folder in the zip. Any help?

StefanoT16 (author)2016-09-04

Hi, why "-13" and "10" in speed parameter? i dont understand calc.

thanks!!

Raunak Singh (author)2016-01-15

i am having a problem in adding this script.

JereH2 (author)2015-06-09

I've been having a problem with adding an rotation animation clip to play when character flips around in x axis. I have a 3 frame fast animation that should play always when character flips. I've been wondering this and, hope that someone knows how to implement this in to this great tutorial.

Assasin512 (author)2015-05-24

I have 1 problem the cam moves but neither the hand moves nor a line shows up. I just jump and i fall down. Can anyone help me out ?

mada93 (author)2015-04-22

hey there,

great tutorial, however steps #13 and 18 were a bit difficult if one is using unity 5, could you please explain how to get the GUI text in unity 5

Assasin512 (author)mada932015-05-24

Hi mada93,

If you want to get GUI Text then create an empty GameObject. Then click on 'Add Component', 'Rendering' and GUI Text.

You're Welcome !!!

CarstenAndersen.dk (author)2014-10-29

This is a really awesome, just one question. I have been going throught you guide now 3 times and I cant seem to fix the jump part. If I tab the spacebar multiple times it keeps jump so i end up going out of the screen.

what could be the problem, or can you point out where you set that part in your toturial

Did you fix it? If you did how as i am running into the same problem.Thanks,

ZainRafiq101 (author)2015-05-16

On step 7 when you make the groundcheck and make the robot jump, my one just keeps on jumping.Any help?

ZainRafiq101 (author)2015-04-16

All was well untill step 14, I pressed play and it would animate but woudnt destroy the blocks (I'm using my own sprites) and would be stuck on idle. Any help?

kmaingault (author)2015-01-02

You forgot the step to explain how create Player Layer ;)

eshansingh1. (author)2014-12-16

Great game and great introduction to the infinite world of Unity!

eshansingh1. (author)2014-12-16

Great game and great introduction to the infinite world of Unity!

Thomasm12 (author)2014-12-02

the animation changes even when the robot isn't moving

fjordcarver (author)Thomasm122014-12-06

Did you add the variable speed to the animator?
Did you change the animation state when speed is greater than 1 to go to drive state, and less than 1 go to idle state.
I am suspect that either you forgot to add the variable to the animator, or perhaps a typo...i.e. "speed" vs "Speed".
Double check that your variables match is all I can suggest from here. I cannot see where you might have missed something, but you are correct in assuming that the animation state should be changing from idle to speed and back.

erotavlas (author)Thomasm122014-12-06

same here, it looks the same stationary as it does when I move it. I thought the moving state was supposed to look different.

erotavlas (author)2014-12-06

I think you are missing some steps in this instruction. For one you show a new JumpFall item in the Animator window. But where did that come from?

NabeelS (author)2014-10-16

Thants great to get more unity3d related stuff checkout this blog > http://unity3diy.blogspot.com/

recently i made and uploaded two games one is golf

Tecwyn Twmffat made it! (author)2014-10-13

This is a truly awesome instructable! I've used this as inspiration to create an animated robot with synfig studio software. The model is uploadable here:

https://www.instructables.com/id/2D-Cartoon-Animation-of-the-Instructable-Robot/

HaiN (author)2014-09-18

I new learn Unity, i very like your tutorial, it's clear. Please you can up tutorial again help me, or please you send tutorial to email: wind1827@gmail.com. I really want to learn it.

HaiN (author)HaiN2014-10-01

Yes, i completed example, thank fjordcarver very much :)

Nanite (author)2014-09-19

OK, great try, but I am extremely lost and I can't imagine how anyone else here can follow this. Everything is fine up until you start step 7, then you casually mention putting the groundcheck gameobject on the player layer, when you have never mentioned anything about layers before. There is no player layer. We haven't created it yet. You don't mention how to do that at all. So after writing out that huge controller script, I'm stuck because I don't know how to create layers, you never mentioned how to, and the What Is Ground variable is useless without the player layer being created.

Mr-Technology (author)2014-07-25

hey, nice tutorial..

I am having a problem:

My character keeps falling

hany_r (author)2014-07-08

hi

please help me!

i create a 2d game with unity , but i don't know how to movement camera.

please help me to show a way or solution ..

ecsaul23 (author)2014-03-22

Congrats on being a finalist! Hope you win!

geoholyhart (author)2014-02-18

Yay I finished. I only have two problems in the end. The player can jump multiple times in the air and the blend tree is being triggered (tested it), but the animation isn't playing during the jump.

Either way, I voted for you and it was a great learning experience!

Now to apply what I learned to a game of my own! :D

fjordcarver (author)geoholyhart2014-02-18

I can't wait to see what you make!! and thanks

geoholyhart (author)2014-02-17

Heads up, the class name for the Spawn script should be the same as the Quad Game Object. You made one BombSpawn and the other BombSpawner.

fjordcarver (author)geoholyhart2014-02-17

You could name your script "ThisIsMyScript" and it would work fine. BombSpawn is the quad name and could have arbitrarily been left named quad and still function fine. The class name does have to match the script name however. This should be fine if you are typing and creating your own scripts. I suspect you copied and pasted my code into a C# file that you created with a different name than mine had, which would result in an error similar to what you are describing.

geoholyhart (author)2014-02-15

Got stuck here. The player is stuck in the JumpFall state once I create the transition it to Any State and Idle. Any ideas where I may have went wrong? Checked my code, then copy/pasted yours to see if I made mistake and it was no different. I remember one of the steps before you asked us to change "groundCheck" to Tag:Player and Layer: Player, but Player wasn't an option and I created it (could this have caused a problem, if it wasn't an option already?).

fjordcarver (author)geoholyhart2014-02-15

It looks (at a glance) as though your groundCheck is nowhere near your player. Check your goundcheck object, it's transform position should be zero in the x , and -0.5(ish, there is a screenshot) in the y. so that it sits right under the players feet.

geoholyhart (author)fjordcarver2014-02-15

I think this was the problem. Moved the transform and it doesn't bad loop any longer, but in the preview when I jump my character doesn't come back down. Is that normal at this point?

fjordcarver (author)geoholyhart2014-02-15

No, you should jump and fall back to the line. Check the rigidbody2D component on your Player object, make sure gravity is set etc. Also check the Animator and make sure that you have unchecked root motion, and checked apply physics (i am guessing this is probably the problem)

geoholyhart (author)fjordcarver2014-02-15

Yea, I had to uncheck "Apply Root Motion" inside the Player>Animator component and it works beautifully now. Thanks a ton!

geoholyhart (author)geoholyhart2014-02-15

Narrowed it down to specifically setting
the transition from Any State to JumpFall. It traps the Player in the
JumpFall state, but before setting that transition the player can't
jump.

I'm also curious, if you can explain what in the code
sets/creates the correlation between it and the JumpFall state. I don't
see the exact connection. I do know a very little bit of c++ and c#.

Thanks. The tutorial has been easy to follow so far!

fjordcarver (author)geoholyhart2014-02-15

There is nothing in the code per say that affects the JumpFall state, in the code we only deal with the Ground boolean value. Unity takes care of the actual transition if that state changes via the transition we specified. So we set the values in the code, and the transition happens according to how we created it. I.e. you could just as easily set the transition to be based on Speed.(it would not make logical sense to a player or game mechanics though). Does that sort of help to clarify? (I also know only a little c#, just cutting my teeth)

geoholyhart (author)fjordcarver2014-02-15

Yea, that helps. Seems a bit like uScript in that sense.

fjordcarver (author)geoholyhart2014-02-15

one other possibility, did you set what is ground? and make sure player is not a part of it. Also check that the grouncheck itself is also tagged player.

geoholyhart (author)fjordcarver2014-02-15

Yea, I did this no problem. Just double checked to make sure and it's set correctly.

ryaneaton88 made it! (author)2014-02-14

Using your awesome instructable. I made my own frustrating, and addicting flappy game to fill the void. You are right, Unity certainly is fun!

jcoertzen (author)2014-02-13

I dont have that speed option when doing the transition condition

fjordcarver (author)jcoertzen2014-02-13

You need to "add a float called Speed" , check the images and reread the instruction just before making the transition.

About This Instructable

185,736views

710favorites

License:

Bio: Dad, maker, dreamer, hacker, painter.
More by fjordcarver:Make A 2D Video Game with UnityAcoustic/Electric Cookie Tin UnitarMake a Keepsake Book of your Child's Artwork
Add instructable to: