Hey what's up, welcome to Hooson In this video, you will be learning how to make a simple yet fun endless runner Where I'll guide you through the entire game creation process If you're just a beginner, and you want to make Your first game using Unity game engine This is the tutorial for you You'll learn how to make a simple player controller Spawning obstacles, how to display score Looping background, and lastly we'll bring the game to another level By adding music and particle effect After we've finished developing the game You'll learn how to publish your game on itch.io And you can ask your family and friends to try it out Impress them and get feedback so that you can improve as a game developer I encourage you guys to finish the entire game creation process And don't give up halfway through I promise you by the end of this tutorial You will have a huge confidence boost as a game developer Alright let's begin Firstly, we'll need to create a new game project Make sure you select the 2D template as we're making a 2D game And enter your project name I'm going to call my project "Stay Safe" As the theme of my 2D endless runner will be about avoiding the coronavirus If you can't think of a name for your game yet You can just name it 2D endless runner for now Alright let's create our game project Once it finishes loading, it's time to configure our game project Click on the file tab at the top of Unity, and then build settings In the build settings window, we want to change the platform to webGL Because we'll be publishing the game on itch.io And we want our players to be able to play on the web browser So let's select webGL and click on switch platform Once it finishes loading, close the build settings window and in your game panel Change the game resolution to be 16:9 You'll see your game now in landscape mode Next, we want to create a few folders in our game project so as to keep things organised We want to create a script folder A sprite folder And a prefab folder Next up I'm going to import my game assets that I drew using photoshop Into my sprite folder I'll leave a link in the description below for you to download it But I would highly recommend you guys to create your own game assets I've a tutorial on 2D character creation and animation which you can check it out For my game assets, the player character is riding on a syringe like looking plane The obstacles will be the coronavirus And the background will be a very simple background Alright it's time to do our player controller Let's drag the player character into the game And I want to rename it to "Player Sprite" Let's create an empty game object called "Player" Reset it's transform component And I want to make the "Player" game object to be the parent of the "Player Sprite" So simply drag the "Player Sprite" into the "Player" game object The "Player" game object will act as a root for our character Any components such as scripts or Rigidbody2D will be added to it Click on the "Player" game object, let's resize it as it's too big right now And we want to add a Rigidbody2D component Adding a Rigidbody2D puts this game object under the control of the physics engine This way, we'll be able to control our character from scripts Freeze the z rotation so that our character doesn't spin And change the gravity scale to 0 The reason why we need to change the gravity scale to 0 Is because we want the player to stay in the air Now let's create a new C# script in our script folder and we'll name it "Player" Alright let's open up the "Player" script Firstly, we'll create a public float variable called "playerSpeed" This variable will dictate how fast our player will be moving Now let's create a private Rigidbody2D variable called "rb" We need this variable because we will be using Very simple physics to move our player Lastly, we'll create a private vector2 called "playerDirection" This variable will be used to process our player's input In the "Start" function, we want to fetch the Rigidbody2D From our "Player" game object Next, we want to create a "FixedUpdate" function below our "Update" function The difference between "Update" and "FixedUpdate" Is that the "Update" function is called once per frame So almost anything that needs to be adjusted regularly happens here Example like timers and detection of inputs are usually done in the "Update" function On the other hand, "FixedUpdate" is used for being in step with the physics engine So anything that needs to be applied to the Rigidbody should happen in "FixedUpdate" In the "Update" function, let's create a float called "directionY" And it'll be equals to "Input.GetAxisRaw("vertical")" We'll be using the "directionY" variable to detect which key the user is pressing So if the user is pressing on the up arrow key The "directionY" variable will be equals to 1 And if the user is pressing on the down arrow key The "directionY" variable will be equals to -1 So now, "playerDirection" will be equals to "new Vector2" And we will give a value of 0 for the x coordinate As we won't be moving our player on the x axis We will put the "directionY" variable for the y coordinate And we'll add ".normalized" at the end to ensure our player's movement being consistent Like I said earlier, we're doing all these in the "Update" function Because detection of inputs are usually done in the "Update" Function Now in the "FixedUpdate" function "rb.velocity = new Vector2" We'll give a value of 0 for the x coordinate And for the y coordinate "playerDirection.y * playerSpeed" Like what I've said earlier Anything that needs to be applied to the Rigidbody should happen in "FixedUpdate" Save the script and let's head back to Unity Attach the "Player" script to the "Player" game object And let's give our player speed a value Alright let's give it a try Perfect we've completed our player controller Now it's time to do our camera movement We want the camera to be continuously moving forward After that, we'll attach the "Player" game object To be a child of the camera so that it'll look like the player is moving forward But in reality, the player is just standing still and the only object moving is the camera So let's create a new C# script called "CameraMovement", and let's open it up Go ahead and delete the "Start" function as we won't be using it And we want to create a public float called "cameraSpeed" This variable will dictate how fast our camera will be moving In the "Update" function We want to continuously change the x position of the camera So "transform.position += new Vector3" for the x coordinate, "cameraSpeed * Time.deltaTime" and for the y and z coordinate We will just give it a value of 0 as we don't want to change any of this position Save the script and let's head back to Unity Create a new game object and we'll name it "Game Manager" Reset it's transform component and attach the "CameraMovement" script to it Now we want to make the "Main Camera" and "Player" game object to be children of the "Game Manager" So let's select them and drag it into the "Game Manager" object Let's give our camera speed a value and give it a try Alright you can see the "Player" game object is constantly moving forward Perfect, we've completed our camera movement Now it's time to add our looping background into the game Create a new quad and we'll name this "Background" Reset it's transform component And we can remove the mesh collider as we won't be using it Select the background sprite Change the wrap mode to repeat And click on apply to save the changes Next, select the "Background" game object And we want to drag our background sprite into it In the shader option, we want to set it to unlit/texture Let's scale up our background so that it covers the entire screen Now we want our background to be a child of the "Game Manager" So simply drag it into the "Game Manager" object Alright let's create a new C# script called "LoopingBackground" Let's open it up Create a public float called "backgroundSpeed" This variable will dictate how fast our background will be moving And a public renderer called "backgroundRenderer" Go ahead the "Start" function as we won't be using it And in the "Update" function "backgroundRenderer.material.mainTextureOffset" "+= new Vector2" "backgroundSpeed * Time.deltaTime" for the x coordinate And a value of 0 for the y coordinate Save the script and head back to Unity Attach the "LoopingBackground" script to the "Background" game object I'll give a value of 1 for the background speed And assign the mesh renderer to the "backgroundRenderer" variable Let's try it out Perfect, we've created our looping background Now it's time to spawn our obstacles Select your obstacle in your game project, and drag it into the game I'm going to rename it to "Obstacle Sprite" And similar to what I've done for the player We need to create a new game object called "Obstacle" Reset it's transform component And make the "Obstacle Sprite" the child of the "Obstacle" game object I'm going to resize it as it's too big right now And then we want to make our obstacle into a prefab So simply select the "Obstacle" game object and drag it into our game project So what is a prefab Prefabs are a special type of component that allows full configured game objects To be saved in the project for reuse So if you select the "Obstacle" prefab that you've created You can see that it saves all the changes you've made to the object And if I were to drag it back into the game You can see that it is still the same, and I do not have to reconfigure it all over again Alright, let's delete the obstacles in our game for now Create a new C# script called "SpawnObstacles" And let's open it up Firstly, create a public game object called "Obstacle" This variable will contain the obstacle that we want to spawn Next, create 4 public float variables called "maxX" "minX", "maxY" and "minY" We need this 4 variables because we want our obstacles to spawn Within the maximum and minimum range for each axis Create another public float variable called "timeBetweenSpawn" This will dictate how much time is taken till the next obstacle appear And lastly, a private float called "spawnTime" We can delete the "Start" function as we won't be using it And below the "Update" function Let's create a new function called "Spawn" In the spawn function create a float called "randomX" and it'll be equals to "Random.Range" And for the range, it'll be between "minX" and "maxX" The reason why we're doing this Is because we do not want our obstacles to always spawn on the same position Let's do the same for the y axis Create a float called "randomY" And it'll be equals to "Random.Range" And for the range, it'll be between "minY" and "maxY" Now we want to instantiate the obstacle The position we want it to instantiate at will be "transform.position" "+ new Vector3" "randomX" for the x coordinate "randomY" for the Y coordinate And 0 for the z coordinate as we won't be using it And lastly, the rotation will be "transform.rotation" In the "Update" function We'll first check if the time passed is greater than the spawn time If it's greater, we'll call the "Spawn" function And then set "spawnTime" to be equals to "Time.time + timeBetweenSpawn" Save the script and head back to Unity Let's create a new game object called "Spawn Point" Reset it's transform component And let's attach the "SpawnObstacles" script to the "Spawn Point" game object Drag your obstacle prefab and add it into the obstacle variable For the "minX" and "maxX" value It's entirely up to you how far apart you want your obstacles to be For me, I'll just give a value of 3.5 for the "maxX" And a value of 3 for the "minX" For the "maxY" and "minY" value Drag your obstacle prefab into the game again Move it all the way up and see what the highest y value is Make sure the obstacle isn't getting cut off by the camera Alright, my highest y value will be 4 Let's move all the way down to see what the lowest y value My lowest y value is around -4 Now your values don't have to be the same as mine if you're using your own obstacle asset Because the size of your obstacles might be different from mine But if you're using my game asset You can just follow my values We can delete the obstacle prefab And lastly, I'll give the "timeBetweenSpawn" a value of 0.6 The values of these variables are entirely up to you to decide You can try many different values until you get the one you feel is best for your game Next up, we'll drag the "Spawn Point" out of the camera Reason being, we do not want to spawn the obstacle right in front of our player We want it somewhere out of the player's sight Now we want our obstacle to move along with the camera So select the "Spawn Point" game object and make it a child of the "Game Manager" object Lastly, let's move our player character back a little Alright let's try it out Perfect, we've managed to spawn our obstacles Right now, we need to create some box colliders to prevent our player from moving out of the screen Now let's create a new game object called "Borders" And reset it's transform component Create another game object and let's name this "Top Border" Reset it's transform component as well And we want to make this the child of the "Borders" game object With the "Top Border" object selected Let's add a box collider 2D component Resize it, and make sure it covers the entire screen Now let's move it up so that it's right above the screen Now we need 1 at the bottom of the screen as well So duplicate the "Top Border" game object and rename it to "Bottom Border" And we'll place it at the bottom of the screen Now our "Player" game object needs a box collider as well So select the "Player" and then add a box collider 2D component Click on the edit collider icon And let's resize it so that it fits the entire player character Lastly, we need to move our "Borders" game object To be the child of the "Game Manager" object This is so that it'll move along with the camera Let's give it a try Nice, now the player won't move out of the screen anymore Now we need to destroy the obstacles that are already out of the screen So let's duplicate the "Bottom Border" And rename it to "Side Border" Change the y position to 0 so that it's back at the centre And give the z rotation a value of 90 So that our "Side Border" is vertical Let's place it somewhere behind Make sure it's not too near to the screen Now we need to create a new tag for our borders Select the "Borders" game object and in the inspector tab You can see a tag section right above the transform component Click on it, and you'll be able to see a list of options All the way at the bottom, click on add tag Under the tag section, click on the plus icon Name our new tag "Border" and click save Select the "Borders" game object again and we want to change it's tag to "Border" Do the same for the top Bottom and side border Alright next up Let's click on our obstacle prefab and on the inspector tab Click on the open prefab button Now we need to add a box collider for our obstacle as well For me, my obstacle is in a shape of a circle So I'll use the circle collider 2D instead If your obstacle is more of a rectangle shape You should be using the box collider 2D Let's click on the edit collider icon and change the size of our collider Make sure it covers the entire obstacle And lastly Check the is trigger option Once you're done, create a new C# script And let's name it obstacle Let's open up the obstacle script Go ahead and delete the "Update" function as we won't be using it And we want to create a new private function called "OnTriggerEnter2D" if the "(collision.tag == "Border")" We want to destroy this "Obstacle" game object Which means whenever the obstacle touches an object With the "Border" tag It will get destroyed Save the script and head back to Unity Select the obstacle prefab and add the "Obstacle" script to it Lastly, we need to add a Rigidbody2D component for our obstacle object as well Freeze the z rotation and change the gravity scale to 0 The reason why we're doing this is because we need the Rigidbody component In order to receive trigger events in the "Obstacle"script Alright now it's time to give it a try Perfect, you can see that the obstacle gets destroyed whenever it touches the "Side Border" Now we need to show the game over panel whenever the player touches the obstacle So let's create a new panel and rename it to "Game Over Panel" Let's change it to a darker colour Select the "Canvas" game object And we want to change the UI scale mode to scale with screen size Reason being, we want our UI to scale with the size of the screen So the x value will be 1600 And the y value will be 900 Create a new image under the "Game Over Panel" object And let's name it to "Wooden Panel" Drag the wooden panel sprite into the source image and let's scale it up Now let's create a new text under the "Game Over Panel" as well And we'll name it "Game Over Text" Change the text to game over Change the alignment to centre Resize the text Increase the font size Let's change it to a darker colour And we'll just place it at the top Now we need a restart button to restart the game So create a new button under the "Game Over Panel" as well And we'll name it "Restart Button" I'm going to drag my own mask button sprite into the source image Resize the button Change the text to restart Change it to a darker colour And increase the font size Select the "Game Over Panel" and let's disable it By simply unchecking the box right below the inspector window Alright let's open up our "Obstacle" script again Create a private game object called "player" And in the "Start" function We want to set the "player" variable to be equals to "GameObject.FindGameObjectWithTag("Player")" In the "OnTriggerEnter2D" function We will need to check if the player touches the obstacle So else if "(collision.tag == "Player")" We will destroy the "player.gameObject" Save the script and head back to Unity Create another C# script called "GameOver" and let's open it up Create a public game object called "gameOverPanel" This variable will be for us to assign the "Game Over Panel" We can delete the "Start" function as we won't be using it And in the "Update" function "if(GameObject.FindGameObjectWithTag("Player") == null)" We will set the game over panel to be active Now let's create a public "Restart" function below the "Update" function So this function will be called when user clicks on the restart button At the top, we want to add the "UnityEngine.SceneManagement" namespace Head back to the "Restart" function And we want to reload the scene when user clicks on the restart button Save the script and head back to Unity Attach the "Game Over" script to the "Game Manager" object And assign the "Game Over Panel" to it Select the "Restart Button" and we want to call the "Restart" function When users click on the button Lastly, select the "Player" game object and change the tag to "Player" Alright let's try it out Perfect, we've completed our game over function And the restart button is working as well Now it's time to add a score for our endless runner There are many different ways whereby you can count scores But for this endless runner The score will be based on how long the player can survive in the game So the score will keep adding up every second Create a new text under canvas and let's name it "Score Text" Change the text to 0 Change the alignment to the centre Resize the text Increase the font size Let's change it to a darker colour and we'll place it at the top Now let's create a new C# script called "ScoreManager" And let's open it up At the top, we want to add the "UnityEngine.UI" namespace Now let's create a public text variable called "scoreText" This variable will be for us to display the player's score Create a private float called "score" This variable will be for us to store the player's score We can delete the "Start" function as we won't be using it And in the "Update" function We need to first check if the player is still alive Because we do not want to continue adding score once the player is dead So "if(GameObject.FindGameObjectWithTag("Player") != null)" We will add a value of 1 to the "score" variable every second And we want to set the "scoreText.text = ((int)score).ToString()" As we do not want the decimal place And convert it to a string Save the script and head back to Unity Attach the "ScoreManager" script to the "Score Text" game object And assign the score text to it Alright let's try it out Perfect, we've created a score system for our game Now let's add our background music into the game I'll leave a link in the description below for the music I'm using Create a new C# script called "BackgroundMusic" And let's open it up We can delete the "Start" and "Update" function as we won't be using it And we want to add the "Awake" function instead Firstly, we'll create a private static variable of type "BackgroundMusic" And call it "backgroundMusic" In the "Awake" function We'll check if "backgroundMusic == null" If it is, this will be the background music And we do not want to destroy it Else, we'll destroy this game object Save the script and head back to Unity Create an empty game object and rename it to "Background Music" Reset it's transform component Let's add an audio source component And add our "BackgroundMusic" script to it Next, we'll attach the music onto the audio clip And lastly, check the loop option so that our music keeps repeating Alright let's give it a try Perfect, we've added our background music Now let's add some particle effect to make the game even better Create a new particle system And reset it's transform component We have our own particle sprite which we want to use So expand the renderer section Let's change the material to sprite default Check the texture sheet animation and expand it We want to change the mode from grid to sprites Now let's assign our particle sprite to it Now you should see your own particle sprite appearing Expand on the shape section and i want to change the shape to cone Now it's totally up to you on how you want your particle effects to be Play around with the different options that are available You can even change the rotation to make it appear differently Now I want my particle to be coming from the right So I'll change the y rotation to -90 Now the particle is coming from my right I'm going to increase the radius to cover the entire screen And then shift my particle system to the right As I do not want it to appear in my player's sight In the particle system section I'm going to scale down my particle as it's too big right now So we can change it by reducing the value of the start size Now head over to the start colour And I want to change the option to random between 2 colours This allows us to choose between 2 colours for our particles It's entirely up to you for the colours of your particles I'm going to just choose 2 random colours Now let's move over to the start speed And this value will determine how fast your particle will be moving So we could change the option to random between 2 constant And this will allow our particles to have different speed You can see that some are moving slower and some faster You can play around with the other options like start lifetime Which determines the lifetime of the particles And also the start rotation which changes the particle's rotation One tip in making great particle effect is to add randomness to your particles That is why I always like to use the random between 2 constant option So I'm going to add randomness to my particles on the start lifetime Start speed And start colour Lastly, I'm going to check the prewarm option So that my particles will be on my screen when I start the game Now if you want to produce more particles Head over to the emission section And you can change the rate over time value So a higher value will produce more particles I highly recommend you guys to play around with the different settings You have for the particle system You don't have to follow exactly like mine Once you're done Make the "Particle System" a child of the "Game Manager" object So that it moves along with the camera Alright let's give it a try Perfect, we've completed our particle effect Congratulations on completing this endless runner tutorial Now it's time to publish your game on itch.io And you can show it to your family and friends Head over to the file tab at the top of Unity and open build settings Before we build our game We need to make some minor changes to our player settings So let's click on the player settings button You can change the company name to your own name Or you can even put your company name if you have one Product name will be the name of your game Head over to the resolution and presentation section Change the canvas width value to 1600 The canvas height value to 900 And we want to check the run in background option Head over to the publishing setting section And we want to change the compression format to disabled Close the project settings window and it's time to build our project Create a new folder and you can name the folder the name of your game And we want to build our game into this folder Once it finishes loading, we want to zip the folder and let's head over to itch.io Log in to your itch.io account And we want to click on the drop down box and select upload new project Add a title and description for your game For the classification, it'll be games Kind of project will be HTML For the pricing it's entirely up to you if you want to make it free or paid Now we want to upload the zipped folder And we want to check this file will be played in the browser option Change the width value to 1600 and height to 900 Check the fullscreen button and enable scrollbars option Now you can slowly fill in the rest of the details But one last important thing to take note Make sure you set the game to public In the visibility and access section so that others will be able to play your game I want to congratulate you on completing this tutorial I know it's not easy if this is your first time making a game But I hope that you learned something from this tutorial You can add more features to your 2D endless runner Like making a main menu page Or even adding an on/off sound button for your players I would recommend you guys to add even more features So as to make your game even better You can leave a link to your game on the comment section down below So that others can play your game as well Don't forget to click on the like and subscribe button if you enjoyed this video And I'll catch you guys in the next one Peace