Step 1: 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 2: 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 3: 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 4: 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 5: 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 6: 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 7: 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 8: 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 9: 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 10: 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 11: 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 12: 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 13: 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 14: 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 15: 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 16: 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 17: 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 18: 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 19: 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 20: 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?
License: Attribution-NonCommercial-ShareAlike.