In this phase we're going to create this shell prefab, it looks like this and has a number of different components, it's got a collider, a rigidbody, it has a light component, and the idea with this is that obviously we'll fire it from the tank, but to demonstrate what it does, it has an overlapped sphere this is a kind of sphere of damage that it can give to any of the tanks that i lands near. So in this video what I'm doing is slowly moving it closer to the tank and what you should notice is that that health is getting reduced by more the closer that that bullet happens to be. Or at least it will do in a moment. Off we go, moving it closer. The closer it is the more damage that will be applied. Obviously if you hit a tank dead-on then that will be a huge amount of damage. That's the shell that we're going to make and then in the next phase after that we'll handle the actual shooting, but first off we're going to handle the damage, or the thing that's going to parse damage to the TankHealth script that we did before. What I would like everyone to do is look in the Models folder, in this folder you will find a model called Shell. If you select it it will look like this in the inspector. A little note, if you want to inspect something, drag around it, you can just drag in that preview window at the bottom of the inspector. So what we'll do is drag that in to the hierarchy. If we drag and drop that model from the project to the hierarchy. Move your cursor over the scene view, press F to frame selected and you'll notice it's at the origin, roughly, so it's near to 0. So all I'm going to do is just to drag mine up slightly so it's somewhere I can see it and work on it, something like that is fine. Remember because we're creating a prefab that we're going to fire with the tank this isn't something that's going to be in the scene when the game starts just like the tank, so we don't need to worry about where it's positioned for now. So because we are making this something that's going to interact with other objects it needs to have a collider. We'll use primitive colliders because they're nice and performant, and given the shape of this we'll use a capsule collider. So with that shell still selected in the inspector we'll hit the Add Component button and I'm just going to type Caps for Capsule and then click on it to confirm, or hit Return. With that capsule collider, because when you are firing things like a projectile as we are. We don't want things to be bouncing off one another and we don't expect this tank shell to ever hit something and push it back, we're expecting it to hit something, create a call back in the script and then create an explosion force. So we don't want any physical interactions. And when we don't want those we use what's called triggers. If you hear someone refer to a trigger or a trigger zone, or a trigger area they're usually referring to a collider that's been checked as a trigger. So if you check the Is Trigger checkbox on that, what that basically means is that it doesn't have it doesn't have a solid surface to it it can intersect, but if can send a call back to the script saying 'I've now entered another trigger' or 'I've entered another collider'. So often trigger colliders are used for things like doors in games, like when you put a big cubic collider in front of a doorway and then when the character enters that way you automatically open the door. It's a pretty classic use of that kind of collider. Once you've added that component, the next thing we want to do is actually set it up. So we need to change the centre, so the centre value for that is (0, 0, 0.2). And the radius is 0.15. And the height is 0.55. Crucially you'll notice that it's not looking in the right direction, so we set the direction to Z axis, and then it should pretty much match our shell perfectly. Or to an amount of precision that would never cause issues. It should look like that. And then finally because this is a physics object we need it to be under control of the physics engine, and so what are we going to add? A rigidbody, there we go, nice and loud. So add our rigidbody component. And it's good to go. So these shells are going to fire a projectile, they're not going to just keep going straight forward, they're going to fall with gravity over time. So just a quick recap of those two points. Okay, so we've found the model named Shell in the Models folder. We dragged it in to the hierarchy. We've added a capsule collider component to the shell and we've made sure it's a trigger so that that trigger won't bounce off of anything it's just going to pass straight through stuff and then immediately be destroyed by the script that we're going to write. We've checked Is Trigger to make sure that is the case. Then we set the direction to Z axis and we changed the centre, so the centre is basically where that originates from so you can kind of offset your colliders if you need to, art-wise. And the radius we've set to 0.15, the radius of the capsule. And the height to 0.55 And we added a rigidbody to make sure that it's under the control of the physics engine. So we've got the shell and currently the shell can fall down and nothing is going to really happen. It's just going to go straight through the ground because it's not going to stop, it hasn't got a physical presence, like I said. So we don't want that, we want it to actually explode and do stuff, so we've created a shell explosion for you. So if you look in the Prefabs folder you will find a prefab called ShellExplosion. So what we're going to do with that is make it a child of the shell. So if you drag from the Prefabs folder and drop it on to the shell It should look like that. And when we simulate it it looks like this. A cloud of dust that kind of falls over time. Okay and then the only other thing that we need to do with that is to add an audio source, so similar to the tank exploding, it needs to have visual effects and an audio effect. So I'm going to click the Add Component button and I'm going to choose Audio Source. And then just like before we need an audio clip, so I'm going to use the circle select next to audio clip and choose ShellExplosion to assign it. Now we don't want this to play as soon as the shell gets instantiated, as soon as the explosion appears, so we're going to uncheck Play On Awake. A quick recap, so we've got our ShellExplosion prefab, we had to make it a child of the Shell game object so it's going to travel with it and then do it's thing as soon as it hits something. We added an audio source to that so that it's able to playback sound and we've used circle select to set the audio clip to ShellExplosion. We don't want it to play as soon as it enters the world so we only want it to play as soon as it impacts, so we uncheck Play On Awake. Okay, the final thing we're going to do with the shell so reselect the shell, the parent object, is to add a light. So as this travels across the game board we want this to light up the environment and it helps pick out the shell, because obviously you've got a gold shell, you've got orange sand, it's kind of hard to see it and the light helps pick it out so instead of creating a point light game object we can just add that same light. So if you've new to Unity, what you'll notice if you go to Game Object - Create is that you've got all these readymade prefabbed game objects with several components on them. So for example if you choose, if there was a cube, then you've got a bunch of different components on it. But you could also create a light which has just the light component on it. We don't need to do that, we're just going to put the component directly on to the shell, so I got to Add Component - Light So now we have to actually handle how that behaves, how it's going to impact and what it's going to do when it hits a tank or when it hits the environment and the kind of forces it's going to apply to other tanks in the game. So what we're going to do is to look in the Scripts folder and find the Shell folder. In that you will find a script called ShellExplosion. So we're going to drag and drop ShellExplosion on to the Shell game object in the hierarchy. And then you should see that along with everything else, the rigidbody, the capsule collider, the light that we just added, you've now got Shell Explosion (Script) and we're going to double click on that to open it up for editing. Okay, so in this one we don't have any private variables but we do have a bunch of public ones. So the first one is a layer mask. Now you might remember at the beginning of the day we put all the tanks on the Players layer. So that means that when we cause an explosion from the shell we can just check for everything that's on the Players layer and see which tanks we've hit rather than trying to affect everything. So that will be available in the inspector and we can choose which layer we want to affect. The next is the explosion particle, remember we just dragged on that as a child game object we're going to get a reference to that so we can play the particles when the shell explodes. Likewise there's an audio source reference, so that's for getting a reference to that audio source so we can play a sound. Then we've got a bunch of floats, so the first one is the most damage that it can possibly do, the maximum damage, and we're setting that to 100. so if you get a perfect direct hit then you'll kill the tank outright. But you can't get a perfect hit because it's never going to be exactly on the position of the tank because the collider is covering it. So you're going to get close but no cigar. The next one is the amount of force that the explosion is going to do right at it's centre. Likewise as the explosion radius gets further out the tank will be less affected by the explosion, you'll feel less force. We've got the max lifetime, so we don't want shells to exist forever so if they happen to miss everything we don't want them to stay in the scene forever so we give them a lifetime, and at the start of the scene we'll say if it's not dead after 2 seconds just kill it anyway. So it's pretty unlikely you'll ever see that, it would either hit the ground or some other object before that ever happened, but it's just a failsafe that we'll write in. So the last public variable is the explosion radius. And that is literally how far from the shell it's going to affect when it explodes. Okay, so let's look at these functions and as we're just mentioning in the Start function we're saying destroy the game object after the max lifetime. So that's saying when you instantiate this if it's still alive after 2 seconds, destroy it. And now we're going to have to write some scripts. So the first thing we want to do, when OnTriggerEnter is called, so you remember we put Is Trigger as True, that means that OnTriggerEnter is called when something bumps in to this. So this function will happen whenever it intersects with anything and then we need to check what it's intersected with and what to do as a result. So we have this argument which we've just called other which is of type Collider. So it's going to say 'okay, we've intersected with something else, it's a collider, what do we do about it?' In this case we don't actually care what we're bumping in to just that it's a collider, so we should explode. But what do we do first? First of all we need to gather up all of the colliders that we need to affect. So we need an array of colliders and you'll remember that's the square brackets after a collider. And we'll call that array Colliders. And we're going to set that to the return of a function called OverlapSphere. So that's Physics.OverlapSphere And what that's going to do is similar to a ray cast, it's going to create an imaginary sphere and everything that overlaps with that sphere or is inside the sphere is going to be collected. And we want that sphere to be at the shell's location, so transform.position for it's position. It's going to have a radius that we've already got as an ExplosionRadius. And we're going to use that TankMask so that it's only picking up the tanks. Okay, so just a quick note about layers. Layers we use for various different things in Unity but ostensibly they're just for grouping things together in some way that you want to use to either include of exclude them from something. In this case we're using it as a way of only including or sort of masking out anything but tanks, which is why we've called this variable TankMask, because it's essentially a layer on which only the tanks exist. But don't think of it in any visual terms, if anyone's in to Photoshop or anything like that there's no kind of layering in that sense. Okay, so now we've got all our colliders we need to go through them all and decide what we're going to do. So for that we need to loop through them all using a For Loop. So this is the same format as we saw before for(int i = 0 i is less than colliders.length so this is, colliders is the array that we're going through so it's less than colliders.Length. And then i++ means that we add to i for every loop. Then open and close brackets? Brackets? Yes brackets. And then we can use whatever we do in that for loop to affect each of the colliders. So the first thing we want to do is check whether the thing that we've hit has a rigidbody, so what we do is we create a rigidbody variable which we'll call targetRigidbody and we'll set that equal to colliders[i], so that's the collider at the position that we're currently iterating through in the array, .GetComponent, so we'll use the angled brackets for rigidbody. So what that's going to do is get that collider that we've just gone through the array and try and find a rigidbody on it. Next we need to know if it's actually found a rigidbody or if it's just found nothing. So what we're going to do is say if not target(!Rigidbody) so what that's going to do is say if there's nothing there then what do I do? And if there's nothing there we want to continue on to the next loop, on the the next collider. You'll remember it's going back to the start of the for loop and carrying on looking for any collider that's got a rigidbody it's not continuing through a list of commands. So bear in mind that this is a bit of a safety catch kind of thing because we're making it everything that's on the Players layer anyway. So everything should have a collider and everything that has a collider there will also have a rigidbody, so we should always find something but it's good to check just in case because otherwise you're going to get errors. So now we know we've got a rigidbody what we can do is we can add a force to that rigidbody so targitRigidbody.AddExplosionForce ( and the force we want to add is the ExplosionForce that we've got as a public variable. So that's m_ExplosionForce. Then comma, so we're on to the next parameter. And the position that that explosion force is emanating from is transform.position. So that's position of the shell. And then the last parameter that we're going to use is the radius, so how far away that explosion force can reach. Okay, so we've added the force now so the tank is going to move but we still need to actually cause some damage to it. So we're going to do something very similar. We're going to create a TankHealth variable, which we'll call targetHealth. So just to qualify that, notice that when we've made these other variables they've been familiar components to things that you've added using the Add Component button. This time we're making a variable of type TankHealth. So that just means an instance of the TankHealth script on a tank, let's go back from the top. So we've gathered all the colliders we could find within the imaginary sphere, the overlap sphere. And we're looping through that list, that array, to the amount that there is, colliders found. And then with each one we're checking that there's a rigidbody and if there is we're adding a force, and then we want to actually also take damage on those tanks. So we're addressing a particular instance of that TankHealth script so we can talk to it and reduce health with it. Okay, so we've got TankHealth targetHealth and we're going to set that equal to the targetRigidbody. GetComponent TankHealth. So we've got the rigidbody, we know that now because we were able to add a force to it. So on the same game object as that get the component TankHealth. And again we should know that there's definitely going to be a TankHealth here but we're going to check just to make sure. Because if somebody wants to extend the game and they make something that's on the Players layer that doesn't have TankHealth then this will still work. So again instead of if(!rigidbody) we've got if(!targetHealth) and then continue. So if there's no targetHealth continue on to the next iteration. So a quick note about this line here. So you'll notice that we've talked about the fact that we need a reference to this instance of the TankHealth script. So you might wondering 'well what's that got to do with the rigidbody, what's health got to do with physics?' Nothing at all, the point is that we've found a particular game object the fact that we're calling it targetRigidbody is not hugely important, we'e just referring to the same game object that we've stored in that. Often when we talk about rigidbodies we'll say 'this is a rigidbody object'. All things in the hierarchy are what we call game objects. But often what people will say is 'that's a rigidbody object'. It just means it's a game object with that particular component attached. So when we're talking about the target rigidbody we just mean it's the tank game object that we know has a rigidbody attached to it. So we've done that check and we can then say we know it's the right game object so we know it's got the TankHealth script on it and we'll carry on from there. Just to reiterate what Will was saying there, you don't need a game object to find a component on it, you can use a component reference to find another component. So that's what's actually happening there. You've got the rigidbody component, we want to find another component on the same game object, that's what we're doing. Okay so we know that we've got targetHealth because we've not come out of the loop yet so let's create the damage, so float damage is equal to this CalculateDamage function which you can see at the bottom of the screen there, which we will write in a minute, but what we need to do is give it the position of the target, because we need to know how far away is that target from the shell when it explodes so we know how much damage it needs to take. So you can actually get the position of something from the rigidbody as well. If you remember back from the TankMovement script we were doing things relative to the rigidbody's position. That's the position that we're going to use here. So we've got the damage now we need to apply the damage. So we've got the TargetHealth script, and we need to call the takeDamage function that we made earlier. And we're going to parse in the amount of damage. So that's all that we need to do for that for loop, that's all that we need to do for each of the targets that we've got, but we still need to make the shell explode and play the correct audio and stuff. Yeah, another thing to mention about this is we're creating a float called Damage, we've got this CalculateDamage, currently if we play this nothing would happen because we don't have anything going on in this CalculateDamage function just yet. But all we're doing is just setting it up so when we do we're going to parse that straight to the TakeDamage function. If you remember when we looked at that TankHealth earlier our TakeDamage function there is public, that's how we're able to just reference it by saying .TakeDamage. Public being the accessibility level of that thing. Okay, we've gone through all the colliders that we need to do, so now we need to sort out the particles and the audio. So when we detonate the shell, when it explodes we want to remove it from the scene, we don't want it to hang around. However if we remove it then the particles are also going to be removed because they're children and the audio source is also going to be removed because that's a child. So we want to make sure that those still play even after we've destroyed the shell. So what we're going to do to do that is to unparent them. So it will come in as a complete game object it'll explode and they will decouple themselves so the shell explosion will no longer be part of the shell. And we're going to do that by setting the transform's parent to null. So null just means nothing. That means it would just be loose in the list of game objects in the hierarchy. So we have detached it now, so next we need to play the particle effect, so m_ExplosionParticles.Play (); And likewise we want to play the audio source so very similarly m_ExplosionAudio.Play (); So then we've just got a couple of more things we've got to do in this function. We need to destroy the particles and we need to destroy the shell. So to destroy the particles we're going to use the same trick as we did in the Start function, we're going to give it a delay. So we're going to say Destroy(m_ExplosionParticles.gameObject We don't want to destroy the particles because that will destroy the component. We want to destroy the game object that those particles are on. And we're going to do that after the duration of the particle system. So you remember before we said that it's going to be 2 seconds, which was a number that decided on. Well particle systems, one of their properties is how long they last for. So we're just going to say destroy it after how long it lasts for. Yeah, so not to be confused with the lifetime of each particle, but the duration is the entire system. So this, as you can see, autocomplete is showing us here Optional amount of time before destroying the object. We can simply just refer to ExplosionParticles.duration and that will simply wait for that to finish and then destroy it. based on that. Which is great, because you can then go and adjust the duration and this code will still take care of it for you. And as James was saying, the last thing we need to do once we'd destroyed the explosion, or once we've triggered a destroy to occur once it's finished playing the explosion is actually to remove the shell as well. So to do that all we do is Destroy (gameObject) and that will destroy the game object that this is on. As ever with scripting everything is just happening straight away, it's not like we're waiting for one thing to happen and then something else to happens, so theoretically you might consider that you would get rid of the shell and then the explosion but it really doesn't matter in this instance. Okay, so, the last thing that we need to do in this script is complete that CalculateDamage function. So in this CalculateDamage function currently we've just got return 0f and that's purely just so it doesn't spew errors while we're working on the rest of the stuff. So we're going to get rid of that to start off with, we don't need it. And the next thing we're going to do is create a vector from the target to the shell. So that is going to be Vector3 explosionToTarget. and that is equal to the target's position, minus the shell's position, which is transform.position. So if you imagine a big circle on the ground, that's the explosion, at the centre of it is the shell, and somewhere in that circle is the target. We're finding a vector between the two. The next thing we need to do is find out how long that vector is, the magnitude of that vector. So what we're going to do is say float explosionDistance is equal to explosionToTarget.magnitude. Okay, so now we've found that distance, which would be somewhere between 0 and the radius. We want to know what the relative distance is. Because we want a number from 0 to 1 really, rather than a number between 0 and some radius that we found. So the relative distance we know the maximum it's going to be is the radius and the minimum is going to be 0. So what we need to do is calculate a number that starts off at 0 and ends up at 1. We do that by dividing by the explosion radius. So relative distance is (m_ExplosionRadius - explosionDistance) then close the parenthesis and divide all of that by the ExplosionRadius. So when you think about that if the explosion distance is very long, IE it's close to the explosion radius then the explosion radius minus something that's very close to the explosion radius is going to be very very small, divided by the explosion radius is going to be very very small so it'll be near zero. However, if the explosion distance is very small then the explosion radius minus something very small, let's say zero divided by the explosion radius is going to be 1. So we're going to end up with a number which starts off at 1 near the centre and trails down to 0 at the edge. And that's how we're going to calculate how much damage is done. So we create a float called damage. And that's equal to the relative distance multiplied by the MaxDamage m_MaxDamage. So when the relative distance is 1 and is very close to the centre, then you're going to deal the maximum damage. When it's close to the edge, it's close to 0 you're going to do very little damage. Okay, so as illustrated in the slide we have our overlap sphere, we have our tank right at the very edge of it, very minimal or maybe 0 damage, and then something right in the middle of that impact such damage, many ow. We're not finished yet with this function. What we need to do next is make sure that the damage is not negative. So we're going to do that by saying damage is equal to Mathf.max of 0f and Damage. So what that's doing is saying if it's negative then set it to 0, otherwise keep it as it is. And then finally we can return that damage. Why is it that we're making sure it's not negative? Well there is literally an edge case in this scenario. In the case that the tank is right on the very edge it's position is actually outside of the overlap sphere but it's collider is within it. So it's going to get picked up by that collider's array and then it's going to be calculated in with everything else but we've only caught the edge of it, so, we're actually going to calculate a relative distance that's negative, because you're starting off at 1 in the centre going down to 0 at the outside and then it'll be negative beyond that. So we don't want negative damage, we don't want to shoot things and make them more healthy, it's just not the way. So that's why we're doing that. Shall we put the script back on and finish it off? Okay, so if you've saved your script switch back to the editor, hopefully there won't be any errors. And then we need to of course populate our script with all those public variables. So interestingly something you won't have seen before, is the first public variable, it's this Tank Mask, so remember it's of type layer mask and we called it Tank Mask. And what that basically gives you is a repeat of all of Unity's layer system. So you'll notice it's the same list that you get in the Layer drop down at the top. This Tank Mask is where we're going to select Players. It's the only thing we want it to actually effect. so select the Players layer from the Tank Mask variable or drop down. Then Explosion Particles is the child object that's underneath the shell. So you can drag a shell explosion on to Explosion Particles, you'll notice in the parenthesis it says Particle Systems. And for Explosion Audio it's the same object because that also has an audio source. But this time when you drag it you'll notice it picks that component. So Unity is smart that way, it knows which component you're referring to if you drag an object that's got that component it'll say 'great, okay, that must be what you mean'. And assign that particular component from the game object that you drag in. Then the other stuff that we've setup there, you know, it's setup based on something that we wanted to make, if we get to the end of the day and you want to have a huge amount of damage, you want to have one shot kills and you just up the maximum damage or add the explosion force and the tank just gets flung all the way off the screen. You can do that stuff. Obviously up the explosion radius as well. You can play around with that. For now let's stick with these values and see how we like that. And then the last thing we're going to do is to save the shell as a prefab, as I said before we don't want it to be in the game when it begins. So I'm going to select my Prefabs folder. I'm going to drag my shell and drop it in to the empty space in that folder. So really we should check if this works, so I'm just going to briefly save my scene and demonstrate what you should be seeing. So if I press Play right now my shell should fall down and because it's pretty near the tank take off quite a lot of damage. Take off a lot of health, sorry, apply a lot of damage. We've applied the shell explosion, in order to populate the particle effect and the audio source on to those two different variables. And then we've made it in to a prefab so now, as mentioned before, we don't need that shell in the game. Delete it out of your scene. Delete on PC, command-backspace on Mac and then save your scene. One more time, select the shell. delete it and then save your scene. Okay, so that's the end of phase 5. Then the next phase we're going to deal with actually shooting these projectiles. A little bit of physics and a bit more UI.