TANKS! Unity Tutorial - Phase 6 of 8 - Firing Shells

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Okay, so in this phase we're going to add a particular point at which we want these shells to be created. We call that a fire transform and we call it that because it's just an empty game object that just has a transform component on it and we put that in front of the barrel of the gun. Then we're going to use UI, we're going to use the slider yet again, we're going to sort of re-appropriate it to create this effect, we're going to put a canvas in front of our tank and we're going to use a slider as a thing that defines this arrow that shows you how much force you're putting in to a shot. And it's going to vary, so depending on how long you hold down the shot it's going to fire over different distances. First thing is to select our tank. And as we stated before there's a number of different ways to do anything in Unity. Making a new object is yet another one of those. So you can click on the Create menu on the hierarchy, you can click the Game Object menu, but if you want to do things directly and parent them at the same time you can right click on existing game objects. So I want to create a child object of a tank so I right click on my tank and I go to Create Empty. That places a new empty game object on to my tank, I'm just going to rename this FireTransform. And then I'm going to give you a position and rotation to put it exactly in front of the gun barrel and then rotate it the right way. So the position for this is (0, 1.7, 1.35) and then the rotation is (350, 0, 0). Yet again it's easier to see on the slides so I'm just going to switch there. So position (0, 1,7, 1.35). Rotation (350, 0, 0). So just to unobstruct that a little bit. The position of the FireTransform, we don't want it to be left or right so the exposition is of course going to be 0. Because the barrel is in the middle of the tank. We want it to be up a little bit, so that's why it's 1.7 up in the Y axis. And we want it to be in front of the tank, not at the back or anywhere else so that's why it's a little bit forward in the Z axis. So if you've done it right it should look something like this. Just in front of it at roughly the same angle as the artwork implies. And just forward so we're not creating the shell so that it's going to intersect the collider and detonate straight away. That would be bad. As I said this requires a little bit of UI work in order to get the arrow to show the player how much they're firing their shell by. So we're going to right click on our canvas now. So if you reselect the canvas that we've got on the tank, and then right click, we're going to create a UI slider. So right click on the existing canvas, we don't want to make a new canvas, we can use the same one that we've got. Create a UI Slider. And we can rename this straight away to AimSlider. So I'm just going to zoom out and show you what this looks like. Yet again it's our old friend the slider. Not aware of what we want to do with it at all. We're going to, basically make this a small strip that's going to exist in front of the tank. And we're going to hold down in order to increase the value on that slider and therefore increase the amount to which the arrow is shown. So what we want to do is alt-click on AimSlider on the arrow to expand everything, so remember when we did this on the canvas before we alt-click the arrow left of it's name to expand everything at once. Then as before we need to get rid of the Handle Slide Area because we don't want to be dragging this around, it's just based on the Fire button in the game. So I'm going to select Handle Slide Area and delete it, therefore deleting the handle as well. So command-backspace on mac, delete on pc. And then we also don't need the Background of this slider because we just want it to be invisible when they're not firing and then just emerge as soon as they start firing. So I'm going to select the background. And delete it. You should be left with Aim Slider, Fill Area and Fill. A quick reminder, so we right-clicked on our Canvas, that's our existing canvas that we used for the Health slider and we added a new object to it, so when you're working with the UI system be aware that you invariably will just create just one canvas and many things within it. So it's the same for screen space UI as it is with our world UI that we're doing. So then we've renamed it AimSlider and we've expanded everything and removed the Background and Handle Slide Area game objects. Then we need to make this not intractable. Yet again it's just something that's controlled by a script, we're not going to be dragging on screen with a mouse or anything like that. So I'm going to reselect my AimSlider and look at the Slider component in the inspector on the right. I'm going to uncheck Intractable and because I don't want it to animate during any interaction because we don't want any interaction we set Transition to None and that's going to remove all of those transition properties for you. Then finally we're going to set this up based on the bottom being near the barrel of the tank and then the top being furthest away from the tank. So the Direction as we call it we'll say is 'Bottom to Top'. Then we're going to set the Min and Max values from 15 to 30. And we can leave our Minimum Value at 15. So we want it to start off and then draw this thing out to a certain amount, and you'll see that once we start doing it. So we don't want it intractable, there's no transition, it needs to render from bottom to top once we've setup the position for it, which you'll see shortly. And we have minimum and maximum values for that slider. Okay, so then yet again we need to setup this slider in context of it's parent. So the parent of this slider is the canvas. Yet again it's a quick way to get things roughly in the right size is to just stretch them over their parent then you can start resizing them and stretching them to where you want them to be. So that's exactly what we're going to do right now. So what we're going to do is multi-select the AimSlider and the Fill Area, just those two. Then if you look at the rect transform yet again we have these anchor presets. So just to remind you these are ways of stretching out where that UI element will exist and also you can position them at the same time using alt, which is exactly what we'll do. So if we select that anchor preset and hold down alt, you can see if I tap alt now we are stretching and positioning. So I'm going to right-click the lower right stretch option there. Then what you'll see is it's getting roughly in the right place now and it's now based under our tank. Then I'm going to expand my Fill Area if I haven't already so I can see the fill. So with the Fill selected, that's the image that we want to actually project, so we've made an arrow for you guys in Photoshop that's just got a gradient fade to the bottom of it. And we've already sliced that up in the sprite editor in Unity, just to show you that really quick. It looks like this. There's our AimArrow, and with the sprite editor what you can do is basically define which areas are going to be sliced and stretched. So what you'll notice is we've got this entire area at the top, which is fine, and then the outer area is defined as well, but in the middle we've got this small space in which we can stretch. That's already setup for you guys, you don't need to worry about that, I just wanted to show it to you. So with that Fill game object we're going to setup it's visual area. So the first thing I'm going to do is to remove this value of 10 from the Height. So I don't want it to be any distance from it's parent at all so I'm just going to zero that out totally, set the height to 0. Then on the Fill game object there's also the actual image itself. So you'll see an image component. In Source Image I'm going to choose that Aim Arrow, So click to the right of Source Image it currently has this default UI sprite thing we don't want. Click on Aim Arrow there. So you won't be able to see anything just yet, we haven't quite finished it. Okay, so we've selected AimSlider Fill Area and we've stretched them over the canvas, the parent, that's what we've done there, remember alt-click to stretch them out. And then we've expanded that Fill Area and selected the Fill and we've set the height to 0 to remove any offset from the parent Rect. So when I say the parent Rect I'm just referring to whatever's directly above it, in this case it's the Fill Area. And then on the Fill game object we've used circle select to choose the Aim Arrow. So we're going to go back to the Aim Slider right now and what you should see is that if you select the rect tool, so the 5th one at the top here. So these tool by the way are Q, W, E, R, T if you're on a QWERTY keyboard then that's how you can just switch between those tools. So the fifth one there is the tool you want. That will help you see these dots and allow you to drag things out. So what I'm going to do is just move my scene view around so you can of course drag around with the first hand tool, but if you're on another tool, such as the rect tool you can hold down alt to orbit around what you're looking at. So if I alt and then drag around I can see what I'm doing. I'm just doing this to get myself some kind of overhead view. Another way to do that of course is to click on the Y spoke of the gizmo in the top right there, and then tap the centre cube to change in to a totally flat view overhead. Because what I'm trying to do is this, and I'll show you it quickly and then we'll go back through it. I'm going to drag the outer bounds in so that they're roughly on the edge of the tank. I'm going to drag it a little bit longer and then I'm going to drag it up so that it's snapped on the front of the tank. Something like that. Then I'm going to orbit around so that I'm in an orthographic isometric view right now. And then I'm going to drag with my translate tool I'll drag back in the Z axis just to bring the up a little bit. So it's just slightly off the ground, like that. I'm going to go back a few steps and run that by you again. So once more, with my rect tool I'm just dragging in the bounds, so remember we're on the Aim Slider, make sure you've got the Aim Slider selected. Drag in the left and right edges. Make it a little bit taller, drag it forward, this doesn't need to be precise by the way, it can just be a design choice, so you might have a slightly more extended arrow than anyone else does on their tank, but as long as that slider is going from between those two values it'll function the same as everybody else's game. And then all I've done to bring that up off the ground, because the rect tool deals with 2D specifically we have to jump back to the translate tool, drag the blue arrow backwards to bring it up off the ground and you should end up with something that looks like this. Of course save your scene throughout. Just to make sure you're up to date. And if you do want the exact same values that we intend you to use I'll give you those values now. Though I've just done this by hand, but if you wanted to just type them in to the inspector our values would be 1, -9, -1, 1 and 3. It would look something like that. So remember this is the Aim Slider, 1, -9, -1, 1, 3. And as before, because it's a slider and the slider is controlling how the image will behave, if I drag my value on the slider you'll see that my arrow is doing what it should do. So you can test it out that way. Make sure you leave it back on the lowest possible value to the left with that slider once you've tested it out. We have our Aim Slider setup and we're ready to start actually firing shells, which is exactly what we need for this tank shooter, otherwise it will just be a tank, something. Okay, so, in our Scripts folder if you pop that open you'll find something called Tank. We've been in there before, this time we need TankShooting, and we're going to just drag and drop that on to the Tank game object. So I can basically collapse my tank right now, just click on the arrow next to it's name, and then I'm going to drag TankShooting and drop it on to the Tank. I'm just going to collapse my other components so that you can see it more easily now. So we have our TankShooting there and we're ready to start editing it. You'll see there's a number of different public variables which we're ready to populate but we'll talk about those in context of the script that way when we come back and populate them they have some meaning. So if you double click on TankShooting to open it we are ready to edit. So like we've had before, there are some blocked comments that we need to get rid of before we can continue. Yeah, let's do that first. So on line 17 and line 37 there should a /* and a */ Easy for you to say! Okay, so that's all the comments done. Let's go through those public variables and find out what they mean. So like we had with the TankMovement script, we have a PlayerNumber because we need some input in this class so we need to know which input axis we need to reference. In this case it's going to be fire1 for player1, fire2 for player2, etcetera. So that's why we need that. We need a reference to the Shell prefab that we're going to instantiate so we've got that rigidbody Shell there. So remember this isn't a reference to the rigidbody, because we only want to affect things about that rigidbody we can just refer to that as the prefab. Okay, and we need a reference to that place that we're going to fire the shells from, that FireTransform, so that's what that references there. Obviously we need a reference to the slider to make it grow and shrink. We need a reference to the second audio source on the tank, the one that's going to play the sound effects for shooting. So that's what that audio source is there for. And we need to know what clips that audio source is going to play so we need a reference to those two audio clips, one for charging up the shot and one for actually firing it. And so now we've got a few float variables. We've got the minimum and maximum launch force/ You'll remember the values of the slider we gave you were 15 for minimum and 30 for maximum? So that is going to correlate like we did with the health we did from 0 to 100 for health, we're doing 15 to 30 for the LaunchForce. If you want to change the LaunchForce, change them both here and on the slider. We don't recommend you do that because it starts bumping in to things like the tank if you go too fast, that sort of stuff. Let them discover it on their own! You can try tweaking stuff, we won't be upset, but yeah, we've found these to be good values for now. So the last public float is how long is it going to take to get from the minimum launch force to the maximum launch force? So about 3/4 of a second to go from minimum charge where you're just, just shooting the shells, just about to really firing them across the screen, takes about 3/4 of a second. Based on that time and how much charge we need to build up we're going to calculate how fast that needs to go. And that's going to be called the ChargeSpeed, and that's our third private variable down there, but the ones before that, if you remember the input axis are strings so input buttons are also strings, so we've got one for the fire button there, which we'll store based on the PlayerNumber. And we need to keep track of how much we've charged up the shot so far, so that's the CurrentLaunchForce, how much have we built up so far. And the last one is whether or not we've fired yet. Because we don't want to fire multiple times, we want to do it once per button press. So the next function we've got there is OnEnable, so that's when the tank is turned back on after being killed. We're setting the CurrentLaunchForce back to the minimum and we're setting the AimSlider's value back to the minimum. So when you're alive you're not already charging a shot, you just start again. Then we've got the Start function. So again this is called right at the start, only once, OnEnable might be called multiple times if you die multiple times but Start will only be called once so we're calculating the Fire button, and that's equal to the string Fire plus a number based on the PlayerNumber. So Fire1for Player1, Fire2 for Player2, etcetera. Just a quick reminder, in the input settings, those are the things I was talking about earlier, so Fire1 there, we just take the PlayerNumber and put it on the end and it then references this which gives us, in this instance, the spacebar. So the last thing we're doing in Start there is calculating the ChargeSpeed, so if you remember Speed equals Distance over Time, this is the same thing, the distance that we've got to cover is from the minimum to the maximum LaunchForce and the time we've got to do that is the ChargeTime. So Speed is the distance we've got to cover over the time, that's how we're calculating that. So next we've got the Update function. Now the Update, what it needs to do is take care of all the inputs, so when the button is being pressed for the first frame, when it's being held down, and when it's being released, it also needs to take care of the account when you've held it for too long and you've reached the maximum and then you need to fire. So to do that we're going to have a series of if else statements to make sure we're catching all the cases. But the first thing we need to do is make sure that the AimSlider's default value, so every frame we're going to set the default value of the AimSlider back to the MinimumLaunchForce. So by default AimSlider is invisible at it's most minimum value. And then if we decide that it needs to be at a different value we can set it then. The first if statement that we're going to write is if(m_CurrentLaunchForce >= m_MaxLaunchForce and, so that's &&, we have not yet fired, so !m_Fired So that's the case, we have charged up to the maximum, and we've not yet fired so we need to do something about that, so what we're going to do is we're going to write all of these if statements so we can take care of the cases and then come back at the end and go through what we actually need to do in those cases. So I'm just going to put in a single line comment just to remind you what you're doing, you can write that in or not, it's up to you. So at the maximum amount of charge but not yet fired. So after that we have an else if statement, else if( and in this case we're dealing with when the button is first pressed so when the button is first pressed Input.GetButtonDown is returned true. So you get ButtonDown is when it's first pressed. And the button that we want to check is the Fire button, so m_FireButton. Okay, and if we have not reached the maximum charge and we've not just pressed the button, then we might be holding the button, so the next else if statement is Input.GetButton So that's saying 'is the button currently held?' But we need to check if it's currently held that we haven't fired already, because we might have hit the maximum launch force and then not fired it, so we need to check for that. And the last else if statement is, you might have guessed it, if you've released the button. So in this case it would be else if(Input.GetButtonUp(m_FireButton) and again we need to check that we've not yet fired. So you might have noticed that all of them are checking that we've not yet fired, apart from when we've first pressed the button, and that's because when we first press the button of course we haven't fired, we've just pressed the button. Okay, so let's go back through those and think about what we actually need to do then. So in the first case we've gone beyond the MaxCharge and we've not yet fired. So what we really need to do is fire, but we don't want to do it beyond the maximum charge, we want to do it at the maximum. So what we'll do is we'll set the CurrentLaunchForce to the MaxLaunchForce so that it's not over the top, and we'll call the Fire function, which is a function which we'll write in a little bit. Then if we've just pressed the button for the first time then we know that we have not yet fired. So m_Fired is false, we've not fired yet. And we also know if we just press the button that the LaunchForce should be at it's minimum. So we'll set CurrentLaunchForce equal to MinLaunchForce. Also when we've just pressed the button we want to start playing a sound effect that related to charging up, so, what we'll do is set the ShootingAudio clip to the ChargingClip, so m_ShootingAudio.clip = ChargingClip And we'll play that audio clip, so m_ShootingAudio.Play Okay, so the next one is if the button is being held, so if the button is being held we don't want to fire but we do want to update how much the charge has gained. So what we're going to do is set the CurrentLaunchForce to itself plus ChargeSpeed times delta time. So to do that we do += m_ChargeSpeed * Time.deltaTime So remember that +=, what it's doing is is saying 'add this to it's current value'. It's saying 'set this to itself plus a little bit extra'. With that new CurrentLaunchForce that we've just increased we'll set the AimSlider's value to the CurrentLaunchForce. So similar to the HealthUI that we did before we're effectively setting the value and then refreshing the actual visual element of it by setting the slider's value. Okay? And the last case that we need to deal with is if you've released the button you fire, that's it! So we'll just quickly go over that. First off we're resetting the value to a default value and then we'll only change the AimSlider based on the button being held. Or pressed, or released. Yes. If the CurrentLaunchForce is greater than the maximum we'll set it back to the maximum and then fire based on that. If the button is being pressed for the first time then we have not yet fired, so fire gets set to False. And then CurrentLaunchForce gets set back to our minimum. We also play the correct clip for that situation. If the button is being held and we've not yet fired, so that's GetButton for held, then we'll increase the LaunchForce by the ChargeSpeed multiplied by Time.deltaTime. And we will set the AimSlider's value appropriately. Finally, if we've released the button then we'll fire. Why don't you set any other audio conditions? That's a good question, the question if you didn't hear was 'why don't we set other audio conditions?' So basically the way this works is we have an audio clip that's kind of incremental, a kind of charging sound, and what happens with that is that when we write the Fire function in a moment we're going to play a different clip, so what we do is interrupt it effectively with the sound of it firing. So that's effectively cutting it off and replacing the clip with another, and that will take care of the rest of the audio in that scenario. That's a good question. Okay, so let's move on to the Fire function. So what we need to do here is instantiate the shell and give it a velocity based on how much we've charged up. So the first thing, when we've fired of course Fired = True. So that's going to deal with all the logic above that we've just put in. And the next thing we need to do is actually instantiate a shell, so we're going to use that instantiate function again, but we're going to use it's return type. So we're going to say that a rigidbody called ShellInstance is equal to Instantiate, the thing that we're going to instantiate is the shell, so m_Shell, we're going to instantiate it at the FireTransform's position so m_FireTransform.position And we're going to instantiate it at the FireTransform's rotation as well. So it's m_FireTransform.rotation. So that's the last parameter that we've got there. But instantiate actually returns something just an object, it doesn't return a rigidbody naturally. So in order to assign it a rigidbody what we do is we say as Rigidbody at the end. And what that'll do is it'll say 'I've created an object, can I treat this as a rigidbody? Well it's got a rigidbody component, so yes, and I'll return that'. So effectively this is doing two things at once, we're instantiating and we're placing the rigidbody in to the scene and we're also assigning it to a variable that we can give a velocity. Okay, so let's do that. So ShellInstance is a rigidbody so it has a velocity, now a velocity has a type of vector3 so what we're going to do is give it a direction, which is the FireTransform's forward direction, and a magnitude, which is the CurrentLaunchForce. So we'll do m_CurrentLaunchForce * m_FireTransform.forward So all that's saying is 'in the forward direction of the FireTransform with an amount equal to the CurrentLaunchForce. So that's launched the shell, all successfully, but we do need to change the audio that's playing as we were just mentioning earlier. So ShootingAudio.Clip gets set to the fireClip. And that will automatically stop the audio source from playing. So we need to play the audio source with the new clip. So m_ShootingAudio.Play. And the last thing we need to do, well we don't need to, this is more of a safety catch, is we're setting the CurrentLaunchForce equal to the MinLaunchForce. So that's just making sure that if some button press sneaks in there then we're not going to launch it twice with maximum velocity or something. That is the bottom of that script so do save, switch back to the editor, have a look at the console for any errors that you might have. Cool, okay, wonderful. Let's hope that I got it right! Which I did. Okay, so reselect the Tank and we need to populate this, so as many of you are probably discovering as you're running ahead and trying to press play and hoping to shoot things it won't work just yet, because we haven't assigned those public variables that we need to. So on TankShooting we need to assign a few things, so our shell you'll remember is a prefab, so delve in to the Prefabs folder in to project and grab your Shell prefab and drop it on to where it says Non (Rigidbody). That will assign it there. Then the Fire Transform is a child of the Tank, if you expand the Tank you will find FireTransform. Drag and drop that on. Likewise with the Aim Slider, the AimSlider is the game object to assign there. And then Shooting Audio is the slightly trickier one. I'm grabbing the second audio source so the title, make sure you collapse and it's a lot easier to do, grab the title of that component, drop it on to the variable Shooting Audio. So grab the component name, drop it on there. And the last two should be fairly self explanatory, they're just two audio clips, ChargingClip, use the circle select ShotCharging. You can use circle select whilst the window is still open to just switch to assigning something else. I'm just going to select that and ShotFiring for the second one. So it should be assigned and it should look like that. Okay, so what I would like you to notice is that with the tank we've added a few things to the tank since we last updated the prefab, and as we know when we don't update a prefab we have things that are in grey and not in blue to indicate that they're part of the prefab version that's saved in the project. So with the Tank selected I would like you to hit Apply at the top of the inspector to update that prefab, it's very important that the version in the project is the finished version that we've made so far. So hit Apply at the top of the inspector then all of the child objects underneath that, so remember you can alt-click the arrow to expand all, they should all be in blue right now. So Apply with the tank selected. Okay, so the tank is now finished. But we don't want it to stay in the scene. We do want to just make sure it works, So I'm just going to hit Play. I'm just going to turn my volume down, or off. Actually I'm going to leave it on so you can see how it's meant to sound like. The keen-eared among you will notice that the mix is terrible, you can't really hear the charging and the shooting, we'll fix that at the end with audio mixing, so that's all going to sound great by the time we're finished so don't worry about that. But for now you should just be able to drive the tank around, charge up a shot, or do small shots. Or you can so what Mike likes to refer to as as death lotus, this move. But once you've done that the tank is complete. Once you've hit apply we're going to get rid of it out of the scene, it's finished, it's ready to be used by the game manager. So I'm going to select my tank, make sure you've updated, saved your prefab. Command-backspace to delete it, or delete on PC, save your scene once you've got rid of your tank. Subtitles by the Amara.org community
Info
Channel: Unity
Views: 82,485
Rating: undefined out of 5
Keywords: unity, shoot, tank, projectile, bullet, rocket, grenade, bomb, tutorial, lesson, lecture, unite, boston, training day, firing, shooting
Id: _In3KT97aTw
Channel Id: undefined
Length: 31min 49sec (1909 seconds)
Published: Wed Oct 14 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.