How to make Asteroids in Unity (Complete Tutorial) πŸš€πŸŒ‘

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello my name is adam in this video we are going to recreate the classic arcade game asteroids in unity this is the third video in our series of recreating old arcade games the first one was snake the second one is pong and now this third one is going to be asteroids specifically we're going to focus on a couple things one it's procedural generation so how can we generate our ash range or spawn our asteroids in a unique and interesting way but do so completely programmatically right how can we randomize different properties of our asteroids so they all feel unique and everything feels natural and it creates this good sense of gameplay and all these asteroids come flying at you at the player and the second thing we're going to focus on of course is the shooting mechanics and so as the player as you fly around you'll want to be able to continuously shoot at the asteroids to defend yourself and this will be a big part of our game and we want to do this completely through unity's physics engine so we'll learn how to do all of that today in our video let's go ahead and dive in let's begin by creating a new project using the unity hub we can click the little drop down menu in the top right here in this blue button and this will allow us to select the specific version of unity we want to use so for this tutorial i'm going to use 2020.2.1 it shouldn't actually matter too much which version you are using but if you want to follow along exactly i would try to use pretty much the same version as this um go ahead and name this project whatever you like asteroids for example choose wherever you'd like to save it let's make sure we're selecting the 2d template since this is going to be a 2d game go ahead and click create and you might need to wait for this to finish loading it could take um a few minutes to initialize once your project is initialized unity will provide you a sample scene by default so we can actually go to our scenes folder here and i'm going to actually just rename this to asteroids and this will trigger us to reload and by default this scene just has one game object which is our camera essentially so first we want to set up our entire scene we're going to create a number of game objects and then add some components to those game objects before we begin to do any scripting um so since the camera already exists we'll just start with our camera and the only thing i want to change is this background color i'm just going to make this black you can see a preview of our camera here and we can also switch over to our game view here to get the full preview let me go ahead and change my resolution here let's do a 16 by nine it feels pretty good feel free to adjust your window to your preferences and so there we go there's our camera with our backpack with our black background there's nothing else we need to change for our camera next let's create some boundary walls that will surround our camera's view um this is going to prevent the player from being able to navigate past the edge of the screen here if we go to our scene view you can see this white outline which is indicating exactly the edge of our camera so essentially that's going to be the edge of our screen so we can right click in our hierarchy here and we can choose create empty and let's just call this boundary and let me reset the transform here by selecting the three dot menu choosing reset that just sets all the values back to their defaults and there's one component i want to add to this which is a box collider 2d um of course we're going to use the 2d versions of all these components this is that this is a 2d game you can see this little green outline is indicating um our box glider and a box glider is defining the shape of the collision area um so let's go ahead and position this at the very edge of our screen let's make sure it lines up exactly so let's say 5.5 now we can scale it in the x-axis let's just make that something like um 18 that looks good it doesn't it doesn't in this case it doesn't have to line up perfectly as long as that main edge is lined up we can duplicate this by right clicking it and selecting duplicate now we can flip this from positive to negative and now we have our bottom one let's go ahead and duplicate this again um and let's create our left and right now in this case we want to flip the axis that this is being scaled on so instead of the x we want to scale in the y um and i think the scale here will be up scale of 10 that looks good and let's position this all the way on this edge um negative 9.4 lines it up perfectly good now let's duplicate this one and let's flip it from negative to positive and there we go there's all four of our boundary walls um directly on the edge of our screen which is going to prevent um our player from being able to navigate past um past the edge there and let me just rename these all to boundary okay good that's it for our boundaries finally we can create our player sprite so let's go ahead and add one more game object to our scene here so we can right click we'll do create empty again and we'll call this one player let's reset the transform as well and there's a few components we need to add so for one we need a sprite renderer and this right here we can assign um i'm going to pull in a sprite that i've already created all of the assets i'm using the sprites and so on will be available to download for free there's a link in the description that will take you to the github project for everything here which has all the assets and everything that you can use but also feel free to create your own spread if you would prefer that too so let me go ahead and drag this in player there's my player sprite that i created and also i'm going to organize my files here so i'm going to create a new folder for sprites and let's go ahead and move that to that folder and so now that we have the sprite added here i can drag this into this property here and there is our sprite and you can see in our game view we can actually see our player showing up which is perfect now there's a couple other components we need to add to this game object so another one we want to add is called a rigidbody and then of course the 2d version a rigidbody is going to turn this object into a physics object so you can see there are a number of physics related properties like mass drag gravity etc because of this component the physics engine will actually simulate you know physics on this object and then finally we also need a box glider 2d once again the box glider is defining the shape of the collision area which is outlined with this green rectangle here which is just going to fit around our player um some of these properties on our rigid body we will change later on once we start scripting our player movement but i'll wait to change those so i can properly explain them then but that's actually it for our scene setup there's nothing else we need to add at the moment next let's start scripting our player movement let's go ahead and create a new script i'm going to also create a new folder to contain all of my scripts so let's call this scripts and let's open this up and that's right click create c-sharp script and i'm going to call this player and once we have a script we can add that script to whatever game object we'd want so of course we're going to add this to our player game object we can drag this into the empty space and now we can have the script show up this means that when this game object is active the script will also be running so long as as it is enabled let's click our three dot menu you can do edit script you can also double click on the script itself and let's go ahead and start adding some code here unity by default creates a class that inherits the mono behavior they also provide a couple functions here um that are just very commonly used but i actually like to just kind of delete everything and start from scratch personally it's just my preference so for our player movement we first need to check for input and then based on that input we will um call some functions on our rigid body so to check for input we can do that inside of a function called update which is a function that unity calls for us automatically every single frame our game is running um this is very commonly used or it's very common that you do input inside of this function so we can say for example if you know input.getkey and then there's a few variations here get key get key down get key up get key is going to return true or false every single frame a given key is pressed and then get key down and get key up we'll return true just for the single frame that that key was either pressed down or pressed up so it's just is like one it's just kind of did you press it once versus are you continuously pressing it which is good key so for moving we want to say are you continuously pressing you know some key here um so let's say for example for moving forward we can use w um so i'm going to use wasd and we could also use arrow keys too so we could say or input.getkey keycode dot up arrow all right and then if that's true we will do something now in this case we actually need to we're going to check for inputs separately from actually moving our player and i'll explain why once we get there but for now we just need some variables to know the state of our movement so i'm going to have a boolean here called thrusting all right so boolean is just going to be true or false you're either thrusting or you're not thrusting and so instead of doing the if here i can say thrusting equals um you're pressing the key you're pressing your w key or you're pressing your up arrow right and then i can have another one for turning um but in turning it's not just true or false it's i need to know are you turning left are you turning right or you're not turning at all so i'm gonna actually use a float here i'm gonna call this turn direction [Music] and so for this i can say if um you know and then same thing here although we're going to change the keys let's say for left we'll use a and then left arrow left arrow so if you're um turning left we're going to say return direction equals so intuitively you would think negative would be left and positive would be right which in most cases is correct however the way we're going to actually rotate our player is going to be sort of the inverse because we're going to be applying torque to our rigid body to rotate the player and it's going to be kind of the inverse of what you would um normally expect so we're actually going to have turning left is actually positive then for turning right um for turning right here it will be the opposite so for re we're going to use d and then right arrow and turn direction will be negative one this time and then if none of those are true then we can just say turning is zero turn direction is zero so that's checking input now for actually moving our player we're going to do that in a different function called fixed update and the difference between these is that fixed update gets called on a fixed time interval whereas update gets called every single frame the game is running so usually for physics related code you do it inside of fixed update because if you if physics was ran during update that means it would be variable or dependent upon the frame rate of your game um which is going to lead to very inconsistent physics and so fix updates since it runs on a fixed time interval it's going to make sure that the physics is consistent and so here is what will actually do some stuff on a rigid body but we actually don't have a reference to our rigid body so we can't do anything yet so we need to establish our reference to our rigid body so i'm going to create a new variable called rigidbody we're going to it's going to be able to type rigidbody2d and the way i can grab a reference to this object is in the awake function so awake is going to get called one time for the life cycle of the script and it's very commonly used to do initialization type work or maybe you know establishing references for example which is what i'm going to do here so rigid body equals get component and then the type of component want to get which is our box collider or not box glider my bed rigid body 2d okay so this is once again a function that uni provides for us that allows you to get a component um it's going to search for a component on the same game object that this player script is attached to so in our scene here that is our player you can see our player game object our player script is attached here so it's going to look on this same game object and find the component that we specified which is rigidbody2d and so now that we have a reference to our rigidbody we can actually go ahead and call some functions on this so we can say if you're thrusting well then we can say body add force so by adding a force it's going to move this object via the physics engine so add force and we can add a force we always want to thrust forward you can only thrust forward so the way we represent forward always know the forward direction of our of our playership is by just saying this i'll transform that up if this was a 3d game you would you you usually would say this.transform.4 but for a 2d game you would just say dot up which so that's kind of the equivalent there and then we can also multiply this by some kind of scalar um which would be like a speed right so we might want to have a variable here for thrust speed and by default i'll just set that to one right and now we can multiply this by speed and i'm making this public because now it'll actually show up in our editor here you can see it shows up there thrust speed is now one and now for rotation it's going to be somewhat similar but in this case since it's not a boolean we need to say if turn direction does not equal zero so as long as it's not zero that means we are turning in some direction and instead of adding a force i'm going to add torque and the torque is going to rotate our object via the physics engine and so for torque here i just need to provide a float this is just going to be our turn direction and this same thing here we can also multiply this by some kind of speed um so we can have a different variable for our turn speed turn speed let's say defaults to one as well this dot turn speed and there we go so that's it that's checking input and then based on the state of that we can apply physics to our object here let's go ahead and actually test this out and maybe play around with some of our variables here let's go ahead and run this and notice how i just immediately fell to the ground and that's because i have gravity turned on um so i actually want to turn off gravity so that's zero and now our object will not just instantly fall over here i'm turning i'm turning way too fast though and that's because we have very little drag we want to bump our drag up to let's say one and this is going to make it so i don't the drag is going to allow me to actually slow down and decelerate and angular drag is for rotation and linear drag will be for our so also notice how here if i move forward i don't ever stop i just keep i'm not pressing my keyboard anymore it's just still moving it's because we have no drags we'll probably also want to set that to something like one and that feels a little bit better i'm still turning pretty fast and so we can also tweak our variables here so we can say turn speed let's say 0.1 and that feels a lot better yeah it feels pretty good um overall it's good i think overall though i feel very heavy my my ship feels very very heavy which maybe isn't a bad thing but in this case i might want to reduce my mass let's say to 0.5 and see how that feels yeah that feels a little bit better i feel like i can move fairly quickly i can turn fairly quickly it's responsive but also it still has some of that floaty feel that makes sense for moving a ship in space right if um my it still takes some time for my ship to actually decelerate and come to a stop and i can still sort of float around which feels feels appropriate for this kind of game so that's good these these feel like good uh good values here now one problem is that i tweaked these values while i was playing the game and so when i stop this all those values then get reset um so that's just something to keep in mind that if you're if you want to save those values you got to make sure you do it when you're not running it let me go ahead and set these all back so drag one one gravity zero um and then i changed my turn speed to point one oh i also changed my mass to point five there we go all those values are back to how they were but there you go that that feels good player movement is done next let's start handling the shooting mechanics of the game let's go ahead and first create a bullet so we can right click on our hierarchy let's go down to 2d object sprites and select square and let's call this bullet so this is going to create a game object with already a sprite renderer on it and it's already going to have a spr a square sprite assigned and you can see our bullet show up there it's a little too big though so let's go ahead and change our scale here let's set the scale to maybe 0.075 that feels pretty good feel free to play around with the scale based on your preferences but it feels pretty good to me we're also going to want to add a rigid body to this um to this game object as well and of course we're gonna need a box collider as well so we can know when collisions are happening for our rigid body though we want to change some of these properties as we saw when we are doing our player movement some of these properties might not make sense such as gravity we want to turn off and for our bullets we don't really need to worry about drag or anything um or we don't care about rotation at all so we can just get rid of drag and we can even freeze the rotation just to make sure our bolts aren't like spinning out of you know spinning out of control they just want to move straight we don't necessarily care about them rotating at least not by the physics engine now for drag though we actually do drag actually is important it's important it is set to zero if it's not set to zero then our bullet will actually come to a stop which won't make sense once you fire the bullet it should just keep projecting in its direction it should never come to a stop due to physics or friction or whatever right so we should make sure that's set to zero which it already is so we're good there so that's our bullet and we want to turn this into something called a prefab which is a custom asset that you can create so in our project panel down here we'll go ahead and create a new folder and i'm going to call this prefabs and all we need to do is take our bullet here and drag it into this space and now we have a prefab and it even says bullet dot prefab so a prefab is going to allow us to reference we can reference this prefab in one of our scripts and we can clone that prefab over and over again every time you shoot and now that we actually have this asset down here we actually don't need this in our scene anymore right so notice how i deleted it from the scene but the asset still exists and that's what the great thing about prefabs is there they are a custom type of asset that will persist across your entire project and you can reuse them in various ways so let's go ahead and create our bullet script next let's go to scripts and let's go ahead and create a new one c sharp script and one calls bullet and that's first before we do anything let's add that script to our prefab we can just go ahead and drag that over to the empty space and now our bullet shows up let's go ahead and start editing this and so for our bullet um we're going to need to project it along a certain direction um by adding a force to our rigid body so just like we did for our player we need to get a reference to our rigid body let's go ahead and add that variable there and then in our awake function once again just like we did for our player we can establish that so rigidbody equals git component rigidbody2d and now for our bullet we need to project it along a certain or in a certain direction and it's really going to be the player that determines the direction right so based on the rotation of the player the bullet will project in that whatever that forward rotation is but the bullet doesn't have that information the the bullet script here doesn't know anything about the player and so the player since the it's the player who's going to check for input which will then shoot cause the player to shoot which is going to spawn a bullet the player will actually inform the bullet which way to project itself and so we're going to create a public function here that way the player can actually call this function we're going to call this project and it's going to pass in a direction here um direction right and then given that direction we can say rigid body add force and we'll add a force in that direction and once again we can multiply this by some kind of speed so let's add a variable for speed and our bullets here are going to need a really fast speed um so let's give it a value of 500 and once again we're going to make this public so we can always tweak that number in the editor based on our preferences but for a default 500 should work well this dot speed so multiply the direction by speed and there's our force um one other thing we might want to do is give these bullets a lifetime like a a maximum lifetime that way they're not persisting forever they'll eventually get destroyed so we can have a variable here for max lifetime let's just say they will at most last 10 seconds right so in seconds there and so when the bullet is projected we can say destroy this.gameobject and then we can pass in a delay here so which is our lifetime so as soon as the bullet is fired basically it's going to add the force to start moving it and then it's also going to say okay destroy this bullet after you know whatever the lifetime is set to 10 seconds for example this is just going to ensure the bullet eventually gets destroyed um it doesn't just move on forever you know um and that should be it for our bullet from here though in our player script we need to actually instantiate um that bullet and so we can add a variable for our bullet here and actually we're in a reference that says we're going to reference our prefab that asset we created previously that's what we're going to assign here and that's what we can instantiate but we specifically want to pull out the bullet script that we just added so we can call this function so we have our roll of prefab there and let's go ahead and add a function called shoot so every time the player shoots we will um instantiate a new bullet and we can do that by saying instantiate and then we can pass in an object that we want to clone which is our prefab and then we need to give this we don't have to give this but in this case in our case we want to we need to give it a position and a rotation so the bullet should always spawn at the same position as the player so we can say this.transform.position is referring to the player's position and then same thing for the rotation we want the bullet to be rotated in the same orientation that the player is so this dot transform that rotation is once again referring to the player um and then once we have a reference to our bullet we can say project and we will project this in the direction that our player is facing and we already know what that information is because we did it when we were thrusting right when we were thrusting you can only thrust in the forward direction which is this value here this stuff transform that up so we're going to use that same thing when we project our bullet great so that's it now we actually need a call shoot somewhere though it's not being called anywhere and we're going to call it an update after we check for input so we can say if input dot get key down in this case i want to use get key down not get key i don't want to shoot every single frame you're pressing the key i want you to have to fully press the key and then it'll shoot that one time you press it and then you'll have to press it again in order to shoot again now that is preference so if you if you know if you want it to if you want to hold it down that's fine you can use git key but in my case i'm going to use get key down now i'm going to say spacebar to shoot or maybe i also want to shoot with the mouse button so i can say get mouse button down then i can pass in an index of which mouse button which for the left click is just zero and so given that input i will shoot great so there we go so let's go ahead and test this out we've got our bullet script we've got our player script modified here so we can actually instantiate new bullets for this to compile it's taking a little bit longer than normal okay so let's go ahead and make sure everything's good here so for our player um script here we need to establish this reference to the prefab let's go ahead and drag in our prefab over there that way instant chase the correct thing the correct object let's go ahead and run this and see what happens so let's press space so i'm pressing space now it's rotating me which is kind of weird um and that's because the bullets are colliding with me which is not what i want and so we can actually change that by um updating our project settings so edit project settings should get some kind of window you can always bring this wherever you'd like i'm going to drag it over there let's go to physics 2d at the bottom you can see this collision matrix which allows you to choose which physics layers collide with one another now we don't have physics layers that to represent our player and our bullets so let's first add those so let's go to our player for example there's this layer um property up here and we can add a new layer and i'll call this one player let me add another one for our bullet as well um so for our player we're gonna select player and for our bullet we are going to once again our bullet prefab we're gonna select bullet and now if we go back to that um collision matrix we can say okay when the um you know player bullet collides with another we don't want that to happen and we do not want the player in the bullet to go to cloud with one another we probably also don't want bullet bullet to collide with one another and while we're at it let's make sure the player can't collide with itself although i don't think that i guess that's not really relevant because there's only one player so but regardless we don't want those kind of collisions to happen let's test this one more time so there we go now i can shoot that feels a lot better notice how our bullets um are getting destroyed they're hitting those boundary walls which is good but they're not getting destroyed oh and you can actually see they're starting to disappear and that's because of that max lifetime but we do need to have these objects get destroyed as soon as they collide with something so let's go ahead and edit our script one more time let's go to our bullet script and what we can do is add a function called on collision enter 2d there's one parameter here which is collision 2d we'll just call this collision and so this is a function unity is going to call for us automatically anytime our bullet collides with something else and this is possible because we've added those rigid body and collider components to this object without those components this isn't going to get called all right so in collision enter we just need to destroy the bullet and it doesn't really matter what you're colliding with so sometimes you might want to check that you're colliding with a particular type of object um in our case if the bullet collides with anything it's going to get destroyed so we can just say destroy the stock game object same thing we did here although we don't need that delay it's just going to get destroyed immediately once it collides with something let's go ahead and test that one more time this time when i shoot you know we should it looks like they're just traveling past the screen but really they're actually just getting destroyed right away which is perfect we they don't need to traverse past the screen so they're real there's player shooting so now we can move around we can shoot and next up we'll need to start adding our asteroids all right for our asteroids it's going to be one of the more complicated pieces of this tutorial and but first let's start simple with something we're already familiar with which is creating a prefab for our asteroids so we just did the same thing essentially for our bullet let's go ahead and do that for our asteroid let's create um a new game object let's right click on our hierarchy choose create empty we're going to call this asteroid let's go ahead and add a few components same thing we did for our bullet which is sprite renderer um and then we're going to need a rigid body and a box collider but first let me assign these sprite here and i'm going to drag in a few sprites that i already have pre-created uh one two three and four so i have four variations of this actually um that way the each ashrae feels somewhat unique compared to the others but once again all of these sprites will be available to download completely free um with the rest of the project through github there's a link in the description link in the description of the video but also once again feel free to create your own if that would be your preference so for ashrae we're going to just give the first one as the default but later on programmatically we will choose a random sprite to assign to our asteroid but initially we'll just give it one okay let's add our rigid body 2d as well and properties here kind of the same thing we did for some of the other for some of the others where we don't need drag or anything or gravity um mass so we're going to actually change the mass of the asteroids programmatically we're going to kind of pick a random size for the asteroids and then give them um set the mass dependent on that size um but that should be good for for that we probably don't want our asteroids to rotate either we don't want them to start spinning around so i might want to freeze their rotation constraints freeze rotation um and that should be good for now we can always add or tweak more later and let's add our box collider as well and there we go there is our spray and if i change this to one yeah i'm gonna set this to one only because um [Music] we're going to be changing the spray dynamically and the size and everything and and i don't the one is a little bit more consistent because it might slightly vary depending on the sprite here so i'm just gonna set that to one as a default okay let's see what else so that's our asteroid now we can turn that into a prefab by dragging this into our project panel just like we did for our bullet and there's our asteroid prefab great now we can delete it from our scene we have the ash um we have the asset here um and let's start by adding our asteroid script and we eventually will need to add an asteroid spawner so that'll be a separate script but let's just give our basic asteroid um some properties here so select our prefab let's bring our script onto it good and let's go ahead and start editing this so what we want to do is kind of give it some random you know some random properties when this first starts so in our start function here [Music] let's randomize a few things um so let's randomize for example its size and its rotation and its sprite and so for um for all the thing for all of those things we're going to need a couple references to some other components so we're going to need a reference to the sprite renderer on the asteroid so we can change what sprite is rendering we're also going to need a reference to its rigid body as well and so just like we've done for some of our other scripts we can establish those references in our awake function and we can say sprite render equals git component sprite renderer and um let's fix that and rigid body get component rigid body oh and this was a mistake this should be 2d 2d there we go okay so onstart we can say spriterender.sprite equals and we can then pick a random sprite from our four we so we can add a variable here that is an array of sprites so we have an array of sprites here that we can assign in the editor and we can pick a random one from this array and to do that we can say random.range between zero and then the amount of sprites we have so sprites.length this is just going to pick a random one of those sprites um let's rotate or let's randomize our rotation so we can say this.transform.euler angles equals a new vector3 and we want to rotate on the z axis so x and y can set be set to 0 and our z will become we can say random nut value to generate a random number between zero and one and then if we multiply that by 360 degrees there we have a random rotation and that's not going to um later on when we spawn our asteroids we're going to give them a random trajectory which is also going to be based upon essentially a rotation this here is more so just for kind of the visual it's more of a visual thing right just so the sprites themselves it'll pick a random sprite and it's also going to um rotate the sprite essentially so they don't all look the same right we want to try to make them all feel somewhat unique um and then another way we can do that is by randomizing its scale as well so some will be big some will be small um some new vector 3 here well actually so for the scale 2 this the scale or the size is going to have a bigger impact the size is not going to change the visual size of it but it's also going to change some of the physical properties too it's going to change the mass of the object which actually is going to change how the physics is simulated and also later on when you start shooting the asteroids they can actually split into smaller asteroids right so if if there's a big enough asteroid it will split into smaller ones before they eventually get completely destroyed so that's all going to be dictated by the size of our asteroid so we should probably have a variable here for size and initially let's say it has one but this is going to get randomized when we spawn them so later on we'll have a different script for spawning the asteroids and we'll randomize the size between some range so i guess we will we will need some we'll add those properties now for the range so min size let's say is you know i don't know 0.5 and max size is let's say 1.5 we can always tweak those later in the editor if we need to um so yeah we these two we won't use yet but they'll come into play later um so here now for our scale we can just say we want this to be scaled by um whatever that size is so this will get assigned elsewhere um so at the at the point in time that our script starts this will already get a random value um so here we're just going to take that size and apply it to our scale and i'm saying one times our size which is just a shorthand way of saying this it would be a shorthand way of saying this dot size this dot size this dot size um so it's just it's just a little bit simpler way of writing this this line of code here which is just giving you know creating a vector with whatever our size here is in all three axises okay so that's our local scale we also want to set the mass of our rigid body to be whatever that size is to right so the larger the size the larger the mass um and is there anything else we want to do so random sprite random rotation random scale random mass i think that's probably good enough for now in order to make each asteroid feel a little bit unique compared to the others and there'll be some further randomization we do when we spawn the asteroids such as the trajectory that they that they travel on um where they exactly spawn right so there'll be even more randomization to kind of make everything feel a little bit more natural but for now this is good for our asteroid okay so let's create our asteroid spawner right click create c sharp script asteroid spawner this is going to be one of the more complicated pieces of code we write there's going to be a few different things happening here um so for our spawner we want to spawn asteroids at a regular rate um yeah we want to spawn a new asteroid at a regular rate and so one way we can do that is use a function called invoke repeating just going to invoke a method every x amount of seconds and it's going to you know it's just going to repeat that method call over and over again and we want to do that as soon as the spawner starts then we will invoke this now what's the function we want to invoke well let's just have a function called spawn all right so we'll invoke spawn here this is you'll you have to reference that method by its name so we can say name of then the name of that method which is spawn and then we need to provide um what's the initial time um to call this and then from after that how often do you want to repeat it and so we need a variable for that and we can call this spawn rate um and maybe it's every one second maybe every two seconds one second might might seem pretty quick so every two seconds we'll spawn some asteroids and once again this is public variable we can always change that in the editor if we want to tweak the game the gameplay and so we're going to use this monterey for both of those um those arguments there so what we just did is basically we're gonna this spawn method is going to get called repeatedly every two seconds that's essentially all we did there and so within our spawn here um we can create an asteroid now maybe we don't want to create just a single asteroid maybe we can make a variable for that as well and we can say spawn amount all right maybe by default it spawns one but maybe you want to say hey i want to spawn 10 asteroids every two seconds that would be quite a lot but um let's create the variable so we can play around with that later so here we can establish a simple for loop i is less than whatever the small amount is i plus plus and now in here we can do all of our logic for spawning each um each asteroid so to actually spawn an asteroid we're going to need a reference to a prefab just like we did for our bullet so let's call this asteroid prefab right so if you remember in our player script we had a bullet prefab where we referenced the bullet script and then we can instantiate it this is going to look very similar so asteroid ashford prefab so here we can spawn a new asteroid by saying instantiate and we're going to copy the prefab and we need to give this a position and a rotation now these are going to be um these are going to be some of those other randomizations we do so we need to spawn the asteroid at a random position and give it the rotation is going to then also determine its trajectory so we'll give it a random rotation too um so let's just handle each of these separately let's start with our spawn point um so we're going to need our spawn point we'll call this one point and that's actually going to become that um so first spawn point let's actually go to our editor real quick um so we're gonna have let me create a new object here let's create an empty object and we're gonna call this spawner let's reset its position all the way back to yeah reset the whole transform to zero and let's add our script to that and so our spawner here is going to be an object in the scene that we can change the position of if we want to we can choose where to spawn these enemies by moving this spawner somewhere else and we could even have multiple spawners if we wanted to um and let's say when we have a spawner it's going to spawn um asteroids in a radius around that spawner okay so in a random a random um radius and then some distance away from that spawn from the position there so if yeah so whatever distance you want and then um yeah it should make sure it should be relative to the position of the spawners there's a few different things that are happening here um so first we need to get a random kind of direction like radial we need a kind of random radial direction here um so we can say spawn direction and one way we can do this is saying randomnut inside unit circle and this is going to generate a random point inside or on a circle and in our case we wanted to always spawn the asteroids on the edge of the circle not never inside the circle always on the edge and so if we actually just normalize this it's going to set the magnitude to be one which is always going to be then be the edge of the circle which is what we want now if we also multiply that by some distance we can spawn you know spawn some distance away from the spawn point but we need a variable for that so let's go ahead and add a variable for our spawn distance so let's say spawn distance and um for our game we want to make sure we're spawning the asteroids on the outside of the screen and then they're gonna charge they're gonna have their trajectory set to go to to the inside they're gonna spawn the outside and then they're gonna move to the inside um so to get them to spawn on the outside from the origin here i'm just going to keep my spawner at the origin for simplicity once again though you could have multiple spawners and you can position them wherever you want but for simplicity i'm going to have one spawner in the center and then given that i need the distance here to be large enough that they always spawn on the outside and i know that i know that the edge um to one of these boundaries is you know about negative 10 and so maybe i want to increase that a little bit more let's say to negative 15 um oh not negative 15 but just 15 to make sure that they're always spawning on the outside there right so we take our direction in our circle and then multiply that by a distance and that will randomly spawn them in some circle and then however far away from that point now the thing is this is not yet relative to our spawner position right now with without making any other changes if they would always be relative to the origin which in our case works because there are spawners at the origin but if i were to move this it would still be relative to the origin not to our spawner so the way we do this is we need to factor in or we need to offset our spawn point by the by the position of our spawner itself um now for the actual spawn point first though our spawn point is going to be um let's see here um do this spawn direction i'm drawing a blank here what is this supposed to be our spawn point is our spawn direction or this should just be um this dot transform that position which is our spawner's position plus then our spawn direction yep so our direction once again is kind of picking a random um point on the edge of a circle and then we multiply that by some distance away and then here we kind of offset that um by whatever the position of our spawner is to to make it relative to our spawner's position um so that's our spawn point which is good now for our rotation um it's going to be a little bit different um so rotations we usually represent with quaternions so we're going to have our rotation here um and for our rotation we need to pick we'll also do this rotation is going to have somewhat of an impact on the trajectory of our asteroid um so given that they're always going to spawn the outside we want them to go towards the inside all right towards the center really but it shouldn't go exactly towards the center there should be some amount of variance between between there so we could have a variable for that variance which is essentially going to be an angle um that it'll pick from so if it spawns out here it goes towards the inside it might go you know in some cone um some within some random cone to determine its exact direction and orientation so we can say before we set the rotation here we can get a random um variance here and we can say random.range between um well we need the variable first so let's say we have a float here for trajectory variance um and let's say maybe it has a variance of like 15 degrees and 15 degrees might not seem like a lot but remember they're going to be spawning way out here so 15 degrees from out here is actually gonna cover a pretty wide range of points along our um our actual screen area here or our play area but once again this is a variable that we can always modify in the editor as needed so we have our trajectory variance and this just can be between a negative and a positive of that value there okay and so given that essentially that angle this is basically an angle we can create our rotation here we can take quaternion.angle axis so this is going to create a road tangle with a given angle in a specific axis the angle is that variance and the axis it should be our z-axis um which is if you remember when we rotated our asteroid here we use the z-axis same thing so um one shorthand way of getting our z axis is by saying vector three dot forward um you can see vector 3.4 is a vector three with zero in the x zero on the y and one in the z axis so that's what we that's the that's that's how you would write that so create a rotation of this angle in this axis which is our z okay so there's our random spawn point random rotation we then instantiate our asteroid and there's a couple more things we need to do and then we can test this out one is we need to set that random size that we established earlier right we want to actually randomize that so we can say asteroid dot um size equals random dot range and we created those variables earlier but now we can actually use them asteroid min size and asteroid max size and let's see oh the the other thing we want to do is actually start to move our asteroid along the right trajectory so let's say our asteroid has a function here a public function called set trajectory think of this just like we did for our bullet our bullet had a function called project and the player is the one who calls this and provides the direction in this case we're gonna have a trajectory and we can say our direction here the spawner is the one who will actually set the trigger the trajectory and we'll call this function and so we can say here asteroid dot set trajectory and the direction should be um the rotation multiplied by the direction that it spawned in um although it should be the opposite direction that it spawned in because let's say it spawned going towards the top left right remember once again it picks a random point in a circle let's say it was towards the top left well that's pointing out right we want it to always point inward so if we negate that direction it's going to give us the opposite and which would always point it in the right direction and yeah we need to multiply that by our rotation um so it's all lined up correctly um let's see i think that's good there we do still need to um add this code here so this this code here is pretty simple though this is this rigid body add force we're going to add a force in a direction and multiply this by some kind of speed just like we did for our um just like we did for our bullet we don't have a speed variable yet so let's go ahead and add that speed and let's see the speed of our asteroids if our bullets are let's say 500 maybe our asteroids are 50 right our 10th the speed we want the bullets to be fast and asteroids to be slow so let's let's say that's 50. um and if we really wanted we could make this random as well um but there's already quite a few different random things i don't think we need to specifically the mass because we're changing the mass um and well we're randomizing the size which then becomes the mass the mass is going to determine how fast or slow that object is moving so we actually don't really need to randomize the speed itself since we're already randomizing the mass but we still want to factor in our speed there and we should probably do the same thing we did for our bullet where it will destroy itself after so um so much amount of time all right so destroy this.gameobject and let's create a variable for our lifetime max lifetime now for this should probably be larger than our bullet our bullet was 10 seconds but our bullets moving really fast and so 10 seconds it can it can traverse quite a quite a lot of distance in 10 seconds since our asteroids are slower let's make that a longer time to give it make sure it has enough time to go from one side of the screen all the way to the other side of the screen um 30 seconds should be good but we can always tweak that in the editor if we need to and so we'll destroy this after that lifetime all right um i think that might be it should we test this out let's go ahead and test it out um we have our spawner here we need to drag in our prefab reference let's drag that in um and let's see let's just go ahead and run it and see what happens oh so one problem here index was outside the bounds of the ray and that's because i forgot to give my four sprites here so four sprites um let's go ahead and drag all of those in one two three and four and if we go to our scene view we can actually see these and now they're moving way too fast that's that's for that's for one thing um so they're moving too fast and they're also colliding with our bounds so let's fix these problems one at a time so first for colliding with the bounce we can basically do the same thing we did with our player and our bullet by adding layers um so let's go ahead and add that let's go to our asteroid go ahead and add a new layer for asteroid and then we need a layer for our boundary as well so for our four boundaries we'll set these to be boundary so i just selected all four change the layer i'm going to select our asset prefab here and set that to be asteroid now we can go to edit project settings go to physics 2d and we can change our collision matrix here so let's say asteroids and boundaries will not collide with one another asteroids should not collide with other asteroids so i know that's not realistic normally speaking your asteroids would collide with other asteroids but for the purposes of the gameplay i think it'll make sense it'll it'll work better for the asteroids not to collide with one another otherwise their trajectories are all gonna get messed up and what's gonna happen is they're gonna start to just kind of cluster around in the middle and they're not gonna actually like fully like traverse through the screen so for gameplay reasons we're gonna we're gonna have the actuators not collide with them on there but you know if if you prefer it prefer it's not to not be that way then you know you can always change that yourself and then boundaries i guess while we're here might as well just turn off boundary boundary collision all right so let's test again let's see what happens um so there that spawn that was good there we go so there's they're still moving way too quickly that's that's one thing um but it is working fairly well the spawn distance is maybe too far so i might want to decrease that a little bit um oh the issue too is my spawner is way out here so that was a mistake um so i needed to reset that back to zero so maybe that maybe the distance was actually completely fine um yeah the distance feels good they're just moving too fast that's all they're crashing into my playership which is fine um later on we'll actually handle making sure the um you know if you hit an asteroid you lose so we'll have to account for that later but these are moving way too quickly um so why is that why are these moving so quickly it could be mass it could be um it could be other problems we might want to just change our mass to be larger so they move slower let's try doing that so instead of just directly setting our mass to be the size let's maybe multiply this by two um always multiply two by two and maybe that'll slow them down as a whole we also do have um we also have so that helped a little bit but we also have a variable for this right we have on our asteroids we have the speed here and maybe this is just you know slower maybe this is 10 or so let's see what happens okay that's a little bit too slow might be a little bit too slow let's go ahead and keep the mass how it was and i think we can just play around with the speed variable until we until it feels right yeah that feels a lot more appropriate it's fast but they're not all going to be that fast right so some of them are pretty slow the small ones tend to be faster because they're lighter they have less mass and so they tend to move a little bit a little bit faster and we can maybe even reduce the speed a little bit i think five might work out a little bit better yeah like that feels a little bit more appropriate to me especially these large ones these are really large asteroids with really big mass and so they're going to move much slower i want to see i want to see a slightly smaller one yeah that one's moving faster there we go so this feels good this feels good and notice how each each um asteroid has a different sprite um different size obviously um different rotation so even these two have the same sprite but they're rotated a little bit differently right so just kind of adding some randomness to this to make it feel a little bit more natural and make each asteroid feel a little bit unique compared to the others i would say that is pretty good we can always tweak this further if needed but this is working fairly well asteroids are coming in from the outside of the screen they're going towards me in the middle um and then my job will be to shoot these and we can check for collision and i can actually shoot them and the collision is being detected although we need to actually break the asteroids in half or destroy the asteroids entirely when you shoot them so we'll we'll definitely start handling that next all right let's actually have the asteroid split into multiple pieces when they get shot by a bullet or for some asteroids if they're already pretty small then they'll get destroyed entirely but we need to really handle that collision that happens between the bullet and the asteroids so let's go ahead and open up our asteroid script and first we want to add a function in here called on collision enter 2d and there's one parameter here which is collision 2d we'll call that collision and i think didn't we add this already yeah we already added this for example to our bullet and for our bullet as soon as the bullet collides with anything it gets destroyed um so for our asteroid our asteroid can collide with multiple things it can collide with a bullet it can collide with the player it can collide right so we can't just to say we can't just assume that um it should split in half when it collides with anything we need to specifically know if the thing is colliding with is a bullet and so what we can do to check that is say if collision so this this parameter here it has all the information we need to know of from the collision that occurred the objects that were involved in it and so on so we can say if collision.gameobject.tag this is gonna be the game object you're colliding with if the tag of this um bullet or of this game object is to bullet then we can do something right um but before we do anything let's make sure we are um we set the tag of the bullet so if we go to our bullet prefab we have a bullet layer that's usually used more for physics related stuff our tag hair can be used for really any of our logic like any game logic so we can add a new tag let's go here um oh oops go to yeah tags list is empty let's call one or add one called bullet and there we go we've bullet let's go back to our bullet prefab and set our tag to be bullet so now every one of our bullets will be tagged with this tag called bullet and we can check for that tag in our code here and so when our asteroid collides with a game object we verify that that object is a bullet and if it is a bullet well then we can do something um so for large enough asteroids we want to split it into multiple pieces um so we but we only want to split it into multiple pieces if the asteroid is large enough and one way we can do this is by saying if the if the size of our asteroid if you were to split it in two so if you took its current size and you divided that by two if if that if each of those um new sizes then is bigger than your minimum size well then it's that means that asteroid is big enough where it can it can split into multiple pieces so for example let's say our is you know 1.2 if you were to split that into two each of the new asteroids would then have a size of 0.6 which is within our appropriate range that we specified so that would be good now let's say the size is maybe 0.8 if you split that into two each at new asteroid would be 0.4 which is below our minimum size that means that that asteroid is already small and it's too small where it wouldn't split into two instead it would just get destroyed entirely so we can do that we can say if this dot size divided by two or i usually like to say multiply by half is greater than or equal to whatever our minimum size is well then that means yes we can definitely sp split that object um oops split that object into multiple pieces and so we'll add another function called um say create split we're just going to create like one half um one half of the asteroid so we'll call this twice right so we're creating two splits we cut it our asteroid in half and creates two splits so when we create a split it can actually spawn a new asteroid um in replace now if that doesn't happen well actually regardless of that happening we for sure want to destroy our current asteroid our current asteroid is going to get destroyed no matter what because the two new ones that get formed are going to just be brand new asteroids entirely so this will get this current asteroid will get destroyed regardless um when it comes to creating our splits here now we're going to need to um instantiate a new asteroid of course and we'll call maybe we'll call this half so it's like half of you know it's half of our new asteroid um or half of the you know previous asteroid so we'll say instantiate we're going to copy we're going to copy this right so the object we're copying is our current asteroid um and then the position here will be um essentially the same position as our current one although we want to maybe do a little bit of randomness that way the two new asteroids don't spawn directly inside of each other and maybe there's a slight offset to them but more or less our position is going to be um our current position but let's go ahead and offset that by a little bit so we'll say our new position is our current position but then we'll increase that or offset that by some random amount and we can say maybe inside unit circle times 0.5 so that that's going to offset our new asteroid in a circle in any direction in a circle but only by like half of a unit which is only a small amount but that should be enough to make it feel like those two asteroids those two new asteroids that are forming from the larger one don't spawn like literally exactly at the same exact point like it there'll be some variance there that'll make it feel a little bit more natural um and then for the rotation the rotation is just it doesn't really matter but we'll just match whatever our current one is and then the other thing i want to do is just set the half so we set um we set the size of our new asteroid to be whatever our current size is times half right over divide by two is another way you could write that um and then from here we want to set a neutral a new trajectory for our asteroid so we can say half dot set trajectory and the direction here honestly the direction doesn't really matter it can be completely random at this point since it's getting destroyed in the middle of the scene it doesn't matter which direction it goes it just needs to go anywhere out right which really it really it just doesn't matter so as long as we just say random you know inside unit circle we say normalized which is going to give it a trajectory we want to normalize it so it always has the same um [Music] you know magnitude or like the same speed um or not speed that's maybe not the right way to phrase that but we don't want it to be half half the magnitude otherwise it's going to start to affect like its speed and everything so i want to make sure that's all normalized it's basically just pick a direction um so inside unit circle normalized and yeah it's gonna pick a random direction to start um traversing on which is nice and when once again when we set trajectory we wrote this function earlier but speed will be multiplied into that so we pass in a direction and the speed will already be multiplied into that so that's why we want to normalize that um cool and i actually i think that's kind of it i don't know that we need to do anything else um so to recap here we check for collision specifically check for collision on a bullet between the ashrod and then we try to split that asteroid into multiple pieces only if the size of it is large enough such that we can actually cut it into half if that's the case we have we create two new asteroids instantiate tuning ashrads they're going to have the same initial position of our current ashrae but with a slight offset just to make it feel a little bit more natural we cut the size in half and then we give it a random new trajectory any direction it doesn't really matter um and there we go and then yeah our new astro or our previous asteroid gets destroyed regardless so let's go ahead and test this out and see what happens let's wait for the ashes to start coming in there's one so let's go ahead and destroy that there we go it got set nice [Music] yep and so notice how some of them um some of them just get destroyed instantly where others don't and there we go that feels good now one thing is they feel pretty slow actually when they um when they break apart they feel really really slow to be honest um [Music] and i feel like their speed should maybe be the speed is five which is pretty low but we changed that because they were spawning in way too quickly earlier um so we can always just multiply this if i know so speed is already being factored into this um into our direction there but if we want we can always um multiply this more um so let's just say we have whatever the speed is and then that's going to get further multiplied later on but let's just test that out and see if it's too much or too little or whatever we can also once again play around with that if we need to all right yeah that okay that felt way better that felt a lot more natural we break that one yep that feels much better okay awesome so that feels good so now i can actually pretty much play the game um at this point we're getting close to finishing um all we really have left to do is check for collision on the player now and make sure the player actually dies and then we can handle things like the number of lives you have we can handle scoring do some ui stuff but for the most part we have the basis of our game working here now let's handle the collision between our player and the asteroids let's go ahead and open up our player script and let's add the same function we've been adding in some of our others which is on collision enter 2d and the one parameters collision 2d all that collision so here we can check kind of like we did for our asteroid when the asteroid collided with a bullet we did something in our case we want to do essentially the same thing but instead of the bullet when the player collides with an asteroid um now we haven't yet added this tag so let's go ahead and do that real quick let's go ahead and go to our asteroid prefab let's go to tags we can add tag click the plus button add new ones call that asteroid let's reselect our prefab and change the tag to asteroid and so now all of our asteroids will have that tag and so we can properly check if that's the correct object we're colliding with if it is the correct object we're colliding with well we need to you know the player dies basically um and then the player will respawn um and we can keep track of lives and stuff but for now we're gonna just focus on the player is gonna die and then they'll respawn after a few seconds so when the player dies there's a few things that need to happen one we need to turn off um we need to stop all the movement of the player all right so we can say rid the body velocity equals zero to stop movement also we need to stop rotation so that's going to be angular velocity and turns out that's a zero oh this is not a um this is not a vector it's just a simple float so that's zero then we also want to turn off our game object entirely set active false this is going to stop all of the components it's going to turn off the entire game object entirely so it's not going to render anything there's not going to be any physics simulating the script's not going to run nothing's going to be happening with our player um until the player respawns then it'll get reactivated it'll get set back to true um now what we will end up doing is we're going to call we're going to use this invoke function which you might remember from our asteroid spawner we did invoke repeating um we're going to do something similar we don't need to do it repeatedly but we're just going to invoke um a certain method after some time so let's say the method will be respawn and the time will be whatever the respawn you know whatever however long we want it to take to respawn maybe three seconds now the problem is we can't call this here because we're turning off our game object we can't um we can't invoke anything on a game object that's turned off so we need to do this somewhere else and this is where something like a game manager might come into play right so we might want to have a new script for our game manager the game manager is going to kind of keep track of the overall state of the game so things like score lives um the states of the player whether they're dead or live or you know things like that that's the kind of stuff a game manager might be useful for so in here the game manager might keep a reference to the player um and then there might be a function such as to the player will inform the game manager that they died right so player died and when that happens we might want to change the score we want want to decrease the amount of lives um or maybe not score but live so let's say we have let's say we have lives here maybe initially of three lives right so we can say when the player dies where your lives becomes decreased becomes decremented um and then also we can invoke the respawn function so we can add a respawn function here say respawn um and then when the player respawns we just go to our player game object and we set it back to be active true so invoke name of respawn and we want to invoke this after let's say um you know whatever our respawn rate is or respawn time which is maybe three seconds and respawn time all right so we're invoke respawn after some delay which is our respawn time and when we do respawn we set our game object back on we also want to reset our position to zero so puts the player back at the center of the board which is good and let's see um lives yeah it gets decremented at some point we're going to want to handle our game over so we can say if this.lives um you know is less than or equal to zero then we can do some kind of game over um we don't have that yet we won't actually handle that quite yet but later on we can add our game over right and then yeah we can add our game over so we don't want to respawn the player if you have a game over so only respawn the player if um your lives is not zero or greater than zero and that's good okay so player player dies uh we decrement lives we check how many lives you have left if you have none of them game over otherwise we'll respawn the player after a certain amount of time when the player responds we reset the position to zero we turn the game object back on um and then one thing we're going to want to do is what we're never calling we're never actually informing the game manager that the player died so we need to do that here now to do that we need to get a reference to the game manager and there's a few different ways we can do this um i'm going to actually do it the bad way um so i'm going to use this is this is the bad way of doing it but i'm going to do it first simplicity of the tutorial because i want to keep the code fairly straightforward and not dive into anything too advanced so i'm going to use a function called find object of type and here i can find object of type game manager and this will return me a reference to the game manager assuming assuming it exists in our scene um oh you know i don't even need to store that in a variable i can just say game manager. player dot and so let me explain why this is bad first of all um so this function here is really slow it's very costly to to use this function um and so very often you'll see new developers use this function all over the place um and it's gonna and a lot of times it starts to degrade the performance of their game now it's really really bad to use this function inside of an update inside of any kind of update because these are happening very very very frequently and so if you're calling some very expensive function very frequently that's what's going to tank your performance now in our case although this is a bad function to use because it has pretty severe performance implications it's only going to be happening every you know it only happens when you clog with an asteroid and then it's only happening once until you respawn and then that one thing happens again so for our cases it's really not going to degrade performance whatsoever but it's still not necessarily a good you know there are better ways you can handle this there are better ways you can establish a reference um a global reference to your game manager without having to use this method but once again i'm not going to go into that for this tutorial because it's going to um sort of complicate things that's maybe not the right way to describe it but i just want to kind of keep everything a little bit simple for this tutorial since this is still a fairly beginner maybe intermediate level tutorial but maybe eventually we can revisit this and i can show you better ways to do that so find object to type game manager and inform the game editor that the player died um okay let's go ahead and test this out run this oh one thing we didn't do so our game manager does not exist in the scene yet and so it would have tried to find it it didn't exist and then that would have caused a crash um because i wasn't doing any kind of error handling and also like another reason why that function is bad is because it has to look through every game object in your scene and then every component as well until it finds the right one and that can be quite a lot at times so but let's create our object game manager let's go ahead and drag that on let's make sure we have a reference to our player established our respawn time is three our lives is three and let's go ahead and run this let's just purposely crash into the first asteroid we see there it is let's go ahead and crash into you boom so the player ship disappeared our lives got decremented to two and now and you can see over here my object is grayed out because it's disabled and you can see the the checkbox there is disabled so let's go ahead and see that i respawn now there you go i respawn i can move around again and everything is working well let's just die again now one problem i can see already happening here is what happens if for example you um you respawn well now in this case i'm not alive so i'm not going to respond but let's say you respawn and you respawn directly into another asteroid that would be kind of unfair right you respawn after three seconds then it just happens to be that there's an asteroid already kind of right there so you just instantly die again that would kind of suck and so that's something we probably should handle so to prevent the player from instantly dying when they respawn what we can do is turn off all collisions entirely on our player for a couple seconds which will give them enough time to move around outside of any harm that might be immediately on top of them and that should help out a little bit so we can turn off all of our collisions it's not as simple as just turning off our box collider though um instead what we can do is we can use those physics layers and that um that collision matrix to turn off all layers so we can actually temporarily temporarily change the layer of our player um to a different one let's go ahead and add a new layer and i'm just going to call this ignore collisions all right um i'll put a space in there it doesn't actually matter but let's put a space in there and so we won't by default we'll be set to player but we're going to programmatically change that to be ignore collisions but in our physics 2d collision matrix here for ignore collisions we can just turn off everything right so if the layer is set to ignore collisions then nothing is going to collide with that right so just turn off everything and now in our script here we can say when the player is respond then we want to change its layer to that and then after a couple seconds it will get set back to get set back to the normal layer which is player right so um one way we can check for when you respawn is i mean there's this function that exists which is fine um so actually yeah we could just do it here why don't we just do it here another way you could do it is potentially in an on enable so unity has functions called on enable and on disable for example this might be another place you would maybe do that at and honestly for our cases here probably doesn't matter too much but since we already have our respawn i'm just going to do it here but in theory it might actually be better to do it on enable because that might cover more cases um but once again it probably doesn't matter too much for this for this game so this our player dot layer um or this dot player that transform that layer no no what is this player that game object dot layer there we go and then we can say layer mask dot name two layers this is just a way to set the layer given a certain name here and we call this ignore collisions all right so we when we respawn we change the layer to be ignore collisions which is going to prevent anything from colliding with us whatsoever um and from here after a few seconds we should turn that back on all right so we can say turn on collisions let's say that after um desktop player that game object dot or this top player dot invoke so we're going to invoke some function called turn on collisions let's say i don't know after two seconds three seconds we'll give them three seconds we'll give them a three second invulnerability um before they have to um before they have to that three seconds is plenty of time for them to find a safe spot so at this point all we do is we set our layer back to what it should be so layer mask dot name to layer and our normal layer for the players is called player right so when the player respawns we change the layer to be ignore collisions and then after three seconds or however long we want to wait um they will those collisions will be turned back on and we can even make this a variable here so we could say um i know we could call this like invulner respawn respawn invulnerability and vol vulnerability time is maybe three seconds it's kind of a long name but whatever respawn and vulnerability time that way we can change that in the editor if we would like to and let's go ahead and test that out and actually i already realized now we probably shouldn't turn off all collisions because then it would allow the player to leave the boundaries of the level so we probably don't want that we really should just turn off collisions with asteroids that's really all we already care about as long as asteroids is checked but we don't want to let the player leave the game area so we want to make sure boundaries is still turned on so maybe ignore collisions might not be the best name for that but once again um this is a pretty simple game so we don't have to make things too complicated um so let's re let's purposely die and respawn and i'm going to try to instantly crash oh this will actually work perfect i barely missed me i was going to try to instantly crash into a oh yeah actually i was already still um [Music] i was already still vulnerable also it's actually not working i'm still invulnerable i actually got an error here player that turned out collisions couldn't be called and that is because i think it's because i'm invoking this on the player and so it's expecting this function to exist on the player rather i need to invoke this on our game object here since our function exists or on our game manager since our function exists on the game manager so that i believe should fix the issue let's try one more time there we go i'm gonna let this kill me and then i'm gonna try to run into another asteroid immediately when i respawn i just missed it now let's try again let's crash into you let's respawn and that's yep so there we go i was able to travel directly through that asteroid um so this is all just to prevent a situation where when you respawn you just end up instantly dying because you an asteroid happens to be right there um and so it gives you a little bit of invulnerability when you respawn so you can kind of get to a safe place so that's it for that one thing we can do to make our game feel a little bit better is add a simple particle effect anytime the player shoots an asteroid so when the asteroid explodes it'll there'll be a little exploding particle effect um we can also use that same particle effect for when the player dies so let's go ahead and create a particle effect let's right-click in our hierarchy go to effects and particle system and i'm going to call this explosion and so by default you can kind of see what's showing up which is not at all what we want it to look like so let's go ahead and change a bunch of properties here to get this to look um more like what we want so duration here let's just set that to 1. um the duration just needs to be long enough for the entire effect to happen so one second will be plenty um we don't want it to loop though this is gonna be a one time thing and and we'll tell it to play when we want it to play so it doesn't need to loop over and over again um let's see what else our lifetime here is going to be the lifetime of the particles themselves so let's say 0.5 they don't need to be very long so 0.5 should be plenty and our speed as well um is a little bit too fast so let's reduce that to just maybe one and if they feel very slow but that's also because the particles themselves are way too big so let's change our start size to be something like 0.05 really a much much smaller so that feels pretty good um now we want to change the way in which these emit and the shape that they spawn in so the emission here we don't really want it to be something that um emits the particles over time we just want an initial burst all right so we can set the rate over time to zero but we can add a burst here so we can say plus button it's going to burst at time zero so that means as soon as the particle effect is played it will do this burst and it has a probability of one meaning it's 100 going to happen every time let's say it bursts 10 particles right so that feels better it bursts 10 particles initially when the particle effect is played now the shape here is going to be the big one though we want to change the shape from a cone to a circle now that does not look like a circle and that's because we need to reset our transform up here so let's go ahead and reset that make sure everything's um the default values and there's our circle it's going to spawn our particles anywhere inside the circle which is not quite what we want we really want them to all start at the very center and then burst outwards which they are bursting outwards they just don't start in the center so we can change the radius of the circle to basically be zero and now it technically can't be zero but it's going to be a small enough number where you don't even notice and now it looks good where it just kind of bursts out outwards from that from the center point and a couple little small things we can do to make this feel a little bit better let's add a color over lifetime which turn that on and we just want to fade out the particles as they as they go away they don't just like instantly disappear they'll slightly fade out so what i'm gonna do is for the first oh man for the first 50 of its lifetime it'll be fully alpha everything's good but then for the last fifty percent it's going to start to fit out right so at 50 it's still at 100 percent alpha but then at the very end it gets set to zero so you can see over time it's fully you know it's fully there and then also it starts fading out as it as it reaches its end um and then lastly this one's really hard to see from here it'll look a little bit better once we can actually see it in the game but the default particle that unity uses doesn't really fit the style of our game we might want to change the material here under the renderer and just use the default sprite right which is going to make this feel more like a little pixel and you can actually you actually can kind of see the difference here but yeah they'll feel like little pixels rather than whatever the default particle unity uses this um so there we go there's our little tiny simple explosion particle effect with just a few um changing a few properties um oh you know what there's a couple things i missed though so our plan awake we're gonna turn that off because we're gonna programmatically tell this to play and so we don't want it to play automatically we will tell it when to play the other thing is we might want to change the simulation space to world space just to make sure the particles are are being simulated in the world and not relative to some other game object that it might be parented to so um but that's it that is our particle effect now we just need to tell this particle effect to play anytime something happens such as an asteroid being destroyed now to do that we need to reference our particle effect and tell it to play and we could reference it in our asteroid script and then in our asteroid script whenever we collide with the bullet we could have it play the effect the problem with doing it in here is that we won't be able to establish a reference to our explosion because our explosion only exists in our scene but our asteroid exists as an asset and so there's you can't create references to objects that are in like i can't reference an object that exists in this scene in this prefab um so what i am gonna do is establish a reference to the explosion in my game manager and i'll let my game manager um handle all of that so here in our game manager we can add our particle system is what we're going to reference and we'll call this explosion and so for example when the player dies this is one of the places we want to play our explosions we can say this dot explosion dot play oops stop play and also we want to change the position of our explosion to be the same position as our player that way it plays the effect at the right at the right location so yeah this top player that transformed that position so that's one of the places where we want to do this the other places when um is when an asteroid is destroyed um so we don't currently have um that hooked up yet so we have when the player dies and then we're heading respawning we also need to have when an asteroid is destroyed asteroid destroyed and the reason why this makes sense to be here is because this is also where we would do something like scoring um so i guess while we're at it we can start to add scoring um so we can keep track of score initially at zero and when an asteroid is is destroyed we can increase our score by some amount but let me revisit that and let's finish the particle explosion first um so really it's the same two lines of code but this time we want to change the position not to be the position of the player but to be the position the position of whatever asteroid is being destroyed now how do we know which asteroid is being destroyed well we can pass that in as a parameter to this function right so we can pass in the ashrod that's being destroyed um and then we can use that to change its or to set the position of our explosion and play that now we just need to call this function just like we did for when the polar died we need to call that function so if you remember earlier we're using this which i kind of um i explained how this is actually not a good way to do this and um so we're gonna do the same thing again um just keep in mind this is not the best way to do this but i don't want to um i want to keep the code here simple enough for this tutorial and the best way the better way to do this i feel like is a slightly more advanced and i don't think it belongs in this tutorial so find object of type game manager and we can say asteroid destroyed and then yeah we have to pass in the asteroid being destroyed which is just this and there we go um yep so when the ashrae is destroyed we play our explosion effects we can add it to do here for score you know increase score but let's go ahead and test our explosion and then we'll come back to the scoring okay so we have our game manager our explosion there let's drag a reference there and so now programmatically whenever those two events happen either an ashrae is destroyed or the player dies we should see that explosion happen if done correctly wait for our asteroid to come in let's go ahead and start destroying some of these there you go there's a little explosion explosion nice so it feels good there we go nice now let's test it out when i crash so i crash boom oh that feels good so i crash and i sort of instantly disappear because we're turning off the player but it feels right because then you see this little explosion happen so it's like my ship just explodes and it and it just makes sense it feels it feels like um what it should boom explode so with a single particle effect we're able to um you know add a lot of polish and a little bit of detail to the game and everybody reuse that one effect for multiple different things so there we go let's go ahead and revisit our scoring since we had started to implement that let's go ahead and finish let's finish that off so in our game manager we added our function for when an astroid is destroyed so we can play our explosion but we also want to increase our score here and we did create our variable for our score which initially has a value of zero so to increase our score really it should be um we could just say you know every time you show an asteroid your score increases by one but i think it would be better to increase our score based on the size of the asteroid right so different size asteroids have a different score associated with them um and i would actually say that the smaller the asteroid the more points you get because the smaller asteroids are harder to hit and therefore you should be rewarded more for them so we can actually check the size of our asteroid because we have a reference to the asteroid being destroyed and that asteroid has the size property so we can actually check and say okay based upon that size you know change the score by this much now we could do some mathematical function here to determine that um but for once again for simplicity i'm just gonna say there are three tiers of scoring um there's basically small medium and large asteroids and one will be worth 25 points 50 points and maybe um you know 100 points right and so let's say if the asteroid size is less than what was our minimum size was 0.5 okay so let's say maybe if it's less than seven five then maybe your score increases by um a hundred points because that would be the smallest if it's then if it's not that and say maybe less than one let me check so one is kind of the middle point um yeah let's do i know one then our score is increased by 50 points um and why does oh our score is an integer here so let's not make these floats let's just do that i also want to do that okay and then if it's not either of those then we can say our score is increased by 25 points as kind of our default and so you know you can play around with this specific numbers here it would probably be better to figure out a formula some mathematical formula for determining the score based upon size but once again for simplicity this works this should work perfectly fine um and we can see our score increase um as we play the game so let's go ahead and try it out so this looks like a small one so let's check that we get 100 points for this yep so we got a hundred these are all small ones it looks like so yep 200 um let's try to find a medium one now and i'm just getting all the small i'm getting all the small ones okay this might be medium it might be large let's see so that was 425 so that was considered large um and that was um broken up into a small one so that's another large yeah so it seems like the range there is maybe not quite right maybe this should be you know 1.25 or you know something like that is a little bit better um that way our range would be i mean in total our range goes from 0.5 to 1.5 so there's a total delta there of one and then if we want to bucket that into three different things then there should be roughly 0.33 between each so maybe 0.5 to 0.8 is small or we'll keep that at seven five um and then maybe from seven five to one point two is the medium and then from 1.2 um to 1.5 would be the largest so yeah i feel like that breaks it apart a little bit better but regardless doesn't necessarily matter you can tweak um tweak those numbers to get it to feel right um it's always kind of your preference at this point there we've got our basic scoring and everything at this point we've pretty much covered everything we need to cover for our game of asteroids here the only thing we didn't do yet is our game overstate now we're not going to really do a full-on proper game over really all we're going to do for the sake of this is reset a couple of variables and respawn the player just like we normally would um so let's say our lives here needs to get reset back to three as an as our initial and our score should get reset back to zero and then from there we're just going to respawn the player just like we were before um and that's it normally speaking you would do a lot more for a game over um so for example you would most likely actually have some kind of ui menu that says game over and maybe it says something about you know press press x to play again or press whatever to play again but just for the sake of time and the simplicity of this tutorial i'm not going to dive into any of the ui just because it would eat up probably honestly another 20 to 30 minutes of just kind of you know just creating the ui not even really scripting anything just creating the ui could take some time so we will not do that here but let's go ahead and just test out that this still works as we coded it so our lives is two our score is 725. i want to just make sure that once our lives hit zero it should all reset so let me go ahead and die now our lives is one let's dive one more time there we go our lives is now three well yeah it gets reset to three and our score is now zero again there we go every sets the game kind of just automatically starts over but if you're curious about what the ui of this game could look like and how to do that and what the code would be what the game objects and all their properties would be the project on github um that i've been referencing a couple times or or that i've mentioned a couple times that project actually has the full on ui and everything i appreciate you taking the time to learn how to make the game asteroids with me if you feel like you learned a thing or two then give the video a like to let me know i did a good job and subscribe to the channel for more tutorials just like this one thank you for watching see you in the next one you
Info
Channel: Zigurous
Views: 11,920
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: cIeWhztKyAg
Channel Id: undefined
Length: 112min 5sec (6725 seconds)
Published: Thu Apr 22 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.