The Unity Tutorial For Complete Beginners
Summary
TLDRIn this tutorial video, the creator shares a practical three-step method for learning Unity, aimed at aspiring game developers who struggle with traditional long-winded tutorials. The method involves mastering foundational aspects of Unity, reinforcing knowledge through hands-on exercises, and building games incrementally. The video walks viewers through creating a version of the popular game "Flappy Bird," covering topics such as UI setup, scripting, game physics, and collision detection. By the end, the viewer should have a fundamental understanding of Unity and an operational Flappy Bird game. The creator encourages active learning by inviting viewers to expand on the project and venture into recreating other simple games using Unity.
Takeaways
- 🎮 Learn Unity by creating Flappy Bird - a hands-on approach!
- 🚀 Understanding GameObjects and components is crucial.
- 🖱️ Unity's UI tools make game interface integration easy.
- 📜 Scripting in C# allows for dynamic game interaction.
- 🏗️ Use prefabs for efficient object management in Unity.
- ⚙️ Manipulating game physics enhances gameplay experience.
- 🔄 Timers and if statements control game events effectively.
- 💥 Use collisions and triggers for interactive gameplay.
- 🧠 Develop problem-solving skills by recreating simple games.
- 📈 Continuously iterating on designs is key for improvement.
Timeline
- 00:00:00 - 00:05:00
Mark expresses his long-standing desire to create video games using Unity. After experiencing ineffective tutorials, he devised a three-step method to learn Unity basics, practice through exercises, and learn progressively by making a game. This method led him to successful projects, including a video essay with 100k plays.
- 00:05:00 - 00:10:00
Mark sets up a plan to learn Unity's basics by identifying crucial actions needed for game creation. He learned through tutorials, Unity docs, and trial and error. This video aims to save others time by providing a comprehensive tutorial to recreate Flappy Bird, covering from basics to sharing the game with friends.
- 00:10:00 - 00:15:00
The tutorial begins with downloading Unity, setting up Visual Studio, and creating a new 2D Core project. Mark explains the Unity interface, intended for creating a bird sprite from imported assets. He outlines the project's four main panels: Project, Hierarchy, Inspector, and Scene View, and their functions.
- 00:15:00 - 00:20:00
Explaining GameObjects and components, Mark shows how to create a bird object with a Sprite Renderer component, enabling it to display the bird image. He demonstrates adjusting object properties and camera views, culminating in a basic setup where the bird image appears on the scene view for further development.
- 00:20:00 - 00:25:00
Mark introduces the Rigidbody2D component to apply gravity to the bird, causing it to fall. He guides through creating script files in Visual Studio to manipulate GameObject properties using C#. By coding spacebar input, users can launch the bird upward using velocity changes, blending technical programming with game design.
- 00:25:00 - 00:30:00
Mark elaborates on code structure, introducing if statements and public variables to adjust the bird's movement dynamics. He emphasizes efficient code practices and real-time parameter adjustments in Unity. The session sets up the bird movement mechanics foundationally, simulating the basics of Flappy Bird's gameplay dynamics.
- 00:30:00 - 00:35:00
The video progresses to making pipes as obstacles, implementing GameObjects to spawn moving pipes across the screen. Utilizing prefabs, Mark crafts a system to instantiate pipes on a timer, ensuring proper game flow. He addresses technical challenges involving frame rate consistency, demonstrating strategic code planning.
- 00:35:00 - 00:40:00
Mark shifts to score tracking and UI, introducing invisible GameObjects for managing gameplay data. By creating and manipulating UI components, he implements score increments when the bird passes through pipes. The explanation extends to designing collision checkers and writing scripts for interactive triggers, enhancing gameplay complexity.
- 00:40:00 - 00:46:39
The final phase integrates game-over conditions using collision detections, with UI panels to restart the game. Mark explores booleans and other variable types for game state management. The tutorial concludes by building the game, suggesting further personal exploration and expansion of the game concepts, and encourages community engagement.
Mind Map
Video Q&A
What is Unity used for?
Unity is used as a game engine for developing video games across multiple platforms.
What is the three-step technique mentioned?
The three-step technique involves learning Unity basics, practicing with simple exercises, and figuring out the rest incrementally.
Why did the creator decide to make this tutorial?
The creator aimed to provide a simple, effective Unity learning method that they wish they had when starting, avoiding lengthy, meandering tutorials.
What does the creator recommend doing with this tutorial?
Following the tutorial helps one remake Flappy Bird while learning Unity basics, with suggested next steps for further self-guided learning.
What are GameObjects in Unity?
GameObjects in Unity are invisible containers that can hold components to add features, serving as elements like characters, pipes, and UI in games.
What is the main purpose of the Logic Manager in the tutorial?
The Logic Manager tracks game status elements, such as scoring, and manages visible UI updates during gameplay.
Why use Time.deltaTime in game development?
Time.deltaTime ensures that game actions occur at consistent speeds across different computer hardware, regardless of frame rate.
What is the purpose of triggers in this Unity tutorial?
Triggers are used to detect when the bird passes through pipes in the game, which helps in scoring.
How can one restart the game in this tutorial?
A button on the game over screen is coded to restart the scene, essentially restarting the game.
What future steps does the creator suggest after the tutorial?
Suggestions include adding game features (e.g., sound effects, animations), and trying out building additional simple games independently.
View more video summaries
- 00:00:00Hi, my name is Mark.
- 00:00:01For years I've wanted to make my very own video games, using software like Unity.
- 00:00:07Unity is the powerful game engine behind titles like Cuphead, Neon White, Tunic,
- 00:00:13Outer Wilds, Hearthstone, Firewatch, and even the Pokemon Diamond remake.
- 00:00:18But I've always found that lengthy, multi-part, meandering tutorials just send me to sleep.
- 00:00:25I can't learn by watching someone else - I have to get hands-on and figure things out for myself.
- 00:00:31And so last year I developed a solution that actually works.
- 00:00:35It's a three-step technique where you: one just learn the absolute basics of Unity.
- 00:00:41Then, two, cement those lessons with simple exercises.
- 00:00:45And then, three, figure out the rest as you go along.
- 00:00:49And it totally worked! In the space of about a year,
- 00:00:52I went from ripping off iPhone games to working on my very own puzzle platformer about magnets.
- 00:00:58And I released an interactive video essay that's had over 100,000 plays.
- 00:01:03But wait, I hear you say! How do you do step one? How do you learn the basics,
- 00:01:08when the software is so complicated to figure out?
- 00:01:11Well for me it was about writing down a list of things I would need to know,
- 00:01:15regardless of what game I was going to make.
- 00:01:17Things like how to make a character appear and move them around the screen.
- 00:01:21How to make stuff spawn in and then delete it again later.
- 00:01:24How to have collisions and game over and animations and sound effects.
- 00:01:28Then I learned all that by hunting through lengthy tutorials, reading the Unity docs,
- 00:01:33Googling esoteric words, and doing a lot of trial and error.
- 00:01:37And so the whole point of this video is to save you that hassle.
- 00:01:41This video is the tutorial I wish I had when I was learning Unity.
- 00:01:46So in the next 40 minutes we're going to use the engine to make Flappy Bird.
- 00:01:50Not because we want to make Flappy Bird, but because in order to remake
- 00:01:54this addictive iPhone game, we'll need to learn basically everything I just listed,
- 00:01:59from spawning objects to getting game overs.
- 00:02:02This tutorial will cover every step of the way from downloading Unity,
- 00:02:06to understanding the UI, to writing your very first line of programming code,
- 00:02:11to building a game that you can share with your friends.
- 00:02:14And then, when the tutorial is over, I'll share some concrete
- 00:02:18next steps that you can take in order to continue learning the rest by yourself.
- 00:02:22Sound good? Then let's get started.
- 00:02:26Okay, let's start by getting Unity from the website.
- 00:02:30Download and install the Unity Hub.
- 00:02:34And then you'll need to make a free account to actually use it.
- 00:02:38Once that's done, you'll be asked to install the Unity Editor - I'm using version 2021.3 for this
- 00:02:45tutorial, if you're watching a million years in the future and wondering why things are different.
- 00:02:49Let's pretend I have fast internet - Neeooowwwwmm.
- 00:02:52We're not quite done yet.
- 00:02:55Under installs, hit the cog icon on the Unity Editor and pick modules.
- 00:03:00You'll see that Microsoft Visual Studio has been ticked - this is
- 00:03:04the software we'll use to write programming code.
- 00:03:06So hit continue.
- 00:03:07And install Visual Studio.
- 00:03:09On this screen, scroll down and tick game development with Unity,
- 00:03:13and untick Unity Hub, because we already have it.
- 00:03:16Neeooowwwwmm.
- 00:03:17We don't need to make an account to use Visual Studio, so skip that.
- 00:03:21And don't bother loading it, we'll open it later.
- 00:03:23Okay, that's all done now.
- 00:03:25So in Unity Hub, pick new project.
- 00:03:27Choose all templates.
- 00:03:29And use 2D, Core.
- 00:03:31This is an empty project, with a few configurations to make it suitable for 2D games.
- 00:03:36Give your project a name, hit create, and let's get game makin'.
- 00:03:43In step one, we're going to become familiar with the default Unity user interface.
- 00:03:48And as we explore the different panels, we'll make the bird appear on screen.
- 00:03:52Right.
- 00:03:53So this is the default screen layout for Unity, and it's split into four panels.
- 00:03:59First of all, down here, is the Project panel.
- 00:04:02This will contain everything that is in our game - like sprites,
- 00:04:06sound effects, scripts, tiles, fonts, and so on.
- 00:04:10Some of this stuff will be made in Unity as we go along.
- 00:04:14But we can also just drag and drop files from elsewhere on our computer.
- 00:04:17Like, I've made some sprites for the bird and the
- 00:04:21pipe in Photoshop and I'm going to import them into my project like so.
- 00:04:25I'd recommend you make your own - that's always more fun - but
- 00:04:28if you have zero artistic ability then check the description for these assets.
- 00:04:32The next panel is the hierarchy.
- 00:04:35This contains all of the stuff that's in the current scene - which,
- 00:04:38in most games, will be a level.
- 00:04:40We're going to start by making the bird, so right click and choose Create Empty.
- 00:04:45This has made an empty GameObject...
- 00:04:48so what's that?
- 00:04:50Well, a GameObject is essentially an invisible container.
- 00:04:53It has a position in space, a rotation, and a scale.
- 00:04:57Then, you can fill that container with components - to add extra features.
- 00:05:02For example, if we add a Sprite Renderer component,
- 00:05:05we can slap the bird image onto the GameObject.
- 00:05:08Absolutely everything in our level will be a GameObject with components - the bird,
- 00:05:13the pipes, even the user interface and the camera.
- 00:05:16All of this magic happens in the third panel, the Inspector - which is for messing with GameObjects.
- 00:05:22So, once we've selected our new,
- 00:05:24empty GameObject we can put a name in the top field - let's call it Bird.
- 00:05:28And we can see and change the GameObject's position, rotation, and scale, under Transform.
- 00:05:34We can now press Add Component, pick Rendering, and pick Sprite Renderer.
- 00:05:40To make this work, we need to fill in the sprite field - so just drag the
- 00:05:44bird image from the project panel into the field and viola, we have graphics!
- 00:05:49That will, of course, show up in the fourth and final panel, the scene view.
- 00:05:54Here we can see what's in our current scene, and,
- 00:05:57if you want, you can use these tools to move stuff around, scale it, and so on.
- 00:06:01This section has an extra tab for game view,
- 00:06:04which shows us what the game will look like from the main camera when it's running.
- 00:06:08Also, from this dropdown, we can set a resolution or aspect ratio to get
- 00:06:13a better idea of what it will look like when played - so I'm going to choose 1920 by 1080.
- 00:06:19Oof, the bird takes up way too much space.
- 00:06:21We could scale it down, but let's actually just zoom out the camera.
- 00:06:25Like I said before, the camera itself is a GameObject in the hierarchy.
- 00:06:29And it has a camera component with stats we can mess with.
- 00:06:33By changing the size, we can zoom out.
- 00:06:36I'm also going to change the background colour.
- 00:06:38Lovely.
- 00:06:39We can now press the play button up here to start...
- 00:06:42the world's most boring game.
- 00:06:45Okay, let's make it a bit more exciting.
- 00:06:49A quick recap.
- 00:06:50Unity has four panels by default.
- 00:06:53Project holds all the stuff in our game.
- 00:06:55Hierarchy lists all of the GameObjects in the current level.
- 00:06:59Inspector lets us see and change those GameObjects.
- 00:07:02And we can see the level in the scene view.
- 00:07:04And a GameObject is an invisible container that we can fill with components, like a sprite renderer.
- 00:07:11In step two we're going to use more components to make the bird
- 00:07:15into a physics object that is affected by gravity.
- 00:07:18And then we're going to write some programming
- 00:07:20code to make the bird fly up when we press the space bar.
- 00:07:23So let's add another component to our bird: a Rigidbody 2D.
- 00:07:27This turns our bird into a physics object, with gravity.
- 00:07:31So when we hit play, the bird drops, and falls off the screen.
- 00:07:35Cool.
- 00:07:36We'll also want this bird to be able to interact with other objects, so let's add a collider.
- 00:07:42A circle collider 2D.
- 00:07:43Back in scene view we can see the collider as a green outline.
- 00:07:47It's a bit off-center for me, so I'll use the offset to move it.
- 00:07:52And, a little game design trick - if we make the collider a bit smaller than the image,
- 00:07:57it will let the player get through pipes even if they juuust touched the edge.
- 00:08:01It gives the game a bit of leniency and makes it feel more fair.
- 00:08:05The final thing to add right now: a script.
- 00:08:08This essentially lets us make our own custom component - but we'll
- 00:08:12have to write it ourself using programming code.
- 00:08:14Choose New Script from the components list.
- 00:08:17And call it BirdScript.
- 00:08:19Once it's loaded, double click the script field to open it up.
- 00:08:23This will open the file in Visual Studio, which we installed earlier.
- 00:08:27So, welcome to programming! It's not too scary, promise.
- 00:08:31We'll take it slow.
- 00:08:32We're writing in C sharp, that's the programming language.
- 00:08:35And the only thing to worry about right now is these two chunks here: start and update.
- 00:08:41Start is for any code that will run as soon as this script is enabled.
- 00:08:46And it runs precisely once.
- 00:08:48Update runs constantly while the script is enabled.
- 00:08:51And it will fire off every line of code, every single frame.
- 00:08:55Over and over and over again.
- 00:08:58So the main thing we're going to be doing with code right now is - well, if we go back
- 00:09:02to Unity - see these numbers and text fields in the components? And how we can change them in
- 00:09:08the Unity editor? We're just going to write code to change these stats while the game is running.
- 00:09:13Just as a dumb example, and we'll delete this in a second.
- 00:09:16In start, we can type gameObject - that refers to this bit up here.
- 00:09:22And then a dot.
- 00:09:24You'll see a list appear, and many of the items refer to stuff back in the Inspector,
- 00:09:29like isStatic, tag, layer, and name.
- 00:09:33So let's pick name.
- 00:09:35Then write an equals sign.
- 00:09:38And in quotes, give our bird a name.
- 00:09:40Finally, we must always use a semi-colon to mark the end of a command.
- 00:09:45And we must always save the script before we go back to Unity.
- 00:09:48Now, when we run the game...
- 00:09:50the name of the GameObject has been changed.
- 00:09:53Nice.
- 00:09:55Okay, delete that code.
- 00:09:56That was just for sillies - but it shows us how we can use code to talk to the game.
- 00:10:00We can write a command by choosing someone to talk to - in this game, the GameObject - and
- 00:10:06then a topic of conversation - its name - and then a command - change it to Bob Birdington.
- 00:10:12We'll be doing this a lot.
- 00:10:14So what we actually want to do is...
- 00:10:16in the Rigidbody 2D's component, under info, we'll see a greyed-out field for velocity.
- 00:10:22And we want to write some code to add upward velocity to the bird to make it fly into the air.
- 00:10:27The problem is...
- 00:10:28initially, a script can only talk to the GameObject's top bit and the transform.
- 00:10:33Right now, this script is completely unaware of the other components.
- 00:10:37So we need to sort that out first.
- 00:10:38We need to make a special slot on this script for
- 00:10:42a Rigidbody2D - so we can then talk to it and send it commands.
- 00:10:46This is called a reference.
- 00:10:48We're going to create the reference up here, between the class name and the start function.
- 00:10:53We're going to write public Rigidbody2D myRigidbody.
- 00:11:00So we now have a slot to store a Rigidbody2D.
- 00:11:03And we have a name that we can refer to - to make sure
- 00:11:06we're talking about this specific Rigidbody2D.
- 00:11:09And because we made it public, it means we can access this slot from outside the script.
- 00:11:13So, if we save.
- 00:11:15And go back to Unity, we'll see that the script component now has a field for a Rigidbody2D.
- 00:11:21We can drag the component into that slot, and viola.
- 00:11:24We have established a line of communication between the script and the Rigidbody.
- 00:11:29Okay, back in Visual Studio.
- 00:11:31In update, we can type myRigidbody.
- 00:11:34Then dot.
- 00:11:35And now look at all the things we can talk about.
- 00:11:38Angular drag, gravity scale, mass - these are all properties on the component.
- 00:11:43The one we want is velocity.
- 00:11:45We want to set this to a new number, and so, just like before with the name, we'll write an equals.
- 00:11:51Now what we're actually writing here is a vector, which is two numbers,
- 00:11:55to represent a position in 2D space.
- 00:11:57And in this case, it's used to represent a direction for the bird to travel.
- 00:12:01We want the bird to go straight up, so zero, comma one would be a good one.
- 00:12:06I'm just going to use Vector2.up, which a built-in shorthand for zero comma one.
- 00:12:11And to give it a bit more power, I'm going to multiply that vector by a number.
- 00:12:16Say, 10, which should send the bird flying up in the sky.
- 00:12:19Now, like I said before, any code in update will run, over and over again, every frame.
- 00:12:25So if we save the script and hit play in Unity...
- 00:12:29off goes our bird.
- 00:12:30Bye!!
- 00:12:31That's not what we want.
- 00:12:32We want this to only happen when the player hits the space bar.
- 00:12:35So it's time to use the most fundamental bit of programming code: the if statement.
- 00:12:41An if statement is like a gate.
- 00:12:43You can surround some code with a fence, and every frame that code will be completely ignored.
- 00:12:48Unless, the game meets some specific conditions that are written on the
- 00:12:52gate - in which case the gate is open, and the code is read and executed.
- 00:12:56So we want to say "if the player hits the space bar, then add upward velocity".
- 00:13:00To do this...
- 00:13:01we can write if, and then in brackets we can write the condition.
- 00:13:05This time we're not talking to a component,
- 00:13:07we're talking to Unity itself - specifically its input system.
- 00:13:11So we'll write Input.
- 00:13:13Then we can pick GetKeyDown, and in brackets, KeyCode.Space.
- 00:13:18This asks Unity if the space bar has been pressed on this frame.
- 00:13:22And then we'll finish with equals, equals true.
- 00:13:25A quick note on equals signs - we use one to make the thing on
- 00:13:29the left be the same as the thing on the right.
- 00:13:32And we use two if we're just checking if the thing on the left is the same as the thing on the right.
- 00:13:37Cool?
- 00:13:38Anyway.
- 00:13:39So this code says...
- 00:13:40if the space bar has just been pressed, then...
- 00:13:43and then we'll use curly brackets - these are the
- 00:13:45fence in our little analogy - and put the flap code in here.
- 00:13:50So, now in update - every frame the game will go to the gate and be asked "hey,
- 00:13:54has the spacebar just been pressed?" If yes, the code will fire and the bird will flap.
- 00:13:58If not, it will skip the code in the curly brackets and try again next frame.
- 00:14:02So - save the script and go back to Unity.
- 00:14:05We can now hit play and tada: the bird goes up when we press space.
- 00:14:10We have now created a character and made it react to input.
- 00:14:14This is a video game.
- 00:14:16Hooray!
- 00:14:17However, it feels like trash.
- 00:14:20The flap isn't right, and it doesn't feel like the original iPhone game.
- 00:14:23So we could change this number.
- 00:14:26Save.
- 00:14:27Open Unity.
- 00:14:28Run the game.
- 00:14:29Not quite right.
- 00:14:30Stop.
- 00:14:31Change the number.
- 00:14:32Save.
- 00:14:33But that's slow and dumb.
- 00:14:35Let's do something smarter.
- 00:14:36First, we're going to make a variable.
- 00:14:39Let's go back to the top of the script and under our reference to the Rigidbody,
- 00:14:42let's make a public float called flapstrength.
- 00:14:46A float is a floating point number - basically a number that can have a decimal place.
- 00:14:51And then back in our update code, we'll multiply the vector2.up by flapstrength, instead of 10.
- 00:14:57Now, back in Unity, you'll see that the script component has a new field: flapStrength.
- 00:15:03And we can change that whenever we want to make the game feel different.
- 00:15:07We can even change it during the game, but note that anything you
- 00:15:10change while the game is running won't save when you press stop.
- 00:15:13This means you can play with values to your heart's content
- 00:15:16without worrying about screwing up your game.
- 00:15:18So, if we mess with the flapStrength, and also the gravity scale on the Rigidbody,
- 00:15:23we'll hopefully get to something that feels good.
- 00:15:25Ah, changing numbers back and forth: honey, that's game design!
- 00:15:30Recap time.
- 00:15:31We can use code to change the properties of a component, while the game is running.
- 00:15:36A script cannot talk to the other components on the gameobject, by default.
- 00:15:40You have to make a line of communication by storing a reference to that specific component.
- 00:15:45We create the reference in code, and then fill it in Unity by dragging and dropping.
- 00:15:50Code in start runs once, when the script comes into existence.
- 00:15:54Code in update runs continuously, every single frame.
- 00:15:57But, we can use if statements to skip some code, unless a condition is met.
- 00:16:01And we can use public variables to change certain
- 00:16:04values in Unity's inspector - even while the game is running.
- 00:16:09Okay, so the secret to Flappy Bird is that while it looks
- 00:16:13like a bird is flapping along through a world of pipes - it's actually not.
- 00:16:17The bird stays completely still and the pipes move across the screen.
- 00:16:21So in step three we're going to make pipes spawn into the world,
- 00:16:25move across the screen, and then delete themselves.
- 00:16:28We'll start by making the object we want to spawn.
- 00:16:31This will be two pipes which move across the screen, from the left to right.
- 00:16:35Let's make another GameObject called pipe.
- 00:16:38Put it exactly on the bird for now, to get the sizing right.
- 00:16:41And then we'll make another object within this one, called top pipe.
- 00:16:46This is a child of the first GameObject's parent.
- 00:16:49This way we can nest multiple GameObjects,
- 00:16:52and move all of them at once just by moving the parent.
- 00:16:55So let's repeat what we did for the bird.
- 00:16:57Add a sprite renderer for the pipe image.
- 00:17:00And add a collider - a Box Collider 2D, this time.
- 00:17:04We don't need a RigidBody because it's not going to be affected by physics.
- 00:17:07We can then move it up above the bird - but keep the X position as zero.
- 00:17:13Finally, we can duplicate this whole top pipe object.
- 00:17:16Call it bottom pipe.
- 00:17:18And flip it upside down by changing the Y scale to minus one.
- 00:17:22Then move it down below the bird.
- 00:17:24As you can see, if we mess with the pipe parent GameObject, both pipes move, scale,
- 00:17:31and rotate along with it, with the parent as the pivot point.
- 00:17:34So let's add a script to this parent's object to make it move across the screen.
- 00:17:40We'll start by creating a variable for moveSpeed.
- 00:17:44If we give it a number here, it will fill this as the default value in Unity.
- 00:17:49But we can always change it there, later.
- 00:17:50Then we'll write code to move the object, in update.
- 00:17:53Now it would be lovely if we could just type transform.position.x,
- 00:17:58and change this number directly - but, no, boo, you have to change the entire Vector in one go.
- 00:18:04Oh, and this time we're gonna have to use Vector3,
- 00:18:07instead of Vector2, because the transform has three numbers.
- 00:18:11Even though we're making our game in 2D, Unity is still fundamentally a 3D engine
- 00:18:16and so it's keeping track of the object's depth with the Z value.
- 00:18:20So, here's what we'll do.
- 00:18:22We'll take the current transform.position.
- 00:18:24And then equals.
- 00:18:26We want to add to its current position, so write transform.position again.
- 00:18:30And then plus.
- 00:18:31And finally, in brackets, we'll do Vector3.left * moveSpeed.
- 00:18:39Back in Unity, press play and vroooof.
- 00:18:41That's way too fast.
- 00:18:42Now, you might think that you could just change
- 00:18:45this moveSpeed variable down to a really small number like 0.001.
- 00:18:49And that will work - but that's not actually the problem here.
- 00:18:53You see, code in update just runs as often as it can.
- 00:18:56In fact, if we check the stats in Game view,
- 00:18:58we'll see the game is running at over 1,000 frames per second.
- 00:19:02Heh, sorry PlayStation 5.
- 00:19:04120 fps? Pfft, that's got nothing on Flappy Bird.
- 00:19:07And the real problem is that the game may run at different speeds on different computers,
- 00:19:11and we don't want the pipe to move faster or slower depending on your rig.
- 00:19:16Real games have actually made this mistake - in Dark Souls 2, weapon durability was once
- 00:19:22tied to frame rate, so your swords would break twice as fast at 60 FPS, compared to 30 FPS.
- 00:19:29That was a whoopsie.
- 00:19:30Luckily, it's a pretty easy fix.
- 00:19:32We just multiply it by Time.deltaTime.
- 00:19:36This ensures the multiplication happens the same, no matter the frame rate.
- 00:19:40We didn't need it for the velocity code because physics runs on its
- 00:19:44own little clock, but otherwise we will need it.
- 00:19:46if you want to know more - about this, or anything really, the Unity docs are a good place to check.
- 00:19:51You'll find info and sample code.
- 00:19:53Okay, now with that fix in place, our pipe moves smoothly across the screen.
- 00:19:58Lovely.
- 00:19:59Next, we want to create a system that will continually spawn new pipes.
- 00:20:03To start, take the parent GameObject from the hierarchy and drag it into your project.
- 00:20:09This creates a prefabricated GameObject.
- 00:20:12Or prefab.
- 00:20:13This is like a blueprint for a GameObject and we can create new
- 00:20:16versions of this entire GameObject- with all its children, components, and properties.
- 00:20:21Oh, and before we move on, we can delete the original in our hierarchy now.
- 00:20:25Bye bye.
- 00:20:26Let's make a new GameObject called Pipe Spawner.
- 00:20:30We'll put it just to the right of the camera.
- 00:20:33And we'll make a script for it.
- 00:20:35The purpose of this script is to spawn new versions of the pipe prefab every few seconds.
- 00:20:40And because the pipe already has code to move left,
- 00:20:42the pipe will automatically move across the screen as soon as it spawns in.
- 00:20:47We're going to write some code to spawn that prefab we just made.
- 00:20:50So we'll start by making a reference to the prefab.
- 00:20:54Up here, we'll type Public GameObject pipe.
- 00:20:58Then in Unity, we'll use the same drag and drop method to fill the slot, but this time,
- 00:21:03instead of a component, we'll drag the prefab from the project panel.
- 00:21:07Now,
- 00:21:08Unity has a nice built-in method for spawning new GameObjects.
- 00:21:12We'll type Instantiate, and then open the brackets.
- 00:21:15In here, the command is asking for some extra details.
- 00:21:19we can actually flip through these to find different, I dunno, recipes? I guess? Number
- 00:21:244 looks good - it will create an object at a specified position and rotation.
- 00:21:28So, for the GameObject, we can type pipe.
- 00:21:31For position
- 00:21:32we can just type transform.position to get the position of the object holding this script.
- 00:21:37That will make it spawn on top of the spawner.
- 00:21:40And for rotation, let's just use transform.rotation so,
- 00:21:44again, it's the same as the spawner.
- 00:21:48Let's run it and oh my god, that's not what we want.
- 00:21:51Spawning works great, but they're coming out every single frame - and
- 00:21:54we want them to come out on a nice interval that we can control.
- 00:21:57So, back to Visual Studio.
- 00:21:59What we're going to do now is to write some code to make a timer.
- 00:22:03this will count up for a specified number of seconds,
- 00:22:06run some code, and then start the count again.
- 00:22:09To do this, we'll need to make a couple variables.
- 00:22:11A spawnRate is how many seconds it should be between spawns.
- 00:22:15And then a timer is the number that counts up.
- 00:22:18We can make this one private as we won't be changing it in the editor or anywhere else.
- 00:22:22In update, we'll do another if statement.
- 00:22:25This time, if the timer is less than the spawnRate,
- 00:22:29then we want to make the timer count up by one.
- 00:22:32So we'll take the timer as it currently is, and add Time.deltaTime to it.
- 00:22:37This creates a number that counts up every frame,
- 00:22:39and works the same no matter what your computer's frame rate is.
- 00:22:42We can actually shorten this by changing it to +=, but, don't feel like you need to make your code as
- 00:22:48short as humanly possible just to avoid getting sniffy YouTube comments.
- 00:22:52If timer = timer + is easier to read and grasp, then that's absolutely fine.
- 00:22:57You can always swap to the other version in the future when you feel more confident.
- 00:23:01Now, before I said an if statement is like a gate.
- 00:23:05And we can add another gate to the side of it, with else.
- 00:23:08This means, if the condition isn't met, then skip the code - and do the code in else, instead.
- 00:23:14So we'll put the spawn code in here, and also reset the timer to zero.
- 00:23:20So now, every frame, it asks if the timer is less than the spawn rate.
- 00:23:24If it is, then count the timer up.
- 00:23:26If it's not - i.e.
- 00:23:28the timer has actually met or exceeded the spawn rate, then spawn a pipe and start the timer again.
- 00:23:33Put this in Unity and - pretty good.
- 00:23:35I'm happy with that.
- 00:23:36The only problem is...
- 00:23:38we have to wait ages for the first pipe to spawn.
- 00:23:41It would be good if this came out immediately, right?
- 00:23:44Now, we could copy and paste the spawn code into start, so it happens once in start.
- 00:23:49And then happens over and over in update.
- 00:23:52But that's a bad idea.
- 00:23:53You should generally try to avoid having the same, or even similar code in multiple places.
- 00:23:59What happens if we want to change how the spawn
- 00:24:02works? We'll have to find and change it everywhere.
- 00:24:05No good.
- 00:24:06Instead, we can put the spawn code in a new function, and then just run that function.
- 00:24:10So here, below update - but above the final curly bracket - we'll
- 00:24:15make a function called void spawnPipe().
- 00:24:17And then cut and paste the Instantiate code into there.
- 00:24:21Now we can just write spawnPipe, with empty brackets, in both update and start.
- 00:24:26This will run all the code in that function when these lines are executed.
- 00:24:30And with that done, it will make a pipe as soon as the game begins,
- 00:24:33and will make new pipes every time the timer maxes out.
- 00:24:37Perfect.
- 00:24:38However - this is a pretty boring game, right? The pipes always come out in the middle.
- 00:24:44we want them to come out at random heights.
- 00:24:46So, remember that when we wrote the instantiate code,
- 00:24:49we had to pick a position for the object to appear? We'll change that value.
- 00:24:52Right now the pipes always spawn on the same position as the spawner.
- 00:24:56We want the X value to be the same...
- 00:24:58but for Y, we want to pick a random point somewhere above or below the spawner.
- 00:25:03So let's create a public variable for a heightOffset, maybe 10.
- 00:25:08And then we'll make a float called lowestPoint.
- 00:25:11Because we're making this variable inside the function, rather than at the top of the script,
- 00:25:16it means it can only be used within the function.
- 00:25:18But, also, it means we can set it by doing a calculation.
- 00:25:22so we'll do equals transform.position.y - heightOffset.
- 00:25:28And then we'll make another one for highestPoint, but this time it's plus heightOffset.
- 00:25:34That gets us these two numbers.
- 00:25:37Then we'll replace the transform.position in our Instantiate code.
- 00:25:41We're gonna write new Vector3,
- 00:25:43we have to write that whenever we're specifying our own numbers for a vector.
- 00:25:47and then in brackets we'll specify the X, Y, and Z values as three different floats.
- 00:25:53For X, we want this to be the same as the spawner, so we'll do transform.position.x.
- 00:25:58But for Y, we can do Random.Range.
- 00:26:01And in the brackets for that, we can supply a minimum and maximum point to pick from.
- 00:26:05That's lowestPoint and highestPoint.
- 00:26:09Then a 0 for Z.
- 00:26:10And close the brackets.
- 00:26:14Back in Unity....
- 00:26:15nice! The pipes will spawn anywhere between these two numbers.
- 00:26:19Oh, one last thing.
- 00:26:21Every time these pipes spawn they'll appear and move left....
- 00:26:25forever.
- 00:26:26Which isn't great practice - they're off screen and doing absolutely nothing,
- 00:26:30and yet they're still in memory and running code every frame.
- 00:26:32And if too many spawn they'll start to spill out the side of
- 00:26:36your monitor and make a right mess of your desk.
- 00:26:38So let's fix that.
- 00:26:40Now we could make a timer, and delete the pipe after a few seconds.
- 00:26:43But instead, we'll check the X position of the pipe,
- 00:26:47and delete it if it goes past a certain point.
- 00:26:49We'll borrow the bird to find out the X coordinate of the left of the screen.
- 00:26:54Looks about minus 45.
- 00:26:57In the pipe move script, we'll add a float for a deadzone.
- 00:27:01-45.
- 00:27:03And then a simple if statement - if transform.position.x is less than deadZone,
- 00:27:10then destroy the GameObject that holds this script.
- 00:27:15Run it in Unity and, bam, they're dead.
- 00:27:18Let's do one more thing, just as a teachable moment.
- 00:27:22Just before the destroy line, let's write Debug.Log, and in brackets, Pipe Deleted.
- 00:27:29Then, back in Unity, you'll see one other panel I skipped during the UI
- 00:27:34demo - it's a tab next to project, called console.
- 00:27:37Then when we run the game...
- 00:27:39every time a pipe is deleted, our message is sent to the console.
- 00:27:43This is a wonderfully useful way to debug our code, because
- 00:27:47we can find out exactly what the code is up to.
- 00:27:51Recap time!
- 00:27:52GameObjects can be turned into prefabs,
- 00:27:55by dragging them from the hierarchy, and dropping them into the project.
- 00:27:58You can then drag these into scenes - I use
- 00:28:01prefabs to create levels in my puzzle game, for example.
- 00:28:04Or you can make a spawner to instantiate new ones during the game.
- 00:28:08Timers are a great way to make code happen on a certain interval,
- 00:28:12but always use Time.deltaTime to keep things consistent across different computers.
- 00:28:17If statements can have an else gate, to make code fire if the condition is not met.
- 00:28:22You can also have else if, to make more complicated gates.
- 00:28:26And you should try to delete GameObjects if they're no longer needed, to free up memory.
- 00:28:32Okay, our next step is to keep track of the player's score,
- 00:28:35and show it to the player on the user interface.
- 00:28:38Then, we want the score to go up by one, every time the bird goes through the pipes.
- 00:28:43So, remember that a GameObject doesn't have to be a physical thing in your game
- 00:28:47world like a character or an enemy - it can be a completely invisible manager
- 00:28:52that's just keeping track of critical data like health, or time, or score.
- 00:28:56And then, we can make that information visible to the player, using a user interface.
- 00:29:01So let's start by making the UI.
- 00:29:03Like everything else, it's a GameObject in the hierarchy.
- 00:29:07This time go down to UI and pick text - which may be under legacy.
- 00:29:12We'll need to zoom really far out on the scene view to actually see the UI.
- 00:29:16To make sure the UI looks the same on every device, we'll pick this new canvas GameObject
- 00:29:21and set the canvas scaler component's UI scale to scale with screen size,
- 00:29:26and choose a sensible reference resolution - I'm gonna use 1080p again.
- 00:29:31We can then move our text around.
- 00:29:33You'll notice that UI has a rect transform, rather than a normal transform.
- 00:29:37The most important thing to note is that you don't really
- 00:29:40want to mess with scale of elements - instead, change the width and height.
- 00:29:46I'll then increase the font size and set the default text to 0.
- 00:29:50And then check it all looks nice on the game view.
- 00:29:53Okay, now we want to make a script that will store the player's score,
- 00:29:56and change the number on the UI to that score.
- 00:29:59We'll make a GameObject called Logic Manager.
- 00:30:03And we'll give it a script.
- 00:30:05This script is going to keep track of high level information like the player's score.
- 00:30:10And it will have various meta-level functions that we can run.
- 00:30:13So we'll delete start and update, we don't need them in this script.
- 00:30:17We can always add them back later if we change our mind.
- 00:30:19We want to store a number for the player's score.
- 00:30:22This time, we don't want a float because we only ever want round numbers.
- 00:30:25So let's do an int, instead.
- 00:30:28That's an integer.
- 00:30:29No decimal places.
- 00:30:30And because we want to update the UI text we just made we will, as always, have to make a reference.
- 00:30:36Except...
- 00:30:37text doesn't seem to be a thing?
- 00:30:40Ah, well.
- 00:30:42By default, a script only loads in the stuff you need for basic
- 00:30:45Unity functionality - but if we go up to the top and type using
- 00:30:49UnityEngine.UI;, we can now access more functionality - in this case, UI stuff.
- 00:30:56Now we can make a reference to text.
- 00:30:59We'll need to drag the text component into this field back in Unity.
- 00:31:02Because we're referencing a component on another GameObject - the text on the
- 00:31:07UI - the best way to do this is to just drag the whole GameObject into our slot.
- 00:31:11This will automatically find the text component for us.
- 00:31:14Handy.
- 00:31:16So now we want to make a function.
- 00:31:17And we'll call it addScore.
- 00:31:19And because we're going to run this function from other scripts, we'll set it to public void.
- 00:31:25This function needs to do two things.
- 00:31:27Add one to the player's score.
- 00:31:29Easy enough, we know how to do that now.
- 00:31:32And change the text on the UI to be this number.
- 00:31:37Oh, the text box is looking for a string - a sequences
- 00:31:41of characters - and our score is an integer.
- 00:31:44They look identical to us humans, but robots are fussy.
- 00:31:48Easily fixed, mind you, by adding .toString() to the game score.
- 00:31:52To make sure this works, let's give ourselves the power to run this function from Unity itself.
- 00:31:58All we need to do is write ContextMenu, and a name, above the function.
- 00:32:05Now, in Unity, while the game is running, hit the little dots on this script and pick the function.
- 00:32:10Nice! This sort of thing comes in real handy for testing.
- 00:32:15Okay, so now that we know the function runs,
- 00:32:17we specifically want to run it when the bird goes between the pipes.
- 00:32:20And the way to do this is collisions.
- 00:32:23Now if two objects have colliders, they will bash into each other - in fact, in our game,
- 00:32:28the bird will already crash into the pipes because we've added colliders to both.
- 00:32:32However - you can also have invisible colliders, called triggers.
- 00:32:35They don't create an actual collision,
- 00:32:37but they do let you know that two objects have touched - and you can run code at that moment.
- 00:32:42So we're going to put a trigger in between the pipes, so we know
- 00:32:45that the bird has passed through them. And then at that moment, we'll run addScore.
- 00:32:50Let's open up the prefab for the pipes.
- 00:32:53We'll make another GameObject called middle - and it needs a box collider.
- 00:32:57Let's make it this sort of shape.
- 00:32:59And this time we'll tick the box isTrigger.
- 00:33:02Finally, let's add a script to this new middle GameObject.
- 00:33:06Beneath Update, type ontrig, and the autocorrect will help us type out OnTriggerEnter2D.
- 00:33:13Just press tab to autofill.
- 00:33:15Anything in this function will run whenever an object first hits the trigger.
- 00:33:19There's also OnTriggerExit and OnTriggerStay, for future reference.
- 00:33:24And its in here, that we want to run the addscore function we wrote earlier...
- 00:33:28except.
- 00:33:28ah.
- 00:33:29once again, this script doesn't know about any other scripts in the game,
- 00:33:32until we make a reference to it.
- 00:33:34So we can write public LogicScript logic.
- 00:33:38But back in Unity, you'll quickly realise that you can't drag the script into this slot.
- 00:33:44You can't drag it from the project panel - we
- 00:33:46can only talk to an instance of a script that lives on a GameObject.
- 00:33:49But we also can't drag from the scene into the prefab.
- 00:33:53That's because the pipe doesn't exist in the scene yet, it will
- 00:33:57only exist when the game is running, and the spawner starts making pipes.
- 00:34:01So, instead, we'll need to fill this reference using code.
- 00:34:04and this needs to happen when the pipe first spawns.
- 00:34:08To do this, we'll need to help the code find the logic script.
- 00:34:12To do this, take the Game Logic object, and look at the top of the inspector: you'll see tags.
- 00:34:18From the drop down, choose add tag.
- 00:34:21Make a new tag called, say, Logic.
- 00:34:24And make sure you go back to the GameObject and actually set this new tag.
- 00:34:29You will forget to do this approximately eight
- 00:34:31thousand times in your Unity career, so look forward to that.
- 00:34:34Now, back in the PipeMiddleScript,
- 00:34:37under start we can write logic = GameObject.FindGameObjectWithTag("Logic").
- 00:34:46this will look for the first GameObject in the hierarchy with the tag, Logic.
- 00:34:51In our case, there will only ever be one in the scene,
- 00:34:54so we know it will always find the right one - but do be mindful of that.
- 00:34:57And then we can add .GetComponent();
- 00:35:03So, as soon as a new pipe spawns,
- 00:35:06it will look through the hierarchy to find a GameObject with the tag Logic.
- 00:35:10Then, it will look through that object's components to
- 00:35:13find a script of the class LogicScript.
- 00:35:15And if it finds one, it will put that in our reference slot.
- 00:35:19It has done the exact same thing as dragging and dropping the component
- 00:35:22in the Unity editor - except it has done it instantly, during run time.
- 00:35:27Excellent.
- 00:35:28So now, the pipe's middle script can find and talk to the logic script.
- 00:35:35And if we write logic.addScore, this will run that code.
- 00:35:40Back in Unity, hit play and if we did everything right,
- 00:35:43the score will go up by one when we pass between the pipes.
- 00:35:47Oh, and just for future proofing and whatnot,
- 00:35:50let's make sure that it was actually the bird that went through.
- 00:35:53We'll do this by putting the bird on a layer,
- 00:35:56and checking if the colliding object was on that layer.
- 00:35:59Go to the bird's GameObject and this time, instead of the tag, we'll change the bird's layer.
- 00:36:05Make a new one, remember to actually assign it, and make a note of the number.
- 00:36:10Now, on the pipe's middle script, we can add an if statement around addScore,
- 00:36:15and check if the collision that just happened was with a GameObject on the bird's layer.
- 00:36:22One more bit of future proofing, while we're on the subject.
- 00:36:25Go back to the Logic Script.
- 00:36:27And, let's take the AddScore function, and in these empty brackets we'll write int scoreToAdd.
- 00:36:34And then instead of adding one, we'll add scoreToAdd.
- 00:36:39Then in the pipe middle script, we can write a 1 in the brackets after addScore.
- 00:36:44Right now this does exactly the same thing as we had before.
- 00:36:48But, as you can surely guess,
- 00:36:50you could later add some other goal in the game that adds, say, 5 to your score.
- 00:36:54This allows us to make a function more versatile,
- 00:36:57as it can be used in different ways, from different places.
- 00:37:00Part of being a good programmer, I think,
- 00:37:03is making stuff less rigid, and keeping it open for future ideas.
- 00:37:07This makes it easier and faster to iterate on your designs.
- 00:37:12Right! Recap!
- 00:37:14UI is just another GameObject, but if we want to reference any of
- 00:37:18these components we'll need to add using UnityEngine.UI to the top of the script.
- 00:37:22GameObjects can be completely invisible things,
- 00:37:25merely there to keep track of rules, logic, score, and so on.
- 00:37:29If we want to a reference a component when one of the GameObjects is not in the scene,
- 00:37:34we'll need to find that component during run time.
- 00:37:36One way to do this is to use tags, findGameObject, and GetComponent.
- 00:37:42A public function can be run from another script, as long as you have a reference to that script.
- 00:37:47And we can even pass in variables when that function runs.
- 00:37:50And Collisions and triggers can be used to make stuff happen when two objects touch.
- 00:37:56Speaking of collisions, let's move on to the next step...
- 00:38:01The final step is to add a fail state.
- 00:38:03When the bird hits the pipes, the game is over.
- 00:38:06We'll do this by making a game over screen, and have it appear when the bird crashes into a pipe.
- 00:38:12The game over screen will have a button, which we can use to reset the game.
- 00:38:16First, let's make that game over screen.
- 00:38:19On the canvas GameObject, add a new empty one called game over screen.
- 00:38:25Then, in that parent, add a text for game over.
- 00:38:30And also a a button - that's also under legacy.
- 00:38:34Resize it.
- 00:38:35And change the text on the button - the text can be found as a child on the button itself.
- 00:38:43So back on the button GameObject, on the button component, you'll see this bit that says On Click.
- 00:38:50This is an event, and it allows us to call a public function on a GameObject.
- 00:38:55So let's make a function for restarting the level.
- 00:38:59We can put this code in the logic script, underneath our addScore function.
- 00:39:04You could make a seperate script if you want, but I think this is fine.
- 00:39:08Let's make another public function called restartGame,
- 00:39:12and in here we'll write code to restart the scene.
- 00:39:15Just like before with the UI, if we're managing scenes then
- 00:39:18we'll need to add a line the top - this time, using UnityEngine.SceneManagment.
- 00:39:23Now in our function, we'll call up the SceneManager and then, dot, LoadScene.
- 00:39:29This is looking for the name of a scene.
- 00:39:31Literally the filename.
- 00:39:33But because we want the current scene
- 00:39:34we can simply type SceneManager dot GetActiveScene, brackets, dot name.
- 00:39:40Close off all the brackets.
- 00:39:44Now back in Unity, add an event to this button.
- 00:39:48Then drag in the logic GameObject.
- 00:39:51and find the restartGame function.
- 00:39:57Give it a test and...
- 00:39:58nice.
- 00:39:59Every time we press the button, the game begins anew.
- 00:40:02Now obviously we don't want this to be on the screen all the time - just when we fail.
- 00:40:06So, we can just take the whole game over screen GameObject and disable it with this checkmark.
- 00:40:13Then we'll make it show up when the bird hits into the pipes.
- 00:40:16Let's write the function first.
- 00:40:18Again in the logic script, let's make a public function for gameOver.
- 00:40:22We'll need to make a reference to the game over screen GameObject.
- 00:40:27And fill it in Unity.
- 00:40:31And then we can simply type gameoverscreen.SetActive true in this function.
- 00:40:38So we want this function to trigger when the bird crashes into a pipe.
- 00:40:42Back on the bird script, let's reuse that code from before to
- 00:40:46access the logic script from the bird script.
- 00:40:49Yes, we could drag and drop the reference in Unity, but hey, we've written this code now.
- 00:40:53And then we're going to do a similar thing to the trigger code, but this time we'll use
- 00:40:58OnCollisionEnter2D, because the pipes are solid objects, and not set to be triggers.
- 00:41:03And when that collision occurs, trigger the game over script with logic.gameOver.
- 00:41:09Back in Unity...
- 00:41:10it kind of works, but we can still play in the game over screen.
- 00:41:15Not ideal.
- 00:41:16So, I've talked about a few key variable types, already.
- 00:41:20Floats and ints are numbers.
- 00:41:22And string is usually for text.
- 00:41:25The other important one is a bool, short for boolean.
- 00:41:29This is a really simple type that is either true, or false.
- 00:41:33On, or off.
- 00:41:34Yes, or no.
- 00:41:35It's a great way to simply check or change something's state.
- 00:41:38So let's have a bool called birdisalive, and make sure it starts as true.
- 00:41:44Then when the collision happens, we'll set birdisalive to false.
- 00:41:49And finally, we'll add an extra condition to our very first if statement.
- 00:41:53We're going to say if the space bar has just been pressed and...
- 00:41:57written with two ampersands...
- 00:41:59and birdisalive is equal to true.
- 00:42:02Actually, we don't need to add this equals equals true thing.
- 00:42:05It does the exact same thing without it.
- 00:42:07But, again, it's up to you - maybe it's easier to read this with the full code written out.
- 00:42:11Anyway, now, the bird won't flap if it's dead, which seems quite logical to me.
- 00:42:17The final thing to do is to build the game.
- 00:42:19Which is really easy. Pick file, build settings, and build.
- 00:42:23Pick a folder on your hard drive.
- 00:42:24And let Unity do its work.
- 00:42:26Then you can open this file to play your game! Amazing.
- 00:42:31In a very short period of time, we have made a pretty functional game.
- 00:42:35And what’s more, we’ve learned loads of fundamental lessons about Unity.
- 00:42:39We have made a character that moves in response to our input.
- 00:42:43We have spawned in new objects on a timer.
- 00:42:46We have created a UI that shows a score, and made that score tick up when conditions are met.
- 00:42:51And we've got the ability to get a game over, and start again.
- 00:42:54Now, I should note that there are different - and
- 00:42:57perhaps better ways to do pretty much everything in this tutorial.
- 00:43:01For example - I used Unity's old way of checking for inputs,
- 00:43:04and the company has since developed a much, much better Input System.
- 00:43:08But it's a lot more complicated to use - so this simple method is great for now,
- 00:43:12and you can look into the new input system later down the line, when you feel more confident.
- 00:43:17That's how it went for me.
- 00:43:19There's also TextMeshPro, which has replaced the old legacy UI
- 00:43:23system - so you'll want to graduate to that, at some point, as well.
- 00:43:27Anyway, these are lessons that will be useful, for making all sorts of games.
- 00:43:31But...
- 00:43:32the game isn't quite finished yet.
- 00:43:34There's still a few more things to figure out.
- 00:43:36Though, I don't want to tell you how to do everything.
- 00:43:39So i'm gonna give you some suggestions for how to finish up the game,
- 00:43:41but I want you to try and figure it out for yourself.
- 00:43:43So first of all, we need to have a game over if the bird goes off the screen.
- 00:43:48That shouldn't be too hard.
- 00:43:49There's also a bug where the score can go up, even after a game over.
- 00:43:53Try to solve that one too.
- 00:43:55We also want sound effects.
- 00:43:57I want you to add an Audio Source component to the logic manager.
- 00:44:00fill it with a sound effect file.
- 00:44:02Reference it on the script.
- 00:44:03And have it play when the score goes up.
- 00:44:05Then, i want you to play around with the particle system to make clouds appear in the game.
- 00:44:11Next, open the animation window, and add some flapping wings to the bird.
- 00:44:15Then i want you to add another scene to make a title screen,
- 00:44:19so the game doesn't immediately launch into the action.
- 00:44:21Here's a clue: you'll need to add this new scene to the build settings window.
- 00:44:25And finally, if you want a real challenge - use PlayerPrefs to
- 00:44:31save the player's high score to the hard drive, and draw that on the UI as well.
- 00:44:35For each one of these, you will probably want to Google the relevant terms, read the Unity docs,
- 00:44:40watch some quick tutorial videos, or ask for help in the comments down below.
- 00:44:45Next, you could expand on Flappy Bird.
- 00:44:47Get creative and add in ideas or designs that weren't there in the original iPhone game.
- 00:44:53For example, with a little messing around I gave the bird the ability
- 00:44:56to shoot out a missile, and then I added targets to the pipes.
- 00:45:00You've now got to hit the target with a missile to open a gap you can flap through.
- 00:45:04It's pretty cool, and adds a lot more depth to the simple game.
- 00:45:07In fact, I'd love to see how you might expand on the original game.
- 00:45:10If you make something interesting, record a bit of footage, pop it on YouTube,
- 00:45:15and drop a link in the comments.
- 00:45:17I might feature some of them in the future.
- 00:45:19And then, finally, I'd recommend that you take another simple game and try
- 00:45:22to remake it in Unity, like we just did right now.
- 00:45:25This is a great technique because you don't have to worry about art or design...
- 00:45:30just code.
- 00:45:31And the problem-solving puzzles you'll face are a perfect example of
- 00:45:36what real game development will be like.
- 00:45:38Good candidates for this include Pong, Space Invaders, Breakout, Pop the Lock, Angry Birds,
- 00:45:45various WarioWare mini games,
- 00:45:48and that dinosaur game that plays in Chrome if your internet's broken.
- 00:45:51So, in this video I wanted to teach
- 00:45:53you the fundamental concepts behind Unity - but, the rest is up to you.
- 00:45:58Luckily, I reckon this sort of hands-on, self-directed,
- 00:46:02learn from your mistakes style of learning is the most fun and effective way to make stuff stick.
- 00:46:08But we’ll see!
- 00:46:10Let me know how you got on in the comments down below.
- 00:46:13And if you want to watch my game development story - which
- 00:46:16is still ongoing, promise - then click here, for episode one of Developing.
- 00:46:22Thanks very much to my Patrons - they're the reason you don't
- 00:46:24get mid-roll ads in a looong video like this one.
- 00:46:28You can help support GMTK at Patreon.com.
- Unity
- Game Development
- Unity Tutorial
- Flappy Bird
- Unity Basics
- GameObjects
- UI Components
- Scripting
- Physics in Games
- Collision Detection