< Return to Video

TANKS! Unity Tutorial - Phase 5 of 8 - Shells

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

more » « less
Video Language:
Korean
Duration:
32:02

English subtitles

Revisions