How to make Pong in Unity (Complete Tutorial) πŸ“πŸ’₯

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello my name is adam i also go by zigarus in this video we are going to learn how to recreate the game pong in unity this is the second video in my series of recreating old classic arcade games specifically in this video we're going to learn a lot about physics in unity instead of manually changing the positions of our game objects and whatnot we're going to simulate everything through unity's physics engine this means our code is actually going to be pretty minimal and you'd be surprised at how much we can accomplish just through the built-in physics that uni provides to us we are also going to explore some ways of implementing very simple artificial intelligence as the player you will be facing off against a computer and so we will learn how we can implement the computer paddle using some ai techniques to begin we need to create a new unity project if you open unity hub we can go ahead and create a new one using this blue button in the top right and you actually can select the drop down here to choose a specific version of unity you want to use i'm going to be using unity 2020.2.1 for this tutorial but it really shouldn't matter too much once you select that we can actually choose a template that we will work off of in this case we're going to choose the 2d template this is going to be a 2d version of pong what that is going to do is install a number of useful 2d packages that you might utilize when making a 2d game you can simply name this pong or whatever you would like choose wherever you would like to save the project and go ahead and click create from here it might take a couple minutes to initialize so give it a few minutes and once this is done we can go ahead and jump in all right the first thing we're going to want to do is set up our entire scene so that means creating all the game objects we're going to need and adding various components to those game objects so we can add interactions later on by default unity provides us a sample scene i'm going to first just rename this to pong and then in the left here is our hierarchy where we can see all the game objects that exist in this scene by default uni provides us a camera let's start by modifying this and let's change the background color to black this is preference so you feel free to set it to whatever you like but for pong i want to just have the background be pure black and that's it there's nothing else we need to change on our camera next let's go ahead and create a ball game object we can right click in our hierarchy and we can either select create empty which will create a new game object with no components on it or in this case it's easier to select 2d object sprites and we can do square this will create us a brand new game object here which i'm going to call ball and it's going to add a sprite renderer automatically to it let me re set the transform here we can click the three dot menu choose reset it's going to reposition our ball to the center it just changes all these values to their defaults and our ball is a little bit too big so we're going to change the scale on this to 0.25 that feels more appropriate [Music] next let's add a couple new objects or components to this object so first we're going to want a rigid body 2d it's a 2d game so we want the 2d version of our rigid body and a rigid body is essentially going to turn this object into a physics object which means the physics engine will actually simulate physics on this object so you can see there are various properties like mass and gravity for example for our ball we do not want gravity otherwise um the ball is just going to fall off the screen which is what we don't want so by setting that to zero it's essentially going to make gravity not affect this object we also want to change our angular drag to zero as well angular drag has to do with the rotation of the ball and in this case i don't actually want the ball to rotate at all it's just going to move around there's no rotation i don't want the ball to spin or anything like that but feel free to play around with that if you think that would be an interesting mechanic for your game and i can even go into constraints here and i can freeze the rotation just to really guarantee that this object is not rotating that's it for now on our rigid body but maybe later on we could play around with for example the mass if we want to make the game feel a little bit different maybe make the ball feel a little bit lighter or heavier but for now we'll keep it the next object or not object but component we want to add to our ball object is a box collider and once again we want the 2d version so box collider 2d we actually don't need to change any properties on this but essentially this is just going to allow um a box collider is defining the shape of the collision um area of this object if we go to our scene view we can zoom in here and it might be hard to see but let me change the size just to show you oh let me go ahead and look at our gizmos there you can see this green outline here which is showing the basically the collision area of this object now i just want to keep the size to one all their default values so it exactly aligns with our ball there and that's it so that is it for our ball game object okay next let's create our paddles we can once again right click in our hierarchy let's go to 2d object sprites and select square again let me reset this transform back to other defaults and let's start by changing the size of this paddle actually let me rename it first let's call it paddle or i'll call it player paddle we're also going to have a computer paddle let's adjust the scale um i don't want it to be as wide so maybe 0.2 and let's make it a little bit taller so maybe 1.5 instead that looks good and let's change its position to be on the left side of the screen negative eight that feels perfect i like to have it a little bit offset from the edge of the screen and that looks good that's our player paddle we also need to essentially add the same components to this as we did for the ball so we're going to want to add our rigid body 2d and for our rigid body 2d we also want to get rid of angular drag because we don't want our paddles to rotate so we're going to also freeze the rotation and in this case the paddle's only going to move up and down right so we can actually freeze the x position so it can't move left or right it will only move up and down from here we're probably going to want to adjust the mass and drag which is going to change how the paddle feels as you start moving it we'll probably adjust these later on to maybe make the paddle feel a little bit lighter or heavier but i think some initial values is to decrease the mass a little bit because that's going to the a greater mass there is going to make it feel a little bit heavier which is essentially going to make the paddle a lot slower i kind of want my pedals to be a slightly faster and then for our drag here if we have our drag at zero our paddle is never going to come to a stop we actually want to set this let's say to maybe two that way as you move up eventually our paddle will decelerate back to a still position and that looks good for our rigid body we also want to add a box collider 2d don't need to change any of the properties having the size as one will once again um perfectly outline our paddle which is exactly what we want so that looks good so we have our paddler and now we can actually just right click this and select duplicate and let's just rename this one to computer paddle and let's just reposition this to positive eight instead of negative eight and now we have our other paddle on the right side of the screen and that looks good so there are our paddles okay next we need to add some walls that surround our entire game area that way the ball stays within those bounds so let's go ahead and once again let's right click in our heart key and in this case we don't need a sprite or anything i just basically want invisible walls that the ball will bounce off of i'm just going to select create empty this time let's go ahead and reset the position here everything to zero and let's just call this let's start with let's say our top wall top wall and all we need to do is add a box collider to this box oops box glider 2d once again this is just going to be an invisible collision zone um sort of at the edges of all of the edges of our entire game area here so the ball will bounce off of it so we just need a box glider don't need any sprite render or anything like that and all we need to basically do is reposition this appropriately you can see here in our scene view this white outline is the outline of what our camera sees which in the game view is of course this entire black area so we want to position our wall here perfectly on the edge so let's say 5.5 looks like is the math and let's change its scale the scale here doesn't matter too much let's just set it to 20 it's okay if it goes past or exceeds the edge there it just needs to at least be as big as that entire area and that looks good now we can duplicate this we'll call this one bottom wall and let's change this to negative 5.5 and there we go so now we have our top and bottom walls let's go ahead and also add our left and right walls let's go ahead and once again you know i can duplicate this let's duplicate we'll call it say left wall now in this case i need to change the scale not in the x but in the y so let's set that back to 1 and instead scale it in the y let's also change the y position let's move it over put this right on the edge um negative nine point four yeah in this case it's not going to um it's not going to be some like even number like 0.5 but point four perfect makes it perfectly on the edge why let's set it to ten there that lines up quite perfectly i'll actually just in case make it a little bit bigger once again it doesn't actually matter um yeah that feels good so lars there is our left wall and we can just duplicate this and call this one right wall and let's change this from negative positive and there goes our right wall so let's select all four of these there we go now we can see all four of our walls which is perfect the final thing we might want to do for our scene is add a line going right down the middle this definitely is not required but i feel like it adds a lot of character so let's go ahead and add that we can once again create a new game object this one will start as an empty one i'm just going to call this a i'm just going to call it line reset the position once again and we can add a component called line renderer there's a few properties we need to change on this so for one our positions here we need to change let's say the y so we want it it's going to draw a line between a few points here so in this case i have two points and let's say the y is negative 10 and i know positive 10. so there's our line obviously it doesn't look um exactly how we want it yet let's go ahead and change the width here let's say 0.1 now it feels pretty good and what else we want the texture mode to be tile that'll become important in a minute once we add um our texture and i'll show you what that looks like and let's see everything else is pretty much fine i guess we can turn off lighting and shadows and stuff we don't need any of that um but that looks good the big thing here is we need to create a material to assign to this so let's go ahead and do that in our project panel on the bottom i'm going to create well first i'm going to create a folder to keep all of my different types of assets organized so let's create a folder called materials in here i'm going to create a new material so right click create material i'm just going to call this line and we want to change the shader type from standard to unlit transparent and then we're going to need to add a texture to this by default well so first let me show you what this looks like just as just with this material without any more changes we can go back to our line renderer here and we can drag this material into this slot here under materials you can see our line there which actually looks fine i want to have more of a dashed line though to make it look a little bit better and one way we can do this is by assigning a texture here um i'm gonna pull in a texture that i already have created and let me explain what it does um and let me put this in a new folder so let me call this or i'll actually call this sprites let me move that over here you can see it's called half square because basically what it is it's just a square but it only fills half of the actual area of um of the sprite the the rest of the area is just transparent so essentially it's just creating some padding around the the actual you know the actual square and then the outer edge and so now if i assign well actually i need to change a few properties on this texture for one i want it to repeat because it's essentially just a line the line's just going to keep repeating this texture over and over again and i'm going to change the filter mode to point um which is you often use for like pixel graphics otherwise it's going to make the edges kind of blurry which i don't want in this case and let's go ahead and assign this to our material so i can select my material i can drag this over and look at that so in here you can get a better visual of what the actual sprite looks like like i said there's the white square in the middle with just some extra transparent padding on the edges which effectively gives us that you know the spacing in between our lines to create that like dashed line effect i will include this texture here in um the pro all the project files for this will be available on github and this texture will be available if you want to use it you can also create one yourself if you have some programs to do so but also you know you don't have to do a dashed line like i did here you can do a solid line in a solid line if you would like it's up to you but there that actually looks pretty good we have our entire scene setup is actually complete now we have our two paddles we have our ball we have the line going down the middle just to add some polish and what you don't see and will be important are four walls surrounding our edge so the ball will bounce off of those next let's start programming our player paddle so let's first create a folder to contain all of our scripts that we will be adding to this project and let's start by creating a couple scripts here so first i'm going to create a script just called paddle and if you didn't catch that you can right click um in the project panel create and c-sharp script we have one called paddle let's go ahead and add another called player paddle and let's go ahead and actually create another one called computer paddle although we're not going to write the code for that quite yet so we have paddle player paddle and computer paddle essentially if we open up one of these scripts unity provides us a you know a little bit by default all of our class is inherent from mono behavior and there's a couple functions here that they provide that are just very commonly used i actually like to delete everything and just kind of start fresh but here we have our paddle and then we're going to focus on player paddle now you might wonder okay why do we have two different scripts here essentially you know if we think about our player paddle and our computer panel the way in which they're going to behave will be different however there are definitely still some similarities between them at the very least there are some shared or not shared but similar variables that that will both contain so our player paddle is going to inherit from paddle and our computer paddle will also inherit from paddle this way we can add any shared any code or logic or variables that should sort of be similar or are the same between both our player and computer we can add in this class but at the same time each respective paddle has their own script that we can add you know paddle specific behavior to so for now let's ignore the computer paddle and let's start by adding a couple things or one thing really to our base paddle class here and that is we need to establish a reference to the rigid body that exists on the same object as this paddle if we take a look in our scene here and let's select our player paddle right we we created a rigidbody and and also while we're at where while we're looking at this we can add this script to this game object by dragging it into the empty space you can also drag it onto the object directly through the hierarchy there and so we need to get a reference to the rigid body that exists on this object let me go back to editing this so let's start by creating a variable called rigidbody2d which will store a reference to that rigid body and in this case i actually don't oh and i meant to add this to the base class here i actually don't want this to be private because then only this class can access this and none of the other classes would be able to so if i actually change this to be protected that means this class can access this variable but also my player paddle and computer paddle can access this and let's go ahead and add a awake function here this is a function that unity provides automatically or unity calls automatically on your script it only gets called one time in the entire life cycle of this game object or of the script and it's essentially used to do just any maybe you know initialization type work so let's say for example we can say rigidbody equals and we'll use a function unity provides called git component and the component i want to get or the type of it is rigidbody2d same as our variable here and we just call that function what that does is unity is going to search on the same object that that script is attached to so in this case our script is attached to our player paddle game object going to look on the same object and see if there is a component of that type we specified which was rigidbody2d and if there is it will return that to us and then we can assign that into our variable here which is exactly what we want so that's how we can establish a reference to our rigidbody that's it for now on this paddle we'll definitely revisit this later on though all right next we want to actually add some specific logic to our player paddle which is essentially going to look for or check for player input and then based on that player input we'll actually move the paddle so let's start by adding um a variable called and we'll have a vector 2 and this will be called direction so this variable will keep track of the paddle's direction and let's add a function called update this is a function that unity also calls automatically and uni calls this function every single frame the game is running so it's commonly used to check for importer or various um various logic that needs to execute every single frame of the game and here we can say if input which is a class unit provides and we say get key and then here we can specify the key we want to check for let's say w i'm going to use wasd um and i can also say i'll check for multiple so i'll say get key key code dot up arrow so you can use either was or d or your arrow keys it's up to you if that's the case we will set our direction to be vector2.up now if it's none of those well let's check for if the key is keycode.s or input.getkey code dot down arrow and if it's that we will set our direction to be down vector two dot down if it's neither or none of those well then we can set our direction to be 0 vector 2.0 which indicates we're not moving and that's it for checking player input and our update function next let's add another function called fixed update so the difference between these two is that as i mentioned earlier update is called every single frame the game is running fixed update rather is called at a fixed time interval so fixed update is very much associated with physics um if your if the physics code was executed or was based upon the frame rate of your game then you're going to get very inconsistent behaviors and so physics needs to simulate be simulated at a fixed time interval which is exactly what fixed update is so typically you'll do all a lot of physics related code in here and once again our rigid body essentially turns this object into a physics object so based on our direction we can apply a force to the rigid body to make the paddle move we are not going to just manually change the position of the pedal this entire game we're going to do everything through the physics engine so first i only want to apply this force if we're actually moving in a direction so one way i can check for this is to see um or look at square magnitude and as long as the square magnitude is um greater than zero you know that indicates that we are moving and i actually should probably say does not equal zero um because if it's positive or negative that's actually fine that effectively i don't know that it ever would be negative but either way let's say as long as it's not zero that implies we're moving in some direction and in this if this is the case we can access our rigid body which once again we declared here in our base class rigidbody.addforce and i'm going to say direction times well we haven't added yet but i want to add some kind of scalar to this which is going to be speed so let's actually declare a variable called speed and we'll do this in the base class as well because this is going to be another variable that both our player paddle is going to utilize and our computer paddle in this case we're going to make this one public and i'll show you why in a minute and let's give it let's say a default of um i mean i don't know it's kind of arbitrary but maybe 10 let's just try 10 for now um and cool that looks good and then let's quickly finish this code so direction time speed gives us our force here let me show you what the speed does in the editor by making it public you can see in our script here now our speed shows up and i can actually modify this directly in the editor which is cool so allow me to tweak this as needed if i feel like maybe tends to do too much i can decrease it i can just do it right in here without having to change any code but now that that is um all written let's actually test this out click our play button let's go ahead and yeah notice how our player paddle there so i'm pressing up right now and then i'm falling i'm pressing up right now and then i'm falling it looks like gravity is um affecting us which we actually don't want so that's something we forgot to turn off earlier our gravity scale here on our rigid body just set that to zero and now gravity will no longer affect that you notice too the computer paddle actually moved as well not because of any code we wrote but because gravity as well you'll see that it just immediately falls and hey one thing you'll notice it's not going past the edge of our screen because we have those invisible walls that it's colliding with preventing it from um from going past but let's turn off gravity for our computer panel as well let's run this one more time so now yeah i can press up and down notice and then if i let go of my keys it will actually come to a stop and that's because of our linear drag here if i were to change this let's say to zero and i press down i'm not pressing my down button anymore i'm completely hands off and it's still moving i pressed up and it's going to keep going and going forever because there's no drag to actually slow down the object that's why we want to make sure this is maybe something like two you can play around with these two until it feels right but but this actually feels really good to me um the mass here i think default mass is one when we first set up our scene we switch this to 0.5 just to make our paddle feel a little bit lighter kind of allow us to you know kind of move faster in a sense yeah this feels really good to me it feels pretty responsive i like the speed everything's good so there you go that's our um player paddle it only took a few lines of code next we can start scripting our ball let's go ahead and add a new script here called ball let's go ahead and add this script to our all game object so i'm dragging this onto our object there and you should see it show up let's go ahead and edit this let's get rid of everything by default just my preference there and essentially there's a couple things we want to do one we just need to give the ball an initial starting force to kind of kick it off um and actually yeah that's that's kind of it from there the ball is just gonna continuously move it will never like come to a stop or slow down and that's the that we can all control through the you know the various rigid body properties so essentially we just need to add our starting force here so we can actually implement a function called start and um onstart so start will get called the very first frame this script is executed and once this just like awake will only get called one time for the entire life cycle of this script so start here and let's actually create another function called add starting force and we'll simply call this within here and in here we're going to get the way i'm going to implement this and feel free to you know get creative but i'm essentially just going to pick a random direction in both the x and the y so the ax will determine does it go to the player first does it go to the computer first you know if you want to always go one way or the other you can hard code that it's up to you my case i'm gonna make it choose a random direction so let's get both an x and a y value here and i can use a class unity provides to us called random i can just say value random.value generates a random value between zero and one and one way i can essentially like this for x here as i said it's going to essentially determine does it go to the left or does it go to the right so really it's just like a coin flip you know 50 50 is it left or is it right and so since this generates a value between zero and one if i just check if that value is less than half well then we'll consider that one direction and if it's greater than half well i'll consider it the other direction it's kind of a simple way to do like a coin flip type of um logic so let's say if it's less than half i'll go negative and if it's greater than half i'll go positive um and this is our direction let's kind of do a similar thing for our y here um but for our y it's not just um it's going to be different essentially we need to the y is going to really dictate the angle of the ball and so we're going to do something similar where it's either going to go up or down so we'll do another like coin flip type of thing here and if let's say if it is um let's say less than 0.5 is going up um random and then from here i don't i could just hard code certain values in here but i want to make this also random that way the angle always is different every time the ball um shoots off otherwise it would be very kind of constant and the game would feel repetitive very quickly um so here i can generate a random number between a range of my choosing and i can actually um let's say so if this is going up up is actually going to be considered negative i believe and i want this to be negative one and like point um negative one and negative half essentially um and then if it's the other direction it's going to essentially be the opposite so between 0.5 and 1. and let me explain this a little bit further so for first of all for range here you're going to provide the min and the max so negative 1 is the lower of the the minimum of these two values so min and max i know it kind of feels confusing because one is greater than 0.5 but in this case it's negative so negative one is actually the min whereas for the other one um you know it's it's reversed and this is just providing kind of it's just going to essentially set an angle for us i don't want to do 0 because if it was 0 then our ball would go perfectly horizontal all right because of our x and it would not go at all in the y whatsoever it would just be horizontal which is not good so that's why we're going to do let's say at least 0.5 and then anywhere from you know 0.5 to 1. and all of our values here are just from zero to one because this is just purely a direction um there's no you know speed or anything being factored into this so it's just between zero and one and i don't want it to be zero because like i said it will just make it flat and so that's kind of the logic there now using these two values i can actually apply a force to our ball and actually we need to get a reference to the ball's rigid body just like we did for our paddles so let's go ahead and do that rigid body 2d call this rigid body i'm going to establish this reference in awake just like we did for our player paddle or for our paddles bridge bodies get component rigid body 2d so same exact code it's going to search for a rigid body 2d on the same game object that this script is attached to and now with that we can apply a force we can say rigid body add a force and our we need a vector 2 here which we can construct using that those x and y values we just generated and that's essentially it although i do want to apply a speed so if if you remember back to our player pedal it's basically a direction times the speed same thing um let's add a speed variable and not once again the speed here is a little bit arbitrary i know this will need to be somewhat of a large value let's say 200 and let me separate this out into another variable just for clarity so there's our direction now it's direction times speed um which is once again pretty much identical to what we did for our for our player paddle it's just how we just set that direction is what's different in this case we basically choose random values so let's go ahead and test this out ball there speed is 200 let's play the game and there we go it went up we'll have to fix that notice how as soon as it collided it just went flat we will fix that next but it is working so there that time it went down instead of up let's see if it'll go to the right make sure it goes to right at least one time let's keep restarting this keeps wanting to go towards me there we go now it went towards the right and let me just show you if this was you know let's just say i hard coded you know zero in here for example um i guess this code kind of doesn't make sense but let's just say this was zero the ball here will just go completely flat or completely horizontal which you know doesn't you would never get any interesting gameplay out of that so that's why we're just kind of picking a random direction you know essentially is establishing whatever angle um the ball will traverse so there is our starting force we do need to fix the the ball sort of when it hits the wall it's not bouncing off the wall it's just kind of hitting or running flat and we actually don't need to write any code for this we can entirely do this through the physics engine so what we're going to do is create a physics material um so right click in our project panel create and we will select um physics material which i there it is physic or physic material although there's a 2d version of it so let's actually go to 2d 2d physics material and let's call this bouncy okay bounciness zero friction full bounciness okay and we can add this to our ball so if we select our ball we go to the rigid body and here you can actually see you can provide a physics material to this let's apply that let's try it again now look at that so now our ball bounces so what this is doing is the physics material is going to determine how when two objects collide how you know how does that affect the the simulation so in this case i said there's no friction whatsoever which the friction was what sort of makes it come to a stop and then start sort of scraping against each other you know before it would sort of scrape against the wall now is no friction but full bounciness that way it just completely bounces and there we go we have our working ball we have our working paddle it bounces off of me um of course there's no scoring yet the computer paddle doesn't move but that's what we can focus on next this is actually going to be some very very simple artificial intelligence um i can almost hardly call it that because it's going to be very very simple but technically it is artificial intelligence let's go ahead and start modifying our computer paddle script we had already created this but we didn't add anything to it it does inherit from paddle though which means we will have a reference to the rigid body that is attached to our computer paddle there's also a speed variable that we can play around with in our editor just like oh well let's go ahead and add the script to our object and there is our speed and and just to make sure this is clear if it was confusing to anybody although our player paddle and computer paddle both inherit from the same script they each get their own unique values so let's say in this case speed is 17 for computer paddle our player paddle has its own values they're not shared they just um both have those same variables declared all right so computer paddle let me reset this back to 10 probably they should be the same um let's go ahead and start adding some logic to this so essentially our computer paddle is going to track the position of the ball we're going to do this inside of fixed update once again fix it update is where you almost always do physics related um logic and so we're going to track the position of our ball and based on the position of the ball we will we will either move up or we'll move down so to track the position of the ball though we're going to need a reference to the ball so let's establish that now we can't do it quite the same way that we did before for some of our other references for example we're getting a rigidbody and we're just grabbing the component directly from or we're using this function git component to establish that reference this is going to search for um the component on the same object that the script is attached to our ball and our computer paddle are on our completely separate game objects so we can't just use git component so instead i'm going to make this public which now means in the editor here we can sort of manually assign a reference to our ball you'll see this show up here it's looking for a rigid body 2d which currently is none but i can drag my ball into here and it will automatically um recognize that the ball has that rigid body 2d component on it and now that reference is established so in our code here the logic is going to essentially be when the ball is coming towards the computer paddle it well it needs to either move up if the ball's above it or the computer paddle needs to move down if the ball is below it if the ball is moving away from the computer paddle well then we will just um essentially have the computer paddle kind of idle in the middle of the playing field so let's check which direction the ball is moving so we can say ball that velocity and we want the velocity is actually a vector so you get velocity in both the x and the y um and if this is greater than zero well that means the um that means the ball is moving to the right which is towards the computer paddle and so in this case we want the computer paddle to then move either up or down based on the y position of the ball so let's check this dot ball and we're not looking at velocity now we're going to look at position so if the y position of the ball is greater than um our paddle and we can say um this dot transform position.y so if the ball's position is greater than the paddle's position well that means the um the ball is above us and we need to add a force to the paddle to move up so rigid body add force the direction here is going to be up and then once again we can multiply this by a speed which we already have established in our base class all right now if the um ball is essentially the opposite here if the ball is dot y is less than our paddle's position well then we will move down instead vector two dot down um times our speed so direction time speed and if if they are perfectly equal if the the positions are perfectly equal then we don't need to move at all so that's why i could have just done else but in this case like if there's um if those positions are the same i don't want to do anything so that's that logic so this is the logic if the ball is coming towards us we also want to have some different set of logic if the ball is going away from us we could we could apply the same logic no matter what but it actually sort of makes the computer better um if if the computer is always tracking the ball no matter what the computer is pretty good and so we kind of want to make we want to add some variability into the computer's behavior so it's not constantly tracking the ball it gives the player an opportunity to actually score and so if the ball's moving away from the computer we will instead sort of idle in the middle of the playing field and actually thinking about it by having the player or the having the computer idle in the middle of the playing field it actually makes the computer smarter because the computer doesn't know where the ball is going to end up when it starts coming back towards the um when it starts coming back towards itself and so by idling in the middle it's actually making it so there's an equal amount of distance it needs to cover either up or down let's say the computer paddle just stopped after the ball after the ball bounced off the computer paddle starts moving away let's say the um the computer paddle just kind of stopped in place if it ended up hitting the ball let's say the very bottom of the screen well now if the ball ends up going towards the top it has a long distance to travel to try to reach that so actually it kind of goes against what i had said where this is actually making the computer smarter rather than um rather than dumber but it's a little bit more fair and i think it's going to make the computer paddle feel a little bit more natural a little bit more human-like instead of just constantly tracking the ball like a robot even though the computer is a robot once again i feel like this just makes it feel a little bit more natural and adds some fairness to the game add some fairness while at the same time still you know the computer has some sense of intelligence to it so if the um or let me rewrite that if the we basically just want to move towards the center of the field so we can check our current position if our current position is greater than zero well that means we need to move the paddle down so if it's greater than zero zero is going to be that center point if it's greater than zero that means we're above and we need to move down to go towards the center and same thing here multiply by speed and if it our current position is greater than zero or i'm sorry less than zero which means we're below that center line then we need to move up timespeed and that's it and that's actually is going to complete the logic for our computer panel so very very very simple it's not the smartest player but let's test it out and see how it works all right so there it is sort of tracking it let me get about let me restart to get the ball i kind of screwed up the ball when i hit it i wasn't paying attention so we hit the ball there you go the player or the computer paddle is sort of tracking it and now look look notice how it's just kind of hovering in the middle there because the ball is going away from it and it's going to reset back to the center it's going to kind of just hover there so it actually gives it a little bit of a natural movement it just kind of feels like it's sort of like sitting there like anticipating you know what's gonna happen next um and it's smart because by sitting in the middle like i said you're it's giving it the most opportunity to cover all directions um if it was just sitting on one end then if the ball goes in the opposite then you're gonna have a hard time actually um actually reaching it in time um and so yeah this feels good this feels very natural um it feels fair the paddle moves very similar to how i move right we have the same speed we have the same physics properties on our rigid bodies but those are all things you can play around with as a way of changing the difficulty of the game you can have the computer panel be faster be slower you can change its mass um or its drag right so if you want the play notice how like the paddle doesn't just instantly come to a stop like those are all various things you can play around with by changing the rigid body properties but there we go now we have pretty much a working game of pong um but there's still more for us to do we need to do scoring um we can go ahead and add some ui as well to for the score and there's actually one more thing i want to do before any of that which is i want to make the ball faster and faster and faster as the game goes on so we'll take a look at that next so to have the ball increase speed over time as the game continues on one way we can do this is by having or is by adding a force to the ball every time it bounces off of something which is going to increase its velocity so let's go ahead and create a new script called bouncy surface and we're going to implement it in this way because this is going to give us a lot of flexibility of how we design our game we'll be able to add this script to whatever surfaces we want and there'll be some variables that exist on this script so we can have it bounce off of those differently off of different surfaces in a different way so for example maybe you want the ball to bounce off the paddles with a lot more strength than if it just bounces off of the walls so this script will give us that flexibility to do so let's delete everything so i kind of alluded to it already but we're gonna have a variable called um bounce strength okay and yeah and from there let's add a function called on collision enter 2d and then this has one parameter which is collision 2d and we'll just call this collision and so this is a function unity calls automatically for us because our objects um well for one our rigid bodies or have a rigid body component attached to them which once again turns those objects into physics objects and the physics engine is what simulates collisions and also because they have those box colliders which is defining the collision area it knows how to detect collisions on everything and this will get called anytime two objects collide or in this case because we're adding this function to our script bouncy service when we add our bouncy surface to some object this will get called anytime that object collides with something else and so what we care about is when some when the ball collides with the surface so we can actually get a reference to that ball directly through this collision to the collision argument here that is provided so collision.gameobject is going to give us the object that collided with our surface so in this case our ball hopefully now we can't guarantee it was the ball that collided with us and so we need to check to say that ball is not null right so we're going to try to get our reference to the ball script but if that doesn't exist if it's null that means it collided with something else it wasn't the ball that it collided with and therefore we don't want to execute any logic but if it's not null it was the ball and therefore we can do something and so we're going to end up adding a force to our ball here which will increase its velocity and that force will be dependent on whatever strength you specify so let's go ahead and construct that direction i'm going to call this the normal which is essentially the the normal vector is the vector that indicates um you know it's a vector kind of pointing away from the surface um and like so in our scene here let's say the ball comes at our top wall here it's going to come in at one angle and it's going to bounce off at the opposite angle so our normal is going to kind of represent that that vector or that direction so we can say we can actually grab the normal is provided to us in the data that is associated with this collision this collision has all of the information of how those two objects collided what you know the angle all that kind of stuff so we can actually say collision.getcontact um getcontact's going to get the contact point of the collision in this case there could be multiple contact points but i really only need the first one so index zero and then i can say dot normal surface normal at the contact point yeah so the normal is once again the sort of vector pointing away from the surface at that point and then from here i can add a force to our ball now to add a force i need actually a reference to the rigid body on our ball or another way i could do this right now this is private i could expose this and make it public so i can access it from a different script but that's sort of breaking general encapsulation rules so i'm not going to do that instead i can add a public function here just called add force right and let's say this is a force so basically anyone could manually add a force to the ball by just calling this function and the ball will determine how that happens which of course is going to go through the rigid body so really i'm just going to call add force on the rigid body so not a whole lot is happening here but it's just general good encapsulation um and only exposing the bare minimum of what's needed so add force now i can say ball dot add force and i can pass in my vector here which is going to be our normal times the whatever our bounce strength is so often in in our other cases we do direction time speed this is still similar our normal is basically a direction and strength is kind of like a speed um you know really it's a scalar which both speed strength right there are just different ways of scaling this direction to have more emphasis um and actually this should be negative because it needs to go it needs to add the force in the opposite direction um in order for it to actually properly increase speed i believe um yeah so that should be negative the normal times our bounce strength and that's actually kind of it so it's a very simple script but it's going to give us a lot of flexibility so let's take a look at um what this will look like in our scene now that we have this we can add it to whatever we would like um and so i for sure want to add it to the top and bottom wall so i'm going to select both of those i'm going to add that there and let's say the bounce strength is i don't know i actually have no clue what these should be let's say five we'll play around we'll test this out and for the paddles let's add the bouncy surface to the paddles as well but maybe these are slightly more so maybe the bounce strength is higher on the paddles than on the walls let's test this out those values might be too much we'll find out and that actually feels pretty good um [Music] and so let's just play the game for a minute here and we should see the ball increasing speed over time and we can actually test this out if we expand this info we can see its velocity which is negative five negative four point eight yep now it's five point yep so it looks like it is indeed slightly getting faster and the negative and positive is really once again just sort of indicating direction as long as these the absolute of these values are is increasing then that indicates our ball is getting faster and of course we can just visually kind of see that it is also getting faster and actually those values i picked five for the walls and 10 for the paddles feels really good i don't want it to get too fast too quickly i want it to be a good progression over time but by adding these by making the ball speed variable it's going to establish um it's going to allow for either us or the computer to make a mistake at some point if the ball is constantly the same speed and the the players are of equal skill level well then no one's ever going to score so by making the ball speed variable it's going to allow eventually someone to make a mistake and thus someone score and it just makes the game play a little bit more interesting so that is that's it for our bowl okay now let's handle scoring in our game we need to detect collision between the ball and our left and the right walls to determine who scored and then we'll have to keep track of that score so first let's start by creating a new script called game manager and notice how you didn't even change the icon for this just because the very um it's very common scr uh you know class to have for your game called game manager which basically is just gonna keep track of the entire state of everything and so in our case we're gonna want to keep track of score so player score and computer score and we might want to or not might but we definitely want some functions for um you know indicating when one player or the other scored so let's say player scores we want these to be public because they're going to get called um from um they're going to get called externally and let's have one for computer scores player scores computer scores and the obvious code here is the score increases for each respectively we also want another function for resetting the ball basically um we'll reset the position of the ball anytime somebody scores you know what i won't even have that i'll actually add a function to our ball script here and i'll say um you know ball and we'll call this like reset position or something okay so when we reset the position of the ball we'll say rigid body dot um we can say position equals zero i also want to change the velocity because the velocity is actually increasing over time so we'll also set that to be zero um reset position and then when the position is reset we'll then add our starting force again and starting force all right so reset the position back to the center reset its velocity back to zero basically stop it from moving and then we'll re-add our starting force which will be another random you know another random direction and what not um and that looks pretty good and actually i'm gonna do one more thing let me move this up here reset position and instead of calling um add starting force and start i'm going to call reset position and start just in case for whatever reason our ball doesn't you know if in the scene it's not lined up in the center or or whatever we'll call reset position which will recenter it and all that and calls add sorting force okay and so in our game manager when someone scores we need to call that function but we need first a reference to our ball so let's get a reference for a ball now we can say ball on this style ball dot reset position and same thing here this top ball that reset position great and now let me go to our editor let's add a new game object for our game manager we're just we're going to call this game manager we're gonna add that script to it now let's bring this to the very top let's establish this reference here so let's drag in our ball there we go all's good there so we have our game manager keeping track of score um when either the player scores we increase the the in the value when we reset the ball same thing for computer um but now we need to actually call player scores or computer scores when the ball collides with either the left or right wall let's add a new script called scoring zone and let's add this to our let's add this to both our left and right wall let's go ahead and edit this delete all that um just start fresh and this script is going to look very very similar to our bouncy surface with this on collision enter right we want to this is what you use to determine if two things have collided same exact thing on collision enter in this case with the scoring zone let's make sure it was the ball that collided so we're gonna do that null check again and if it is the ball that collided we can do something in here now essentially what we need to do is call either this function or this function now the problem is we don't know is the scoring zone for the player is it for the computer we could have two separate scripts for for each but um i'm going to show you a way we can do this that's a lot more flexible i have to import something called event systems so we're using unity's event system api for this and here we can add a trigger so we're going to trigger an event when the ball collides and so this is event trigger dot trigger event and we'll call this score trigger um and so to actually trigger this event when we've collided we can say this score trigger dot invoke and this will invoke our trigger now you actually have to pass in some data to this event data so we need to construct that first we'll just call this event data new event data and we need to pass in the event system that's handling this which we can just say current so there's a lot of boilerplate code i'm not really diving into the specifics here it'll make more sense in the editor which is what i want to focus on um so don't worry too much about the code here um if you're not familiar with uni's event systems but essentially is when our ball collides with our scoring zone we are going to trigger some event that event indicates that someone scored let's take a look at what this actually looks like in the editor though so you can see our scoring zone we can add a trigger and we can provide an object we want to call some function on so that's going to be our game manager all right so we drag our game manager in and now we can invoke some function when this event is triggered when you know someone's scored game manager and that will either be player scores or computer scores so far left wall that's the player's wall it's actually the computer that's scoring in that case so we can we can trigger our computer scores function to be called when this event happens and then for our right wall it will be player scores okay let's take a look let's test this out make sure it works let me just print out the um let me just print these out so we'll know for sure that these got called oh i guess too it's going to reset the position of the ball so we'll we'll visually see something happening if this works let's play our game um let i'll let the computer score on me first let's go to our console here i'm gonna let the computer score boom so it got called we printed out the computer score here and also you notice the ball reset to the center and started over again oops and i yep there we go i accidentally missed let's um test that it works when we score so that's actually we're gonna need to just play the game for a minute here because initially the ball is fairly slow and the computer has no problem keeping track of it and so as the ball increases speed over time it's going to allow for the computer to make a mistake and eventually allow us to score so let's just play here for a minute hopefully i don't mess up i also could if i really wanted to i could just change the speed of the computer paddle so it's too slow to reach the ball but that would be cheating um i don't know can you can a can a developer cheat at their own game i guess i guess they could oh there we go perfect so i scored i scored it showed up player scores the ball reset it started moving again and notice too it's it's actually back to going slow right so it was going pretty fast when i scored and then it started out going slow again all of that is working exactly how we want at this point we have a fully working game of pong um the player paddle i can obviously move the player paddle the ball moves the computer responds um i can score we're keeping track of the score we could call it here but i'm gonna do just maybe a couple more things mainly i just want to show the score actually show the score of the player and computer at the top and maybe just do a little bit of clean up here and there and then we can call it a wrap um so let's go ahead and add the ui for our scoring so i can right click on our hierarchy and i could go to ui and i want text this is going to create unity creates us a canvas which is what um you use to actually render some you know any kind of ui object so this is going to determine like you know like for example you can have your ui render on top of the entire screen you can have the ui rendered like based on the camera or you can even render ui directly in the world itself but for my cases we're just gonna leave all this exactly how it is don't need to change anything and we just want to focus on our text component here i guess by default you can kind of see it's really small but by default we'll set that to be zero we will change and let's say this will be the player score so let me name this player score i'm going to right align it and i will um i'm going to just have it overflow which means i can effectively is slightly hacky but i can basically just ignore the size and um just have the text completely overflow and let's reposition this towards the top let me also let me change the color because i can't even see i can't even see it let's change the font size let's just make this like really large that looks actually pretty good we'll we'll change the actual font too but let me reposition this and i can have this aligned to the top so i can i can choose there have it aligned to the top now if i change this position y to zero you can see it the you know it aligns to the top i want to maybe scoot this over just a little bit i don't know negative 50 that she looks pretty good um and i the right line is important because as this score increases if i wanted to go that direction um versus if it wasn't it would you know it would you know start to overlap the wrong side there so i want that definitely to be right aligned and let's actually change the font here because it is not a good looking font especially for an old retro game like this and i'm actually going to drag in a font i already have picked out but we can you know this font will also be available in all the project files on github so feel free to use this if you like and of course use your own let me drag this in here we've got this font here let me go ahead and organize all of my stuff here we'll call this fonts and i never created a folder for my physics material i get i don't really need folders because there's not that many assets but it's just a good practice to kind of organize your stuff um let's call this physics so bring our fonts there let's bring our physical stereo there so now everything's organized let's go ahead and drag this font into the font there it looks pretty good nice zero um we need to change the y position actually let's say negative 50 yeah it's negative 50 negative 50. it looks really good actually you know cool cool actually might you know i'll leave it i'll leave it um and let's duplicate this and call this computer score and this one will be left aligned and it should instead probably be positive 50. and that definitely does not line up quite right let's make this um 60 65 that feels more even that looks good okay cool so there we go we got our score showing up now we need to update the text here programmatically whenever somebody scores um so we need to establish references to these text components and we already have our game manager is what's keeping track of score and everything let's go ahead and create some variables for our um components here so we can reference them and i think i need to import unity engine dot ui there we go now i can say text we'll call one of them player score we'll call the other computer score on also that's actually confusing because i have those so we'll call this computer score text player score text and so when the player scores we will of course change the player score text.tax equals player score to string um and then here we will say um just organizing everything this dot computer score text dot text equals computer score to strength grades um and i know i'm kind of going back this is a little bit irrelevant or a little bit of a tangent but thinking about this reset position again um i actually want to separate out these functions from one another i don't want to necessarily assume that when you call reset position it also adds a starting force because when you if you were to just say reset position you wouldn't necessarily expect it to do this logic too so i actually don't want to call this function in there like we were doing i'm going to have these separate and um i will just sort of manually call both of them in our game manager i know it's like adding actual lines of code um oh and then this will need to be public i know it's in a way sort of making me add extra lines of code here but i just feel like the separation of responsibilities there is is a little bit better so just trying to employ some good programming practices and now in this case if i really wanted to i could have another function to encapsulate some of this logic which i actually will do in a minute because the other thing i want to do is um i reset the position of the ball what we didn't do earlier was reset the position of the paddles we should probably also do that um let's say we have paddle here with player paddle and another one computer paddle once again i know this is a little bit of a tangent from the ui stuff but you know all in all right now we're just kind of cleaning up the code polishing everything adding the last details and now i just want to make everything as good as possible so player paddle computer paddle and then we can call reset on those so in our base class we'll also add a function here called reset position just like we have for the ball and we can say rigid body dots same thing we did position is zero well actually it won't be zero because that would put it into the center of the field which we don't want we need to maintain the x position we already have we want to reset the y back to the center point and we want to maintain the axe that way they stay aligned either in the left side or the right side uh and then the velocity as well can get reset so it stops movement oops vector two there we go so basically the same as the ball more or less reset position and now we can say player paddle that reset position computer paddle resupposition all reset position all right so it's just like we're doing all of this stuff to reset everything when someone scores and now there's a lot of redundancy in our code and so let's actually um reset um you know reset round maybe we'll call this a round um where we can do all of this code in one and we will call this function reset round so there we go a little bit of code cleanup here it's always important to go back and um refactor things as needed to keep your cone your code clean and fresh and so this looks a lot better player scores increase the score we update the text whenever we do so and then we reset the round resetting the same thing for the computer when we reset the round we basically reset all the positions of our three main objects and then we re add our starting force to the ball really nice lots of different references here but that's to be expected because this is our game manager and once again your game manager is usually the one thing that's sort of keeping track of everything and so it definitely makes sense for the game manager to have those references which we need to establish let's just drag everything into the appropriate field here we've got our new text um our new text components there too and there we go is that let's this might be our very final play test here um i guess i'll let the computer score there we go it changed to one notice how my position we added that new code to reset my position as well let me look at that one more time boom we were set back to the center so there we go it's basically everything starts fresh every time you start a new round and let's score on the computer one final time and that will wrap up our game of pong here um all in all it's a fairly easy game to implement and the great thing about pong is there are so many different ways you can customize this right so i encourage everyone to get creative see how you can change the game to be unique in your own way see what else you can add to the game maybe there's new features you can add there's so many different ways you can make this interesting and we should be scoring here in a minute as the ball increases speed oh that might be it oh he got it in time the the computer like really accelerates like he's slow at first or yeah he kind of has slow acceleration but he has a pretty good like top speed um oh there we go so i scored it's one to two and great resets awesome there is our working game of pong i've gone ahead and made all of the source code available for this project you can go ahead and download everything the code some of those assets i've used there's a link in the description of the video for github where all of this is available publicly i've also gone ahead and cleaned up some of the code i've added additional comments that you can learn from explaining everything i'm doing and why um so feel free to use this you can you can also use this all as a starting point um to continue building off of if you want to see how you can expand upon the game of pong and add maybe new functionality so feel free all of this is available on github link in the description of the video i appreciate you taking the time to learn how to make the game pong with me i hope you learned a thing or two if you did give the video a like to let me know i did a good job if you want to see more videos like this one then subscribe to the channel i will be continuing the series of recreating all the classic arcade games next up on the list is the game asteroids which will be fun a little first person game or i'm sorry a little shooter game if you have a particular game in mind that you would like to learn how it was made then feel free to leave a leave a comment um on the video to let me know and i'm sure i can make a video for that one as well if you like my work then you can receive exclusive rewards for supporting me on patreon not only do i create unity tutorials i also create unity assets for other developers and becoming a patreon gives you access to all of this work your support means i can continue development of my next game which you can even help contribute to thank you for watching stay tuned for the next one you
Info
Channel: Zigurous
Views: 16,716
Rating: undefined out of 5
Keywords: unity tutorial, unity, how to use unity for beginners, how to make a game, unity 2d tutorial, game development, how to make a game in unity, unity 3d, unity 2d, game dev
Id: AcpaYq0ihaM
Channel Id: undefined
Length: 79min 27sec (4767 seconds)
Published: Wed Apr 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.