Create Flappy Game Mechanics with Unity & PlayMaker
- 1.5 hours on-demand video
- 13 downloadable resources
- Full lifetime access
- Access on mobile and TV
- Certificate of Completion
Get your team access to 4,000+ top Udemy courses anytime, anywhere.Try Udemy for Business
- quickly develop small prototype games with the basic mechanics in place
- set up the basic mechanics for a small Flappy-like game
- understand the basics of PlayMaker in Unity
- react on object collisions
- manage the game progress with a basic Game Manager
- This is not an introduction to Unity, so you should at least understand the basic concepts of GameObjects, Components, Scenes, Transforms and the Physics Engine
- You should have access to PlayMaker, an addition to Unity. No other software is required.
Update: May 2020 - the Flappy Game is updated using Unity 2019.3
This course is a gentle introduction to small interactive games like Flappy Birds or other classics. Instead of making a clone, we will only go through the game mechanics: flapping or jumping, gravity and collisions, using Unity Physics.
The graphics will be deliberately crude: a white capsule and a few boxes. There are no textures, sprites, sounds or particle effects. We encourage you to make something of your own.
You'll need to know the basics of Unity: creating GameObjects, navigating the 3D Window and adjusting components. We'll use the popular Playmaker extension from the Asset store, which is a visual coding system, providing a Finite State Machine implementation, requiring no custom scripting. We go through every step from scratch, although the final result can be downloaded as a package for you to study.
So if you want to add some interactivity and make something fun, but don't know where to start, this is a good opportunity. And please share your results and make something unique.
- This Unity course is meant for beginning game designers, who know the basics of Unity, but want to apply PlayMaker, a visual programming system
- This course explains the game mechanics, but skips any art or imagery.
- This is not a course in custom C# programming.
- We keep everything rather basic, so you understand every step of the way.
Before we begin the course, we give a small demonstration what our final result will look like. It is crude and simple, but we create it from scratch. There is nothing to download, nothing to install, apart from PlayMaker.
This is not a fill-in-the-blanks course, which will get you a polished result, but which does not teach you much. Every step you do is your own and you can diverge from the example as much as you want.
For your convenience, you can download a package for Unity 2019.3 from the resources, to compare with. But everything is created during the course, so you don't really need it.
We start with creating a new Unity project and adding the PlayMaker package. If you have not used PlayMaker before, head over the the Asset store: PlayMaker Package (https://assetstore.unity.com/packages/tools/visual-scripting/playmaker-368)
While it is not free, it is often available at a discount.
In this lecture, we set up a few game objects: a capsule which will become our hero, a Directional light to see something and two quad mesh objects, which will act as floor and ceiling. We also set up the camera to be orthographic, rather than perspective, as to get a (fake) 2D look.
Position everything in the center of the world, so it is easier to navigate around.
PlayMaker adds Finite State Machines (FSM) to Unity. FSM define the behavior of objects. PlayMaker provides a visual approach to manage the states of objects.
The concept is straight forward:
- Unity GameObjects can have one or more FSM components;
- Each FSM encapsulates a specific behavior;
- Inside an FSM, States are defines;
- At any point in time, only one State can be Active;
- States have Actions that define what happens while the State is active;
- Actions can call Events;
- Events do nothing in themselves - think of them as messages;
- Global Events are events that are sent between FSMs;
- Transitions allow you to link an Event to a State;
- This way, objects will shift between states when the app is running.
Some useful tips:
Make FSM as small as possible. Simply describe in which different states a particular object can be. If an object has multiple behaviors, such as moving and shooting, you can define them in different FSMs.
If you need to maintain a score or health or inventory, define them as "Managers", which are often just empty objects with a few local variables. The managers do nothing special, but they react on usually global events.
Objects that are interactive in the scene get their own FSM. They don't keep a score or health or other information. They simple have their own behavior and will send a (global) event to the managers that will do the book keeping.
Now we are ready to get into action. We add an FSM (Finite State Machine) to our hero character and have him jump or flap whenever we hit a button or press the mouse.
Everytime we push the screen or press a key, an impulse force is applied which pushes him up. But by also adding a RigidBody component, the Physics engine will ensure that he falls down again.
In fact, our very basic game mechanics are ready at this point. But we'll continue a bit, off course.
The next step is reacting on our player hitting things.
We focus on the lower quad, which acts as a ground plane. By adding a FSM, we can check collisions against the player. The collision event ensures that only an object tagged "Player" will be detected and then emits a "global" event, to warn other FSMs that something was hit by the player.
That's all our ground plane needs to know.
The moving poles take a bit more effort to set up, but they are still fairly easy to create. We add two boxes, one "upper pole" and one "lower pole" and group them together by parenting them to an empty object, called poles.
Both poles get a copy of the FSM from the ground plane, as they also need to detect the player hitting the pole.
We'll add a new FSM, which will first move the poles to the far right (outside of the screen). They will also shift a bit up or down randomly, so the space between the two poles is always at a different spot.
And then they get into a moving state, where they simple move from right to left at a fixed speed.
Maybe you can slowly increase this speed over time?
And to clean up, they get removed or destroyed when they have passed the left side of the screen. This is simply done by checking the position and comparing it to a preset fixed value.
At the end, we also turn the Poles object into a Prefab, so it can be instanced afterwards whenever we need a new pole. All poles in the game are just copies of this one.
We set up an empty GameObject with two new FSMs to manage our game. The first FSM is the "Pole Spawner". This loops between the creation of a new pole (an instance or clone of the Poles prefab) and waiting for the next pole to be added.
As the poles take care of movement and hit checking, there is nothing else to do in the Pole Spawner.
However, to clean up when the player hits anything, we react on the global "player_was_hit" event and go to an empty final state, so no new poles will be added.
Ultimately, we need to keep track of a score. Our interpretation of the game simply compares the position of the Poles ("current_x") with the fixed value of -1. If we ever get that far, that means our pole has passed the player without being hit, so we can emit a message to increase the score. This is done by the Poles.
The actual score keeping is done in the second FSM that is attached to the Game Manager: our Score Manager.
This keeps the score as a whole number (integer) called "score" and also transforms this into a string. We'll use a GUI Text to display this string.
Whenever we receive the global "add_score" event, we will increase the score and display the new value.
Here we will put some finishing touches on our Game. Not on graphics, but on making sure we wrap up nicely.
We need to react on the global "player_was_hit" event and finish the game. This is done be allowing the user to press a "restart" button (but any click or key press will also do this).
That's it. We are ready to test. We also ensure that the hero is stopped at this point, by also reacting on this global event.
Tip: Maybe you can look at "PlayerPrefs" to store our maximum score?
Tip: This would be a good time to add a sound or particle effect.
This game is a recreation of a classic Breakout game: you move a paddle from left to right and try to catch a falling ball. By bumping the ball up, you can hit target bricks for points. When you get the final brick, you finish the level.
Here we show the end result we can achieve at the end of this Section.
First we create our paddle: a simple Cube. We react on key presses: the left and right arrows. Whenever one of those keys is held, we go to a moving left or right state.
The first attempt is straight forward, but we have to finetune it a bit, to allow moving from the moving left to the moving right state directly, as to allow an improved control over the paddle movement.
Otherwise, we would have to pass by the waiting state every time we change direction and we have to release the left button before we can start moving right.
The walls will be simple cubes. There is nothing to it.
The ball is a sphere. We add a Rigidbody to it, to make use of Unity Physics, but we don't use Gravity. Instead, we set the velocity of the ball in our FSM.
We use a Vector3 (an X-Y-Z direction) to define where the ball is moving. Whenever we hit an object, we get the direction of that object from the Collision Event, in the Normal, which is also a Vector3. This defines the perpendicular direction of the surface we hit.
We need to reflect our incoming direction (before the hit) with the surface to get our out coming direction (after the bump). Luckily for us, PlayMaker provides a simple "Reflect" operator which does exactly this.
At the end of this lecture, we already have the main game mechanics of our project in place.
However, when we miss the ball, it continues into an eternal void. We need to catch the ball with an invisible box. Upon collision, we can reset the level. A bit brutal, but this works for now.
And now we can introduce the target bricks: simple boxes, that also react on a collision with the ball. In fact, we use almost the same FSM as the reset box, but instead of resetting the level, we destroy the brick to remove it from the game.
When we hit a brick, we need to keep track of the score. We do this by defining a global event "add_score", which can be reused from the Flappy Capsule game, if we work in the same project.
Whenever a brick is hit, it emits this event globally. Nothing more.
Then we add a Game Manager object to track the score. It keeps track of the score with a "score" int variable, which is increased every time we receive an add_score global event.
The Game Manager is then responsible for displaying the score, by copying the score value in a string to be display as a GUI Text element.
Beware that at this point in the project, the game has no end...
The final task is keeping track of the score. We do this by counting all bricks. The easiest way to do so, is by adding a tag to the bricks and counting the tags at the start of the level (in the Start State of the Game Manager).
Now we can compare the actual score with the total required score, every time we receive an add_score event and if they are equal, we transition to a Finish State.
The make a clean end, we display a Restart GUI Button and also warn the other FSMs in the scene, so the paddle stops moving and the ball is cleaned up.
That's it. Our game is ready. Or ready enough, at least.
That is it. We finished the game. It's not perfect, but it is fully functional. Think about what you could do next: increase the speed over time? Add some special bricks with special features? Add a shooter to the paddle? Slowly move the bricks down? There is no limit to what you can create.
Thank you for taking this course. I really hope you enjoyed it and please stay in touch. Leave a message on the Discussion Board, leave an honest review or spread the word to other possible students. This really helps me continuing making new courses and improving the existing ones.
And if you have a question, do not hesitate to ask.