Affiliate links on Android Authority may earn us a commission. Learn more.
How to make a simple 2D platformer for Android in Unity - Part three
In the previous two posts in this series (part 1 and part 2), we’ve seen how to create a basic 2D platformer using Unity. So far we have a character who responds to keyboard input and touch controls, has basic physics and explodes in a gory mess when he comes into contact with enemies, spikes or the bottom of the screen.
In this final installment, we’ll be adding some collectibles, music, animation and levels to finish off this basic-but-fun little platform game.
Some polish and organization
I actually added music before uploading the APK in the last post – if you downloaded it then you will have been greeted by some awesome chiptune sounds by Mentalcacao. To implement this, all I had to do was add an MP3 to my project (in a folder called ‘Audio’ within Assets) and then add it as a component of the player character. I also set ‘Play On Awake’ and ‘Loop’ to true.
I also decided to make some changes to Rushdy’s speed, angular drag and gravity scale:
Gravity Scale: 2
Angular Drag: 13
Jumpheight: 12
Movespeed: 4
This makes Rushdy a bit more responsive and fun to control. Lastly, I’ve increased the size of the touch screen controls as they were a little frustrating to use before. Oh and we also want to prevent our game from being played in portrait orientation (forgot that last time!). This setting is found under ‘File > Build Settings > Player Settings > Resolution and Presentation’. Then just tick the orientations you want to support:
You don’t have to follow my advice here though – mess around and get everything just how you like it!
Now before we go any further, it’s worth tidying up our Hierarchy a little. If you’ve had fun dotting platforms and enemies around the level, then you’ll probably have a long list of ‘ground’ and ‘baddy’ objects and it’s likely getting a little tricky to find specific elements. This is why it’s worth creating some empty game objects and using these as folders. Make yourself folders for ‘Platforms’, ‘Hazards’ and anything else that is clogging up this view, then simply drag and drop those items to make them children and collapse the folders to keep things tidy.
Adding collectibles
Nearly every platformer needs to have some kind of collectible. With that in mind, we’ll be needing a new sprite:
We also need to create a new variable for our character in the ‘Controls’ script, which in this case we can call crystals. That will be an integer, seeing as you can’t collect .3 of a crystal. Make sure it’s a public variable so that other scripts can edit it.
If you remember how all this works, then you’ve probably already guessed that you need to add a polygon collider to your crystal and set it as a trigger. We’re also going to set the order in layer to make sure these are always at the front. Make these changes in the prefab so that you can edit them easily later. Now create an empty game object called ‘collectibles’ to act as a folder for your crystals and drag a sound effect you want to play when you collect these onto it (this time don’t select play on awake). We’ll use this in a moment.
Now to create another script, which thankfully is pretty straightforward. This will work just like the hazard code, except when the player enters the trigger it will cause the object to destroy itself, while also playing a sound effect and increasing the player.crystals variable by 1:
public class Crystals : MonoBehaviour {
private Controls player;
public AudioSource bling;
void Start () {
player = FindObjectOfType<Controls>();
}
void Update () {
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Destroy(gameObject);
bling.Play();
player.crystals++;
}
}
}
For this to work, you’ll also need to drag the collectibles container you just created into the empty box that says ‘audio source’ for the crystals in the Inspector (unfortunately you can’t just use the audio file). You’ll need to do this to the objects in the scene though, not the prefab. You can now copy and paste your crystals around the level and when you collect them, the sound should play and they should disappear. Satisfying…
We’re not quite done though, because we need a way to indicate to the player how many crystals they’ve collected. To do this, we need to create another UI element which will once again be a child of the canvas (just like the arrow buttons we made in part one). So select the canvas in the Hierarchy, then go to ‘GameObject > UI > Text’ in the top menu. This will create a new text element, which you want to anchor to the top left of the screen the same way you anchored your control buttons to the bottom. In the Inspector, enter the text ‘Crystals: 0’ and make sure that the text is big enough to be easily legible.
Can you guess what’s next? We need another script! Call this one ‘Score’ and use the following code, which you will attach to the Text element you just made:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Score : MonoBehaviour {
Text text;
private Controls player;
// Use this for initialization
void Start()
{
text = GetComponent<Text>();
player = FindObjectOfType<Controls>();
}
void Update () {
text.text = "Crystals: " + player.crystals;
}
}
Notice the using lines at the top this time. The first two are always there by default so I haven’t mentioned them up until now. This time we’re added a new one: using UnityEngine.UI;. This is just like importing classes in Java – it means that we’re using additional code that isn’t always accessible by default. This is what lets us access the Text command. Then all we’re doing is updating the string to equal player.crystals. Collecting these little crystals is oddly satisfying…
Animating the player
Rushdy does a lot of things right now, but moving convincingly is not one of them. In fact, our entire level is pretty static and lifeless, so let’s fix that by giving our hero a few animations.
First, you need to create yet more sprites:
One is Rushdy but a bit more compressed and one is Rushdy blinking. These graphics probably aren’t going to be giving Naughty Dog any sleepless nights, but hey. Now you need to open two more windows by using the menu along the top. These are ‘Animation’ and ‘Animator’. You can drag and drop them wherever you like within in your UI or let them float around the screen. This is where it pays to have a large monitor (unlike yours truly).
Once you’ve done this, click on Rushdy in the Scene view while you can see the Animation window. The latter should include a ‘Create’ button, which will let you easily create a new animation. Click that and then make an animation called ‘Idle’. While you do this, create a new folder in Assets to contain this in and call it ‘Animations’.
Now you’ll see the view change and it will say ‘Idle’ with two little arrows next to it on the top left. Click those two little arrows and you can choose to ‘Create New Clip’. Use this to make another one called ‘Walking’ and use that menu subsequently to switch between the two.
You’ll now notice that you have a kind of timeline visible in your Animation window. Creating animations is as simple as dropping the sprites where you want them in that timeline; so for our idle animation we want Rushdy to spend 90% of his time in the first frame and then occasionally to blink. I dropped the blinking sprite in at just past 1:30 and then switched back to the regular sprite a couple of seconds later. Do something similar for your walking animation but put the squat Rushdy about halfway so that he’ll appear to alternate between a taller and shorter version of himself.
Select the your ‘Animator’ window and you’ll see that it is essentially a kind of flow chart. At the moment it should go from ‘Entry’ to ‘Idle’, which means that ‘Idle’ is now the default animation and should play constantly when you run your game. In this case, ‘Idle’ is a ‘state’ and the other useful state you have in your flow chart is ‘Walking’ (‘Any State’ will only come in useful as your animations get more complex). Right click on ‘Idle’ and select ‘New Transition’. This will create an arrow, which you can then drag so that the chart goes Idle > Walking.
With this transition still selected in the Animator, find the little tab that says ‘Parameter’ and switch to that. You should then see a ‘plus’ button and if you click this, you can select from various types of variables. Make a new bool and call it Walking.
Next we’re going to add some new code to the Control script. First, we create a new Animator reference which we may as well call anim:
private Animator anim;
Then, we need to point to that animator in the Start function.
anim = GetComponent<Animator>();
Now we can create and change variables that will be accessible by the attached animator component. We just need to edit that bool we created called Walking so that it will be true when we’re moving (and grounded) and false when we’re not. The easiest way for us to do this is:
if (rb.velocity.x != 0 && onGround)
{
anim.SetBool("Walking", true);
} else {
anim.SetBool("Walking", false);
}
Just put this inside the Update function. This simply means that if the player is moving to the left or right (i.e. if there is velocity on the x axis) and they are grounded, then the animation will be ‘on’. If the player isn’t touching the ground, or they come to a halt, then they’ll revert to the idle animation.
To make sure this has the desired effect, you’ll need to head back to the Animator and select the transition. Now open the inspector and where it says ‘Conditions’ select ‘Walking’ and ‘true’. This now means that the animation will kick into effect if the Walking bool is true. You should also untick the box that says ‘Has Exit Time’. This means that the animator won’t wait for the animation to finish before it switches.
Got that? Great… now do it all again for a new transition that will take you from Walking back to Idle (this time the Walking condition needs to be false). I also sped up my walking animation by selecting it in the Animator and using the Inspector to set ‘Speed’ to 2.
Of course you can make as many of these animations and conditions as you like and set various different variables. You can create an animation to have your character pushing against a wall for example by making Pushing equal true when the player presses right but there is no velocity in the RigidBody2D. You can also create animations for different orientations, or ‘flip’ the sprite so you don’t need to create everything twice. You’ll also likely want to get familiar with using sprite sheets, which can save you a fair bit of time by letting you arrange all your elements in one file. I’ll let Unity explain that one though. You should likewise do the same for your enemies, your in-game objects and everything else. Take a look at any good platformer and you’ll find there’s constant motion all around – collectibles appear to ‘dance’ and flowers spin around. This obviously doesn’t change the gameplay at all but it can give your characters, your game and your world a lot more character.
Objectives and levels
I’m going to be honest and say that I’m quite enjoying playing Rushdy at this point, but there’s still not really much to do. To make a game fun, there almost always needs to be some sort of objective. Minecraft is the exception, not the rule…
With that in mind, I’ve changed the text on the score counter to read “Crystals: 0 / 41” and I’ve scattered 41 crystals around the level. To get them all, you need to do some precision jumping, solve some puzzles and explore a little. Herein lies the challenge and hopefully the fun.
So once our player has collected all 41 crystals, we want something to happen. Usually, that means loading the next level! First we need to create our new level then. Make sure to save and then go ‘File > New Scene’. Everything you’ve made will disappear (!) but don’t worry, you can still load your last level any time by going to ‘Assets > level1’ (or whatever you called your first scene). Note that you lose everything and not just the level – if you want to change the way your character behaves you can do. You could even make level 2 a first person shooter if you wanted! But we probably don’t want to do that… Instead, just head into your assets folder and start dropping elements from your last level into this new one. This is another good reason to create prefabs with all the scripts and properties attached (note that you can also do this by saving your level ‘as’ a new level, or copying and pasting your scenes).
Then you can just go about creating a new level! Seeing as this is only a little demo, I’ve just created a screen to congratulate the player:
And congratulations to you as well for making it this far!
Now all we need to do is transition from one scene to another when we collect all 41 crystals. To do that we just need a one last bit of code. Normally we’d put this in some kind of dedicated ‘level manager’ script but for our purposes, it will work just fine in the control script.
if (crystals == 41)
{
Application.LoadLevel("level2");
}
Note: technically Application.LoadLevel is depreciated with the latest versions of Unity, but there seems to be issues with the new method and this works just find for now.
This code could just as easily be implemented with a doorway using an onTriggerEnter. Remember as well that you need to include this new scene in your build settings before you compile. Now build your APK and keep your fingers crossed. You should have a working little game!
Conclusions and closing notes
This is a pretty simple project but hopefully it has given you enough of a foundation to start making you own games. You can easily add some more intrigue to a platformer like this by giving your character some kind of gimmick. Or you could make this an infinite runner by making the player automatically run right. My advice is to build something really simple for your first project though just to get some experience. If you struggled to follow these instructions then feel free to grab this project from Github and simply bend it to your own needs. Change the character, drag the elements around and distribute it as you like!
Check out this previous article for tips on level design in mobile games. You can also download the APK directly from here. Let me know if you find all the crystals and be sure to share your own projects!