Let’s make a Flappy Bird game with Unity and LootLocker. We’ll call it… FlappyLoot.
Creating a simple physics game is great practice. And they don’t come any simpler than Flappy Bird. So we can run through creating, polishing and adding features to the game, without spending hours and hours on the core gameplay loop.
Also, the original Flappy Bird was missing one thing that we think would’ve made it much more fun: leaderboards. So we’ll run through the process of adding leaderboards to pretty much any game.
If you’re new to LootLocker, this will be good practice for creating leaderboards. And if you’re just checking out LootLocker to decide if it’s right for you, this will show you just how quick and simple it is to use.
To follow this guide, you’ll need to know the basics of programming in Unity and C#. We’re using Unity 2021.2.7f1, but you should be fine using any similar version.
If you need any help with using Unity, go to: https://learn.unity.com/.
Flappy Bird is an extremely simple game that went viral in 2013. I works like this:
We’ll put all these features into our game, but with an online leaderboard too.
Let’s get started.
We now have an empty Unity Project. Let’s tinker with the settings so it looks a bit nicer.
We’ll start by changing the background color to something a bit more fitting.
There’s nothing to say your character has to be a bird. You could have a bee, a dragonfly or even a person with a jetpack.
We’re going to use a bird though – namely Hector, the bird in our LootLocker logo. We think he’ll enjoy the exercise.
Feel free to use our images for your project, or create your own if you prefer:
Quick test: Your game view should now show only your background color, with Hector chilling motionless in the foreground:
Let’s give Hector some movement.
Quick test: Press play and Hector should fall down.
First we’ll give Hector the ability to flap by himself on the start screen. Then we’ll put that function into practice in the game itself.
In Update() check if the bird's position is below the y-position 0 (the middle of the screen). If so, set the bird’s velocity to the jumpAmount.
In case you were wondering: Setting the velocity directly, rather than using AddForce, gives us more control and a more arcade-like feeling. Using AddForce would just add the force to the bird. This would mean that if Hector’s falling very fast, the jumpAmount won’t be the same.
Quick test: Press play and you should see hector bouncing. He should bounce higher when you hit spacebar:
Hector needs some pipes to navigate through. We need the pipes to behave like this:
Let’s create the pipe object first.
In case you were wondering: This code creates a pipe object, containing two pipe prefabs. It’ll then move all those pipes along the x-axis. When they reach the end of the screen, the pipes reset their positions and get a new random Y value.
Now, we’ll configure the settings in Unity to make the pipes work how we want them to.
Quick test: Hit play and you should now have something that’s starting to look a lot like Flappy Bird.
At the moment, the game’s playing by itself. (Well, it’s not really a game yet, but let’s call it one for simplicity's sake). We need the game to behave differently in different states:
So we need to create a GameController class that’ll handle this for us.
Quick test: Press play and you should now get a countdown. When the countdown says ‘GO!’, the pipes will start spawning and you’ll have control of your bird.
‘Game flow’ is how we describe the whole ‘outer loop’ of a game. It’s the level above the gameplay loop itself.
In what order do we present things to the player? Writing these down in steps usually makes it easier to see what features we’re still missing.
We want our game to flow like this:
With these steps, we can easily see what we need to add:
So let’s get started on that now.
Quick test: Press play in Unity and you should have a complete game flow – you can hit the pipes, die and restart.
We now have a playable game. But we have nothing to quantify how well we’re playing it. For that we need a scoring system. So we’ll:
Quick test: When you play the game, you should now see your score at the top of the screen.
It’s nice sometimes to take a break from adding new features – and spend some time on the little visual flourishes.
So let’s quickly do two things to make our bird feel more alive:
This is pretty simple: we just read the Y velocity and angle our bird based on that value.
Physics uses FixedUpdate() instead of Update(). By using FixedUpdate() we know the physics engine will be done when we set the rotation there.
Quick test: Press play and see how much more alive your bird looks with this one little tweak.
You might’ve expected this to be task one of the guide. But no, Hector’s been literally unflappable thus far.
Luckily, this is quick and easy to fix with a coroutine.
In case you were wondering: On our curve, we go down quite a bit before we go up to 1. We think this looks more realistic. Think about how an actual bird flaps its wings. They don't just move their wings down – they lift they, and then swiping them down. So we try to mimic that by overshooting the curve.
Here’s the difference between an unclamped(overshooting) and clamped curve.
We think the unclamped version looks a lot better.
Quick test: Play your game and make sure the wings are flapping just how you want them to.
Our players can see their scores now, but they can’t really compare them. To do that, two players would need to screenshot their scores, or print them out on paper and send them by pigeons. Not optimal.
So let’s add online leaderboards.
This is quick and simple to do with LootLocker. We’ll start by implementing the LootLocker SDK.
We’ll start off by creating a LootLocker account and setting a few things up. This is all totally free, and you don’t have to submit any personal data.
(If you’ve already got a LootLocker account, you can skip this part.)
Now it’s time to install LootLocker into our Unity project.
We’re going to install the LootLocker SDK into Unity.
To do this, we need to install Git first. This will allow us to add the SDK into our project quickly and easily. (If you already have Git installed, you can skip this part.)
Now with Git installed, we can add LootLocker to our FlappyLoot project.
Quick note: You might need to restart Unity before it recognizes you’ve installed Git.
Unity will now have a quick think and then start downloading the LootLocker SDK.
And that’s it. We now have the SDK installed. Simple, huh?
Now we’ve installed the SDK, we’ll turn on the feature we’ll use for this part of the guide.
Now we have our LootLocker settings just how we want them.
We need to tell the LootLocker SDK in Unity what game it should be referencing.
First we copy the identifier for our game – our API key.
Now Unity and LootLocker can communicate.
Now we have the SDK setup, we can add the actual leaderboards.
We’ll store our players’ identities and let them upload their score so they can compare them with their friends.
Here's what we’ll do:
There are different types of leaderboards that fit different types of games. For our Flappy Bird game, we want more of an old school, arcade leaderboard – rather than a standard one. So we’ll create a generic leaderboard instead of a Player leaderboard.
We first need to create this leaderboard on the LootLocker dashboard.
You might be thinking: ‘what are we doing with all of these configurations and SDKs?’
Well, we‘ll log in our player and let them upload their score.
The PlayerManager class will handle all of this. It’ll take care of all the information about the player during their login session.
Quick test: Press play. If everything works, you should see text telling you to press spacebar. Otherwise the text should tell you it’ll retry logging in:
If we show the leaderboard now, it won’t have anything on it. So let’s upload some scores to our leaderboard.
Create a new GameObject called Leaderboard:
Add a script called Leaderboard to it:
We want to let the player upload as many scores as they want, without needing to start a new LootLocker session each time. So we’ll add some more characters to the player’s ID and use that new ID when uploading the score.
We’ll also make sure the player can only upload their score once they’ve died. We’ll do this by adding a check that we’ll later reset in GameController.cs.
Insert this code to handle uploading our score to the leaderboard:
Where the code says "Your leaderboard ID", enter the ID for your own leaderboard ID (which you can find on the LootLocker dashboard):
In GameController.cs add a reference to Leaderboard:
In DeathRoutine() we’ll store away the score that’ll upload when the player dies. We’ll also allow the player to upload their score by setting canUploadScore to true:
Set the reference to Leaderboard in GameController: Now we’ll set up the UI that’ll handle uploading our score.
Add a new button to the canvas (UI -> Button) and deactivate the game object:
Scroll down to the button component and add a new OnClick() method to call SubmitScore() from Leaderboard:
Add a reference to the button in GameController.cs:
Then in SwitchGameState() we turn it on when we get to the Dead state, and off when we go back to the menu:
Drag the reference to the Button in GameController:
Quick test: Play the game and click the button when it appears. Then go to your LootLocker dashboard and see if a score has uploaded.
We can upload the players’ scores now, but we want to show it to them as well. We want the main menu screen and death screen to show the scores a bit differently. So we need our game to do these two things:
First we’ll make our leaderboard UI so we have somewhere to show the score.
We have the UI for our leaderboard set up. Now we’ll create a function to fetch the top performing players from our leaderboard. We’ll show this on the menu screen and when the player dies.
Quick test: Press play and you should immediately see the top ten scores from the leaderboard.
We want to show and update the leaderboard in two places: on the menu screen and when the player has died.
So we need to hide it when we start the countdown – because having the leaderboard open while playing the game would be nothing but a nuisance.
Quick test: Play the game. Check to make sure the leaderboard shows and hides when we want it to.
At the moment, our leaderboard only says ‘Player Name’. Obviously that won’t do – our players need to give themselves nicknames when they upload their scores.
We’ll give each new player a default ID like #Guest000000 (where 000000 is their ID). But we’ll make sure they can change it if they want to.
We won’t use the players’ actual IDs when uploading the score – we’re using a generic leaderboard, so we don’t need to change the players’ names either. We can just store that in PlayerPrefs.
Quick test: Play the game in Unity and upload a score. This new score should now show on the leaderboard as a default name, like #Guest000000.
Our players now have unique names, but not particularly distinctive ones. It’s not easy to beam with pride as you see your score atop the leaderboard, tagged as Guest#3928474.
So we need to let players create more expressive nicknames, like SockRock, FlappyNerd or WeLoveHector.
First we need to set up the UI to handle this.
Quick test: Play a quick game and upload your score. You should now be able to change your name and keep that name preserved between playing sessions.
When the player uploads their score, we want to show them where they are on the leaderboard.
At the moment, we can only show the top ten. So we need our leaderboard to focus on the score the player’s just uploaded.
Quick test: Play in Unity and upload a score. The new score you just uploaded should now be highlighted in yellow.
Our game’s pretty much done now. But there’s still an important stage left: polishing.
It’s always important to go back to the features we added early on, and make sure they still work okay now we’ve added more features.
We’ll polish more aspects of the game later on. But we need to start with the UI, since it hasn’t really been able to keep up with all the new features we’ve added.
The leaderboard can be hard to read with the outlines we added early on. It also looks a bit unfinished when it just appears out of thin air.
So here’s what we’ll do with the UI:
At the moment, we’re just switching the game objects on and off. That looks pretty clunky, so instead we’ll ‘swoosh’ them in from the sides.
To do this, we need to read the anchor points of our different UI’s: If it’s anchored to the right, it’ll swoosh in from the right side of the screen, and vice versa for the left side.
Quick test: Play your game and look at all the swooshy movements.
We still have text telling the newly-dead player to press spacebar to return to the menu. This doesn’t really fit anymore – it’ll fight for attention with the button we added for uploading the score.
So to return to the main menu, let’s have a button instead.
Quick test: Press play and do a full run through – play, die, upload score and return to menu. Just don’t get sidetracked by trying to beat your best score.
With all the buttons and leaderboards we’ve added, the outline of the text doesn’t fit that well anymore. But that’s very quick to fix.
Quick test: Have another quick playthrough and make sure the text is looking nice and readable.
When something happens in the UI that’s tied to something in the game, it’s good to show there’s a connection between the two. We can do this by animating specific parts of the UI.
At the moment, our score UI is only visible when the player’s playing our game. To show the connection between scoring a point and the score UI changing, we’ll animate it.
Quick test: Play the game and watch the score ‘pop and spring’ with every pipe you pass.
At the start of this guide, we decided on a name for our game: FlappyLoot. But that name doesn’t actually appear in the game yet.
Let’s add a title to our menu screen, so the player knows what game they’re playing. We’ll give the title text a bit of animation too.
Quick test: Start the game and take a look at the main menu. You should now have your game title drifting up and down. It’s not the fanciest title screen, but it’s more interesting than static text.
Our bird dies when it hits the bottom of the screen – but it doesn’t actually have anything to collide with. So let’s add some grass to make it clear that the bottom of the screen is the ground.
Our sky’s a bit bland too. So we’ll add some passing clouds to make it feel more dynamic.
The grass will behave pretty much the same way as the pipes – it’ll just appear on every screen, rather than only while playing the game.
First we’ll create a SceneryController class that’ll handle the scenery movement.
Quick test: Start your game and you should now see some grass whipping along the bottom of the screen as Hector flies along.
This will be a pretty quick process now, since we just need to add some more things for the SceneryController to move.
To get a nice parallax effect, we’ll also randomize the scale of the clouds. And we’ll use that scale to determine what speed they should move.
Quick test: Hit play and you should now see some nice, puffy clouds drifting by.
When Hector dies, he just falls down at the moment. To make it more interesting, we’ll give him a bit of a spin and add something called a hitstop/freeze frame. A hitstop is when the game freezes time for a moment to give more impact and feedback. If you’ve played anime or manga games, you’ll see this effect used for punches and kicks. So it’ll work perfectly for our game.
We’ll create a function to handle this behavior for us. The code is small – it’s just one function, which we’ll call when our bird collides with something.
Quick test: Play the game and fly Hector into a pipe. You should now have a much more interesting death animation.
When Hector falls down into the grass, the game setup we have now leaves him falling forever. That’s because he can’t collide with the grass yet – only the pipes. So let’s fix that.
Quick test: With these changes, any recently deceased bird should now land and stop on the ground.
We haven’t done any sound work yet. So our game’s completely silent.
Luckily, setting up sound is quick and easy. And since FlappyLoot is a pretty straightforward game, we don’t need many sounds. We’ll add only three:
Quick test: Play the game and listen to Hector flapping and squawking.
This process is similar to what we just did. The only difference is that we’ll call it from PipeController, since PipeController is the class that gives the score.
Quick test: Play your finished game and make sure it’s all working how you want it to.
And with that, we’re done with this guide.
Be proud of yourself – you’ve made a complete game from scratch. That’s no small feat.
On top of all the game features you’ve practiced, hopefully you’ve also learned:
So what now? If you want to take this project further, there are plenty of other things you can work on. Such as:
If you want to add more features from LootLocker, you can see our full repertoire on our website.
Now you’ve finished this guide, give us a shoutout. We’d love to see your game. You can find us here: