WEBVTT 00:00:00.000 --> 00:00:04.295 In Unity 4.3 we're launching our first set of 2D features. 00:00:04.295 --> 00:00:06.295 To compliment this we have constructed a 00:00:06.295 --> 00:00:08.295 demo project with these tools. 00:00:08.295 --> 00:00:11.527 Our 2D platformer is nicknamed 'Tower Bridge Defence' 00:00:11.527 --> 00:00:13.776 It depicts London's Tower Bridge in the midst 00:00:13.776 --> 00:00:15.556 of an alien invasion. 00:00:15.556 --> 00:00:17.955 It's a completely sprite-based, physics driven 00:00:17.955 --> 00:00:20.216 2D sample level that we hope will help you 00:00:20.216 --> 00:00:23.472 understand how 2D games are put together in Unity. 00:00:23.472 --> 00:00:25.472 This video will discuss the background and 00:00:25.472 --> 00:00:28.184 foreground construction, characters, effects, 00:00:28.184 --> 00:00:30.184 camera tracking, animation and scripting 00:00:30.184 --> 00:00:31.639 used in the demo. 00:00:31.639 --> 00:00:33.639 To begin with, let's discuss the basics 00:00:33.653 --> 00:00:36.139 of working in 2D in Unity. 00:00:36.860 --> 00:00:39.291 Firstly, when working in 2D, you should set the 00:00:39.291 --> 00:00:41.221 Editor Behaviour Mode to 2D 00:00:41.221 --> 00:00:43.040 for various settings. 00:00:43.040 --> 00:00:45.040 This can be done when making a new project 00:00:45.040 --> 00:00:47.040 using the drop-down on the project wizard 00:00:47.040 --> 00:00:49.543 or during a project by choosing 00:00:49.543 --> 00:00:53.172 Edit - Project Settings - Editor from the top menu. 00:00:53.172 --> 00:00:55.172 This means that by default textures 00:00:55.172 --> 00:00:57.172 will be imported as sprites and the 00:00:57.172 --> 00:00:59.630 Scene View will default to 2D mode. 00:00:59.630 --> 00:01:01.630 This new mode gives you a completely orthographic 00:01:01.630 --> 00:01:04.420 view in which to construct 2D games. 00:01:04.420 --> 00:01:06.806 It also hides the usual 3D gizmo 00:01:06.806 --> 00:01:09.197 in the top right of the view, giving you more space 00:01:09.197 --> 00:01:11.941 to work in. Aside from these settings the work 00:01:11.941 --> 00:01:14.244 flows for 2D have been designed to mirror 00:01:14.244 --> 00:01:17.040 existing Unity approaches to 3D game creation. 00:01:17.040 --> 00:01:19.040 So if you already know a little about Unity 00:01:19.040 --> 00:01:21.040 you'll be in a great position to start making 00:01:21.040 --> 00:01:22.929 2D games right away. 00:01:22.929 --> 00:01:24.929 It's worth noting at this stage that you can 00:01:24.929 --> 00:01:27.219 still mix 2D and 3D in Unity, 00:01:27.219 --> 00:01:29.722 so if you want to add 3D elements to your 2D game 00:01:29.722 --> 00:01:32.870 or vice versa you can do that with no worries. 00:01:33.366 --> 00:01:35.496 Let's take a look at the demo project itself, 00:01:35.496 --> 00:01:38.312 and how we built it up one stage at a time. 00:01:38.812 --> 00:01:40.812 We began by sketching out the level design 00:01:40.812 --> 00:01:42.812 for this sample level and then went about 00:01:42.812 --> 00:01:44.812 recreating the layout in Photoshop. 00:01:45.312 --> 00:01:47.312 Creating and exporting the layers, 00:01:47.312 --> 00:01:49.312 we were able to import these in to Unity 00:01:49.312 --> 00:01:51.312 using the new Sprite type. 00:01:58.373 --> 00:02:01.306 In order to create parallaxing in our background later, 00:02:01.306 --> 00:02:03.666 we kept some of the background elements separate 00:02:03.666 --> 00:02:06.515 and placed them on to a Background Sorting Layer. 00:02:06.515 --> 00:02:09.658 Yet another new feature of 2D development in Unity. 00:02:10.158 --> 00:02:12.841 Having assigned all of our backgrounds to this layer, 00:02:12.841 --> 00:02:15.157 we could then use the Order In Layer property 00:02:15.157 --> 00:02:17.379 of the Sprite Renderer to sort them. 00:02:17.379 --> 00:02:19.379 Once we were happy with their positions 00:02:19.379 --> 00:02:21.379 we could lock the Background Sorting Layer 00:02:21.379 --> 00:02:23.379 so that when we added foreground elements 00:02:23.379 --> 00:02:25.379 we didn't need to worry about accidentally 00:02:25.379 --> 00:02:27.751 dragging background elements around. 00:02:27.751 --> 00:02:29.751 This is done using the Layers pull-down in the 00:02:29.751 --> 00:02:31.751 top right of the interface. 00:02:32.817 --> 00:02:35.531 Because the background elements are purely decorative 00:02:35.531 --> 00:02:37.531 we did not require any additional components 00:02:37.531 --> 00:02:39.531 on the sprite game object. 00:02:39.531 --> 00:02:41.531 They were parented to an empty game object 00:02:41.531 --> 00:02:44.201 that has a simple script to handle parallaxing 00:02:44.201 --> 00:02:46.201 called BackgroundParallax. 00:02:46.201 --> 00:02:48.643 For more information you'll find this script 00:02:48.643 --> 00:02:50.643 fully commented in the Scripts folder. 00:02:54.914 --> 00:02:56.914 Next up came the creation of the foreground elements 00:02:56.914 --> 00:02:59.400 that our characters would actually traverse. 00:02:59.790 --> 00:03:02.280 We designed London's Tower Bridge with a UFO 00:03:02.280 --> 00:03:03.466 landed in the centre. 00:03:03.466 --> 00:03:05.466 The character has the run of the environment 00:03:05.466 --> 00:03:07.466 as enemies spawn from the skies and begin 00:03:07.466 --> 00:03:09.216 to navigate around the level. 00:03:09.216 --> 00:03:11.216 As such, each piece of the foreground required 00:03:11.216 --> 00:03:13.632 a collider for characters to walk upon. 00:03:13.632 --> 00:03:15.632 For most of the environment we used 2D 00:03:15.632 --> 00:03:17.632 box colliders for efficiency, 00:03:17.632 --> 00:03:21.239 but the UFO itself has a more complex shape. 00:03:22.505 --> 00:03:24.505 Unity's Polygon Collider allowed us to 00:03:24.505 --> 00:03:26.878 automate creation of the collider itself 00:03:26.878 --> 00:03:28.724 based on the shape of the sprite. 00:03:28.724 --> 00:03:30.724 It even meant that we could tweak the shape of 00:03:30.724 --> 00:03:32.053 the collider later. 00:03:32.053 --> 00:03:34.164 Moving, adding or subtracting points 00:03:34.164 --> 00:03:36.164 of the collider shape to make it more 00:03:36.164 --> 00:03:38.164 appropriate to walk over. 00:03:38.664 --> 00:03:40.664 To sort these foregrounds we created a 00:03:40.664 --> 00:03:43.154 Foregrounds Sorting Layer, which was drawn 00:03:43.154 --> 00:03:45.599 above the backgrounds in the Tags And Layers manager. 00:03:48.875 --> 00:03:50.875 Next, let's take a look at our hero. 00:03:53.709 --> 00:03:55.598 Our player character was yet again designed 00:03:55.598 --> 00:03:57.598 in Photoshop, and for this demo 00:03:57.598 --> 00:03:59.598 we chose to make a character with independent 00:03:59.598 --> 00:04:01.598 limbs and features in the style of 00:04:01.598 --> 00:04:03.598 2D hits such as Rayman. 00:04:03.598 --> 00:04:05.598 Our other option would have been to design 00:04:05.598 --> 00:04:08.140 a sprite sheet-based animation and design each 00:04:08.140 --> 00:04:09.643 each frame in Photoshop, 00:04:09.643 --> 00:04:12.365 an approach we use later for the background Swan, 00:04:12.365 --> 00:04:14.365 which we'll discuss later in the video. 00:04:15.072 --> 00:04:17.072 Because our character had independent elements 00:04:17.072 --> 00:04:20.196 that we wish to animate we finalised the design 00:04:20.196 --> 00:04:22.196 and then moved his bodily elements in to separate 00:04:22.196 --> 00:04:25.408 spaces on our canvas to allow Unity to isolate them 00:04:25.408 --> 00:04:27.959 as separate sprites in the Importer. 00:04:28.763 --> 00:04:30.763 This meant that we could then arrange all of 00:04:30.763 --> 00:04:33.096 our sprites as separate elements to be animated. 00:04:33.096 --> 00:04:35.495 We placed these on to a new Character Sorting Layer 00:04:35.495 --> 00:04:38.167 that we created, and then used Z values in the 00:04:38.167 --> 00:04:40.921 transform to sort their rendering depth. 00:04:48.811 --> 00:04:50.811 All of these sprites are then arranged under an 00:04:50.811 --> 00:04:52.811 empty game object, which has all of our 00:04:52.811 --> 00:04:56.591 controls scripting, colliders, physics, excetera attached to it. 00:04:56.591 --> 00:04:58.591 Once we'd done this we were able to use the newly 00:04:58.591 --> 00:05:01.041 upgraded Animation window to create 00:05:01.041 --> 00:05:03.906 Idle, Run, Jump, Shoot and Death animations 00:05:03.906 --> 00:05:07.095 by animating each of the character's sprites over time. 00:05:07.095 --> 00:05:09.795 With the new Dopesheet View in the Animation window 00:05:09.795 --> 00:05:11.795 this is easier than ever. 00:05:13.414 --> 00:05:16.006 We simply add animation to the parent object 00:05:16.006 --> 00:05:19.403 and then create keyframes for any of the child objects. 00:05:19.403 --> 00:05:21.403 Moving the playhead to where we want 00:05:21.403 --> 00:05:23.403 and then moving the various parts of the character 00:05:23.403 --> 00:05:25.403 to automatically keyframe the animation. 00:05:27.313 --> 00:05:29.644 The ability to switch between Curve and Dopesheet 00:05:29.644 --> 00:05:32.448 representation of our animation makes it easier than 00:05:32.448 --> 00:05:35.064 ever to adjust timing and design. 00:05:36.730 --> 00:05:38.730 With these animations created we can 00:05:38.730 --> 00:05:41.370 then design a state machine for our character 00:05:41.370 --> 00:05:43.801 so that when called upon in code, differing animations 00:05:43.801 --> 00:05:45.277 could be played. 00:05:45.277 --> 00:05:47.277 the animator controller for the character is 00:05:47.277 --> 00:05:50.574 not driving a 3D biped, so we simply deselect 00:05:50.574 --> 00:05:53.673 Apply Root Motion and select Animate Physics 00:05:53.673 --> 00:05:55.673 in order to drive our animations in time with 00:05:55.673 --> 00:05:57.287 the physics engine. 00:05:57.287 --> 00:05:59.858 In order to traverse the environment our hero has a 00:05:59.858 --> 00:06:02.231 circle collider at his feet and a box collider 00:06:02.231 --> 00:06:04.564 to cover the rest of his body outline. 00:06:04.564 --> 00:06:07.067 This means he can smoothly walk up and down hills 00:06:07.067 --> 00:06:09.454 and when he jumps his head will hit the ceiling. 00:06:09.802 --> 00:06:12.537 In order to control the character and it's animations 00:06:12.537 --> 00:06:16.038 we wrote a script that moves him via 2D physics forces. 00:06:16.038 --> 00:06:18.038 This means that we can apply physics to him 00:06:18.038 --> 00:06:20.038 and the enemies during the game for more 00:06:20.038 --> 00:06:21.427 dynamic game play. 00:06:21.427 --> 00:06:23.814 In our PlayerControl script for the character 00:06:23.814 --> 00:06:25.814 we check for player input. 00:06:25.814 --> 00:06:27.814 We use this to apply physics forces 00:06:27.814 --> 00:06:30.766 for movement and also send the value of the input 00:06:30.766 --> 00:06:33.487 to the animator, which in turn defines which 00:06:33.487 --> 00:06:36.475 animation should be playing and smoothly transitions 00:06:36.475 --> 00:06:38.475 between the different animation clips that 00:06:38.475 --> 00:06:40.475 we've created as states. 00:06:40.475 --> 00:06:42.475 The great thing about using the animator to 00:06:42.475 --> 00:06:44.475 create states from animation clips is 00:06:44.475 --> 00:06:46.861 that we can go and tweak speeds of animation 00:06:46.861 --> 00:06:48.861 to match our physics velocities 00:06:48.861 --> 00:06:51.278 without having to reanimate anything 00:07:23.129 --> 00:07:25.129 The FixedUpdate function evaluates with 00:07:25.129 --> 00:07:27.588 each physics step, and the first thing we 00:07:27.588 --> 00:07:29.588 do with this is to feed the value of Horizontal 00:07:29.588 --> 00:07:32.994 input in to the Speed parameter of our animator. 00:07:33.950 --> 00:07:35.950 The transition between Idle and Run 00:07:35.950 --> 00:07:37.950 in our simple state machine requires 00:07:37.950 --> 00:07:41.718 that the Speed parameter is above 0.1. 00:07:41.718 --> 00:07:44.025 When it is, the animator blends from Idle 00:07:44.025 --> 00:07:46.025 in to the Run state. 00:07:51.857 --> 00:07:53.857 We then go on to add forces to the player's 00:07:53.857 --> 00:07:57.184 2D physics component, the rigidbody2D, 00:07:57.184 --> 00:07:58.822 in order to move him around. 00:07:59.626 --> 00:08:02.521 We also handle which direction the character is facing 00:08:02.521 --> 00:08:04.702 based on the value of Horizontal input, 00:08:04.702 --> 00:08:07.710 checking whether it is above or below 0. 00:08:07.710 --> 00:08:10.557 This is because in Unity, holding the left input key 00:08:10.557 --> 00:08:14.573 returns a value of -1, where right returns positive 1. 00:08:15.073 --> 00:08:18.700 Depending on input, we then call a simple flip function, 00:08:18.700 --> 00:08:21.477 which reverses the X scale of the character, 00:08:21.477 --> 00:08:24.566 giving him the appearance of facing the opposite direction. 00:08:26.848 --> 00:08:28.848 To decide whether the player is grounded 00:08:28.848 --> 00:08:31.605 we added a layer in Unity called Ground 00:08:31.605 --> 00:08:34.982 and applied it to all of our walkable foreground surfaces. 00:08:43.397 --> 00:08:45.969 We then used the Linecast function in 2D 00:08:45.969 --> 00:08:47.969 to check whether something on the Ground layer 00:08:47.969 --> 00:08:50.234 is below the character's feet. 00:08:50.234 --> 00:08:52.777 To customise this more easily we created 00:08:52.777 --> 00:08:54.777 an empty game object to use as a point 00:08:54.777 --> 00:08:56.777 at which to check for the ground. 00:08:56.777 --> 00:08:59.083 By adding a gizmo to this empty object 00:08:59.083 --> 00:09:01.083 we are able to manipulate how far below 00:09:01.083 --> 00:09:03.083 the character we'll check for the ground. 00:09:03.083 --> 00:09:05.486 From a gameplay perspective this means that 00:09:05.486 --> 00:09:07.958 the character can only jump when grounded. 00:09:08.456 --> 00:09:10.456 Check out the rest of the comments in the script for more 00:09:10.456 --> 00:09:12.648 information on the control of the player. 00:09:12.648 --> 00:09:14.648 We will discuss the player's weapon 00:09:14.648 --> 00:09:15.879 later in this video. 00:09:15.879 --> 00:09:17.879 Next, let's take a look at how the camera 00:09:17.879 --> 00:09:19.879 tracks the player in our demo. 00:09:21.291 --> 00:09:24.352 In 2D games, much like 3D, the motion of 00:09:24.352 --> 00:09:26.352 the camera tracking the action can make 00:09:26.352 --> 00:09:27.824 or break your game. 00:09:27.824 --> 00:09:30.581 For a classic 2D platformer, we looked at the mechanics 00:09:30.581 --> 00:09:33.625 of one of the most interesting camera in 2D gaming history, 00:09:33.625 --> 00:09:36.651 the camera from Super Mario World on the Super Nintendo 00:09:36.651 --> 00:09:38.651 or Super Famicom. 00:09:38.651 --> 00:09:40.651 In Super Mario world the camera tracks 00:09:40.651 --> 00:09:42.651 horizontally, but uses a dead zone 00:09:42.651 --> 00:09:45.119 or margin in the centre of the viewport 00:09:45.119 --> 00:09:47.119 in which the character can move a little 00:09:47.119 --> 00:09:49.342 without the camera tracking. 00:09:49.342 --> 00:09:51.635 Once the character moved beyond this margin 00:09:51.635 --> 00:09:54.047 the camera tracks back toward the player. 00:09:54.047 --> 00:09:56.867 The Super Mario World camera used particular heights 00:09:56.867 --> 00:09:59.544 to snap to vertically, but we didn't need this 00:09:59.544 --> 00:10:01.544 kind of detail for our game as we 00:10:01.544 --> 00:10:03.878 do not have a long level in the X axis 00:10:03.878 --> 00:10:06.848 but more of a stage on which the action takes place. 00:10:07.210 --> 00:10:09.210 For this reason our camera employs 00:10:09.210 --> 00:10:12.787 similar tracking vertically as it does horizontally. 00:10:18.779 --> 00:10:20.779 Take a look at the CameraFollow script on the 00:10:20.779 --> 00:10:23.138 mainCamera game object to see comments 00:10:23.138 --> 00:10:25.138 on how it achieves this effect. 00:10:26.135 --> 00:10:27.845 There are several effects in the game, 00:10:27.845 --> 00:10:29.845 but most important is our heroes ability 00:10:29.845 --> 00:10:32.732 to slay the alien onslaught he's faced with. 00:10:32.732 --> 00:10:36.338 Our hero shoots a bazooka which has animated recoil. 00:10:36.338 --> 00:10:38.898 This action is made up of several parts. 00:10:38.898 --> 00:10:41.643 First we listen for key input and when the Fire key is 00:10:41.643 --> 00:10:43.962 pressed we instantiate a rocket, 00:10:43.962 --> 00:10:47.969 play an audio clip and trigger an animation state to play. 00:10:47.969 --> 00:10:49.969 Let's break this down even further. 00:10:49.969 --> 00:10:52.418 in order to play the Shoot animation while other 00:10:52.418 --> 00:10:54.418 animations such as Run are playing we 00:10:54.418 --> 00:10:56.418 created a separate layer within our animator 00:10:56.418 --> 00:10:57.677 called Shooting. 00:10:57.677 --> 00:10:59.677 By setting the Weight property to 1 here 00:10:59.677 --> 00:11:02.532 we can totally override motion in the base layer 00:11:02.532 --> 00:11:04.532 on any parts of our character that are animated 00:11:04.532 --> 00:11:06.980 by clips on the shooting layer. 00:11:20.499 --> 00:11:22.499 In this layer we switch to the Shoot animation 00:11:22.499 --> 00:11:25.351 from any state, when the Shoot trigger 00:11:25.351 --> 00:11:27.351 parameter is called from code. 00:11:27.351 --> 00:11:30.543 Let's take a look at the Gun script in charge of this. 00:11:32.700 --> 00:11:35.140 Here you can see that we address the animator 00:11:35.140 --> 00:11:37.402 and set that trigger to True. 00:11:37.402 --> 00:11:40.513 Triggers simply act as a switch and reset themselves to false 00:11:40.513 --> 00:11:43.247 on the next frame so that they can be called again, 00:11:43.247 --> 00:11:45.511 which is perfect for actions such as shooting. 00:11:46.011 --> 00:11:48.673 In addition to setting the animation we fire the 00:11:48.673 --> 00:11:50.673 rockets themselves from this script, 00:11:50.673 --> 00:11:52.673 playing an audio clip and dependent upon 00:11:52.673 --> 00:11:54.673 the direction that the player is facing 00:11:54.673 --> 00:11:57.775 we instantiate a rocket and give it a velocity 00:11:57.775 --> 00:12:00.555 that's positive or negative in the X axis. 00:12:01.276 --> 00:12:03.933 This script is attached to the Gun empty game object 00:12:03.933 --> 00:12:05.294 in the hero's hierarchy. 00:12:05.294 --> 00:12:08.078 We place code like this on to an empty game object 00:12:08.078 --> 00:12:10.078 as it allows us to easily position 00:12:10.078 --> 00:12:11.663 where the rockets are created. 00:12:11.663 --> 00:12:13.663 We do this by placing the empty object 00:12:13.663 --> 00:12:16.010 at the end of the barrel of the bazooka 00:12:16.010 --> 00:12:18.010 and then we use it's own position as the 00:12:18.010 --> 00:12:20.010 point at which to spawn the rockets. 00:12:40.248 --> 00:12:42.804 The rocket itself has a 2D rigidbody 00:12:42.804 --> 00:12:44.804 and we assign a velocity to that in order 00:12:44.804 --> 00:12:46.804 to make it move. 00:12:46.804 --> 00:12:49.096 It has a sprite swap flame exhaust 00:12:49.096 --> 00:12:51.096 plus a particle system for smoke. 00:12:52.826 --> 00:12:56.482 The particle system also accepts the new sprite type of graphics 00:12:56.482 --> 00:12:58.482 so by adding a sprite sheet of smoke puffs 00:12:58.482 --> 00:13:00.482 to a material we can assign it to the 00:13:00.482 --> 00:13:04.149 texture sheet animation module of the particle system 00:13:04.149 --> 00:13:06.232 and we get instant animation of our 00:13:06.232 --> 00:13:08.232 sprites for the particle emission. 00:13:16.122 --> 00:13:18.935 When our rockets hit an enemy or part of the environment 00:13:18.935 --> 00:13:20.935 the rocket itself is destroyed and 00:13:20.935 --> 00:13:22.935 an explosion is spawned. 00:13:22.935 --> 00:13:24.935 The explosion is simply a sprite game object 00:13:24.935 --> 00:13:27.731 that animates through a sprite sheet that we have created. 00:13:27.731 --> 00:13:30.311 Yet again using sorting layers to render this 00:13:30.311 --> 00:13:33.699 at the lowest layer order of our foreground objects. 00:13:36.174 --> 00:13:38.174 When adding sprite-based animation like this 00:13:38.174 --> 00:13:40.174 we setup the sprites themselves by 00:13:40.174 --> 00:13:42.174 selecting the file in our Project Panel 00:13:42.174 --> 00:13:44.576 and choosing the Sprite Mode Multiple. 00:13:44.576 --> 00:13:46.576 This gives us access to the sprite editor 00:13:46.576 --> 00:13:49.757 which allows us to slice manually or automatically. 00:13:49.757 --> 00:13:52.406 Once happy with the selection of sprites from our file 00:13:52.406 --> 00:13:54.406 we simply hit Apply and Unity 00:13:54.406 --> 00:13:56.765 generates the sprites as children of that file 00:13:56.765 --> 00:13:58.765 to be used in our project. 00:13:59.707 --> 00:14:01.693 So that's our rocket in a nutshell. 00:14:01.693 --> 00:14:03.693 We will discuss the mechanics of killing the enemies 00:14:03.693 --> 00:14:06.533 later in this video in the section about enemies. 00:14:07.102 --> 00:14:09.448 Let's return to the player character now and look at 00:14:09.448 --> 00:14:12.194 how we handle health and taking damage. 00:14:12.194 --> 00:14:14.194 Health is stored as a float and 00:14:14.194 --> 00:14:16.194 with each interaction with a tagged enemy 00:14:16.190 --> 00:14:18.548 we call the TakeDamage function. 00:14:18.548 --> 00:14:20.548 This is only allowed to occur after the 00:14:20.548 --> 00:14:22.548 repeatDamagePeriod has passed 00:14:22.548 --> 00:14:25.347 to avoid the player being killed very quickly. 00:14:26.524 --> 00:14:29.136 To allow the player to escape enemies more easily 00:14:29.136 --> 00:14:31.136 and to show the player that they are being hurt 00:14:31.136 --> 00:14:33.136 we make the act of taking damage 00:14:33.136 --> 00:14:34.847 repel the character physically. 00:14:34.847 --> 00:14:37.540 To achieve this the TakeDamage function briefly 00:14:37.540 --> 00:14:39.540 stops the player from jumping 00:14:39.540 --> 00:14:42.125 and finds a vector from the enemy to the player 00:14:42.125 --> 00:14:44.125 and repels him in that direction 00:14:44.125 --> 00:14:46.125 by adding a physics force. 00:14:46.125 --> 00:14:48.684 The hurtForce variable is exposed in the Inspector 00:14:48.684 --> 00:14:51.323 as public so that it can be tweaked 00:14:51.323 --> 00:14:53.323 to adjust this element of game play without 00:14:53.323 --> 00:14:55.323 returning to the script. 00:14:55.323 --> 00:14:57.323 In addition to repelling the player, 00:14:57.323 --> 00:14:59.810 we of course subtract from the player's health. 00:14:59.810 --> 00:15:02.209 and update the player's health bar. 00:15:02.209 --> 00:15:04.624 To signify the decrease in health we subtract 00:15:04.624 --> 00:15:06.885 from the width of the bar and use a colour lerp 00:15:06.885 --> 00:15:09.825 to transition it's colour between green and red, 00:15:09.825 --> 00:15:12.640 both by finding the percentage that the current health is 00:15:12.640 --> 00:15:14.640 of the full health amount. 00:15:14.640 --> 00:15:17.873 The health bar simply comprises of two sprites, 00:15:17.873 --> 00:15:19.965 one for the outline of the bar and the other 00:15:19.965 --> 00:15:21.744 for the bar itself. 00:15:21.744 --> 00:15:23.744 This was again designed in Photoshop and then 00:15:23.744 --> 00:15:25.954 the two separate elements were exported. 00:15:25.954 --> 00:15:27.954 In the import settings for these sprites 00:15:27.954 --> 00:15:30.470 we set their pivot to the middle left of the graphic 00:15:30.470 --> 00:15:34.053 so that when it scales down it shrinks towards the left. 00:15:48.573 --> 00:15:50.573 These two sprites are placed under an empty 00:15:50.573 --> 00:15:52.573 parent game object which has a simple script 00:15:52.573 --> 00:15:54.573 on it which makes it follow the player. 00:15:54.573 --> 00:15:56.621 We do this by setting the position to the 00:15:56.621 --> 00:15:58.621 same as the player object's position 00:15:58.621 --> 00:16:00.621 plus an offset that we've made public to allow 00:16:00.621 --> 00:16:02.621 for adjustment in the Inspector. 00:16:16.215 --> 00:16:18.215 When the player has 0 health remaining 00:16:18.215 --> 00:16:20.215 we allow him to fall through the level by 00:16:20.215 --> 00:16:22.629 setting his colliders to triggers, 00:16:22.629 --> 00:16:24.629 and we move him to the very front of rendering 00:16:24.629 --> 00:16:28.194 by placing his sprite renderers on the UI Sorting layer, 00:16:28.194 --> 00:16:31.594 one we've made to render in front of everything in the game. 00:16:31.594 --> 00:16:34.223 We have 2 animations for when the player dies. 00:16:34.223 --> 00:16:37.252 1 called Death, where he loses his hat and gun 00:16:37.252 --> 00:16:38.631 and another called Falling. 00:16:38.631 --> 00:16:40.631 We naturally transition in to Falling once 00:16:40.631 --> 00:16:44.002 the Death animation completes by using the Exit Time 00:16:44.002 --> 00:16:47.239 as our transition condition in the animator. 00:16:50.778 --> 00:16:52.778 Finally, to stop the player moving the character 00:16:52.778 --> 00:16:55.278 or shooting during the Death sequence 00:16:55.278 --> 00:16:58.340 we disable the PlayerControl and Gun scripts. 00:16:58.340 --> 00:17:00.731 Because the Die function is made as public 00:17:00.731 --> 00:17:03.332 we can call it from elsewhere, such as if the player 00:17:03.332 --> 00:17:05.040 falls in to the water. 00:17:05.040 --> 00:17:07.733 To reset the game once the player does hit the water 00:17:07.733 --> 00:17:09.733 we have a KillTrigger object, which simply 00:17:09.733 --> 00:17:12.463 comprises of a trigger collider and a script. 00:17:12.463 --> 00:17:15.012 For most of the game the purpose of the Remover script 00:17:15.012 --> 00:17:17.012 is to remove our enemy objects that fall in 00:17:17.012 --> 00:17:19.789 to the river, and instantiate a splash animation 00:17:19.789 --> 00:17:21.442 and sound effect. 00:17:21.442 --> 00:17:24.001 However, when the player is detected by this trigger 00:17:24.001 --> 00:17:27.092 we call the Die function in the PlayerHealth script 00:17:27.092 --> 00:17:29.092 and also disable CameraTracking 00:17:29.092 --> 00:17:31.092 whilst moving the player off screen 00:17:31.092 --> 00:17:34.527 and calling a co-routiene that pauses for 2 seconds 00:17:34.527 --> 00:17:36.527 and then reloads the level. 00:17:37.079 --> 00:17:39.079 But let's not dwell on the death of the player, 00:17:39.079 --> 00:17:41.079 let's look at his survival and the tools that we give 00:17:41.079 --> 00:17:42.481 him to do that. 00:17:42.481 --> 00:17:44.481 Our game features 2 airdropped crates that 00:17:44.481 --> 00:17:47.124 assist the player, 1 containing a bomb, 00:17:47.124 --> 00:17:49.911 the other a med kit to boost health. 00:17:50.411 --> 00:17:52.963 These crate drops are made up of 2 parts. 00:17:52.963 --> 00:17:55.695 The crate itself and a parachute. 00:17:58.046 --> 00:18:01.311 These 2 elements are nested beneath an empty parent object 00:18:01.311 --> 00:18:03.768 to allow us to animate them as a group. 00:18:03.768 --> 00:18:05.768 We position the 2 sprites so that the parachute's 00:18:05.768 --> 00:18:08.476 centre is at the centre of the parent. 00:18:09.045 --> 00:18:11.907 This way the animation can swing left and right 00:18:11.907 --> 00:18:15.307 as if the entire parachuting crate is floating to the ground. 00:18:15.307 --> 00:18:17.307 We then simply add a rigidbody to cause 00:18:17.307 --> 00:18:19.307 gravity to pull the object down 00:18:19.307 --> 00:18:21.307 and add colliders to the crate so that 00:18:21.307 --> 00:18:23.307 we can detect when it lands and when 00:18:23.307 --> 00:18:24.962 the player picks up the crate. 00:18:24.962 --> 00:18:26.962 Upon landing we transition to a second 00:18:26.962 --> 00:18:30.513 animation state which scales the parachute down. 00:18:30.513 --> 00:18:33.308 Like other parts of our game, the animator handles 00:18:33.308 --> 00:18:34.916 the states of the object. 00:18:34.916 --> 00:18:36.916 We can see that by default it plays the 00:18:36.916 --> 00:18:38.916 floatDown animation state 00:18:38.916 --> 00:18:40.916 but then switches to a landing state 00:18:40.916 --> 00:18:43.472 when the trigger Land is set to true. 00:18:43.972 --> 00:18:47.383 In our script we do this using an onTriggerEnter function, 00:18:47.383 --> 00:18:49.732 which detects the ground via a tag. 00:18:49.732 --> 00:18:52.822 We also detatch the crate itself from the parent object 00:18:52.822 --> 00:18:55.098 and give it a rigidbody of it's own 00:18:55.098 --> 00:18:57.490 so that it can interact with the environment 00:18:57.490 --> 00:19:00.624 resting realistically on a slope if it lands on one. 00:19:00.624 --> 00:19:03.672 Let's focus on the bomb first of all. 00:19:03.672 --> 00:19:05.672 Picking up the bomb crate is handled on the 00:19:05.672 --> 00:19:08.475 BombPickup script, attached to the crate. 00:19:08.475 --> 00:19:11.057 We pickup the crate by destroying it and adding to 00:19:11.057 --> 00:19:13.057 the count of bombs that the player has 00:19:13.057 --> 00:19:15.057 in the script attached to the player called 00:19:15.057 --> 00:19:16.739 LayBombs 00:19:17.557 --> 00:19:19.557 The LayBombs script simply checks if 00:19:19.557 --> 00:19:21.557 the player is carrying a bomb 00:19:21.557 --> 00:19:23.557 and then instantiates an instance 00:19:23.557 --> 00:19:25.557 of the Bomb prefab. 00:19:27.424 --> 00:19:29.952 The Bomb prefab has a timed fuse 00:19:29.952 --> 00:19:32.147 which waits by using an yield within the 00:19:32.147 --> 00:19:34.147 BombDetonation co-routiene 00:19:34.147 --> 00:19:36.147 before calling the Explode function. 00:19:36.799 --> 00:19:39.545 The Explode function performs several actions. 00:19:39.545 --> 00:19:41.545 First it resets the bombLaid variable 00:19:41.545 --> 00:19:43.797 to allow another bomb to be deployed, 00:19:43.797 --> 00:19:45.797 it tells the pickup spawner it is allowed to 00:19:45.797 --> 00:19:47.797 spawn a new crate drop and kills 00:19:47.797 --> 00:19:49.797 enemies within a defined blast radian. 00:19:50.518 --> 00:19:53.058 Let's take a look at how this last part works. 00:19:53.058 --> 00:19:55.058 Because bombs are lethal to enemies regardless of 00:19:55.058 --> 00:19:57.180 their remaining hit points we use the 00:19:57.180 --> 00:19:59.976 Physics.OverlapCircleAll to collect all objects 00:19:59.976 --> 00:20:03.470 tagged Enemy within a certain radius of the bomb. 00:20:03.470 --> 00:20:06.612 We then run a foreach loop for every enemy found 00:20:06.612 --> 00:20:10.663 setting their health to 0 finding a vector from where the bomb was 00:20:10.663 --> 00:20:12.663 to where the enemy is, in order to apply 00:20:12.663 --> 00:20:15.542 a force in the direction of that vector. 00:20:16.304 --> 00:20:18.538 Once the foreach loop is complete 00:20:18.538 --> 00:20:21.381 we play and instantiate visual effects, 00:20:21.381 --> 00:20:23.381 play an audio clip for the explosion 00:20:23.381 --> 00:20:25.907 and of course destroy the bomb itself. 00:20:26.875 --> 00:20:29.252 The visual of the explosion is twofold. 00:20:29.252 --> 00:20:31.252 The main part is a simple circle that appears 00:20:31.252 --> 00:20:33.583 briefly and is then destroyed 00:20:33.583 --> 00:20:35.583 and the second part is a particle system of 00:20:35.583 --> 00:20:37.583 stars that reuses the same sprites 00:20:37.583 --> 00:20:39.583 as our rocket explosion. 00:20:42.265 --> 00:20:44.265 For efficiency we keep this particle 00:20:44.265 --> 00:20:46.265 system in the scene at all times 00:20:46.265 --> 00:20:48.265 and when it is required we use code 00:20:48.265 --> 00:20:51.735 to move the system to the desired position and play it. 00:20:52.511 --> 00:20:54.511 This keeps the particle system in memory 00:20:54.511 --> 00:20:56.511 and makes the game more efficient. 00:20:57.011 --> 00:20:59.011 It's worth noting that we can do this 00:20:59.011 --> 00:21:01.011 because we know we will only have 1 00:21:01.011 --> 00:21:04.668 single explosion in the scene at any one time 00:21:04.668 --> 00:21:07.794 as the player can only throw 1 bomb at a time. 00:21:07.794 --> 00:21:09.794 This is why keeping our particle system in the 00:21:09.794 --> 00:21:11.794 scene and replaying it is more 00:21:11.794 --> 00:21:14.936 efficient than creating instances and then removing them. 00:21:15.714 --> 00:21:17.618 With the rocket explosion however, 00:21:17.618 --> 00:21:19.618 we can have many at once so we do 00:21:19.618 --> 00:21:21.618 need to spawn and remove them. 00:21:22.118 --> 00:21:24.118 Now let's take a look at what happens when our player 00:21:24.118 --> 00:21:26.118 kills an enemy and scores points. 00:21:26.618 --> 00:21:28.436 This is done in 2 parts, 00:21:28.436 --> 00:21:31.668 a scoring animation that plays showing 100 points earned 00:21:31.668 --> 00:21:33.668 and the score UI at the top of the screen 00:21:33.668 --> 00:21:35.528 that increments. 00:21:35.528 --> 00:21:38.303 The score animation is made up to 2 number sprites, 00:21:38.303 --> 00:21:40.193 a 1 and a 0. 00:21:40.193 --> 00:21:42.872 We place this in the scene under an empty parent object 00:21:42.872 --> 00:21:46.036 and animated them using a simple destroyer script to 00:21:46.036 --> 00:21:49.186 remove them from the scene when the animation is complete. 00:21:49.186 --> 00:21:51.186 We call the destroyer function in the script 00:21:51.186 --> 00:21:53.186 by placing an animation event 00:21:53.186 --> 00:21:55.186 at the end of the timeline. 00:22:06.142 --> 00:22:09.703 The ScoreUI itself is a simple GUI text component 00:22:09.703 --> 00:22:11.703 with a custom font and script that manages 00:22:11.703 --> 00:22:13.703 the score for the player. 00:22:13.703 --> 00:22:16.759 The Score variable is public, meaning that we can address it 00:22:16.759 --> 00:22:18.980 from the Enemy script when they are killed 00:22:18.980 --> 00:22:20.980 and add 100 points to the value. 00:22:20.980 --> 00:22:22.980 Speaking of the enemies, let's take a look 00:22:22.980 --> 00:22:24.980 at them more in depth now. 00:22:25.480 --> 00:22:28.260 In our game we have 2 types of alien enemy, 00:22:28.260 --> 00:22:30.854 a green slug-like monster and a smarter 00:22:30.854 --> 00:22:32.854 alien that brought his ship with him for 00:22:32.854 --> 00:22:34.563 protection during the invasion. 00:22:34.563 --> 00:22:36.563 These characters share the same script 00:22:36.563 --> 00:22:38.563 as the behaviour is very similar 00:22:38.563 --> 00:22:40.881 and we allow for differing movement speeds 00:22:40.881 --> 00:22:42.881 and amounts of hit points by setting 00:22:42.881 --> 00:22:45.765 these as public variables in the Inspector. 00:22:46.638 --> 00:22:49.093 Each enemy has it's own Walk animation. 00:22:49.093 --> 00:22:51.093 The slug has a moving tail, whist the 00:22:51.093 --> 00:22:54.444 ship-based enemy rocks back and forth as it approaches. 00:22:55.994 --> 00:22:57.994 For the slug we used the sprite importer 00:22:57.994 --> 00:22:59.994 to define the tail section of the graphic 00:22:59.994 --> 00:23:01.994 as a separate sprite element, 00:23:01.994 --> 00:23:04.438 meaning that we could animate it individually 00:23:04.438 --> 00:23:07.475 and avoid having to scale the entire sprite. 00:23:07.475 --> 00:23:09.475 By setting the pivot to the right 00:23:09.475 --> 00:23:12.124 we are able to animate the tail expanding and contracting 00:23:12.124 --> 00:23:14.124 from that point. 00:23:16.475 --> 00:23:19.918 For added character we then move the eyelid up and down 00:23:19.918 --> 00:23:21.918 and we use the Z value to sort the sprites 00:23:21.918 --> 00:23:24.859 amongst one another, the eye being below the eyelid 00:23:24.859 --> 00:23:26.859 so that we could animate it over the top. 00:23:28.865 --> 00:23:31.268 The second enemy's animation was much simpler 00:23:31.268 --> 00:23:34.046 and just meant that we rotated it back and forth. 00:23:35.798 --> 00:23:37.798 For the mechanics of moving the enemies 00:23:37.798 --> 00:23:41.229 we drive them by setting the velocity of the rigidbody. 00:23:41.229 --> 00:23:43.889 When they encounter an obstacle such as a wall 00:23:43.889 --> 00:23:47.826 they detect this by using a Physics.OverlapPoint function, 00:23:47.826 --> 00:23:51.317 which checks for a point in space overlapping a collider. 00:23:51.317 --> 00:23:53.854 Our walls, the towers at each side of the level, 00:23:53.854 --> 00:23:55.854 are tagged as obstacles. 00:23:55.850 --> 00:23:59.161 When this function detects them it calls the Flip function, 00:23:59.161 --> 00:24:01.767 it reverses the X scale of the enemy 00:24:01.767 --> 00:24:04.070 sending them moving in a different direction. 00:24:04.070 --> 00:24:06.070 To kill the enemies, each time a rocket collides 00:24:06.070 --> 00:24:09.036 with them it's script calls the Hurt function on 00:24:09.036 --> 00:24:11.036 the particular enemy that it's hit. 00:24:14.962 --> 00:24:16.962 In this function we subtract 1 from the 00:24:16.962 --> 00:24:19.213 hit points of the particular enemy. 00:24:19.213 --> 00:24:21.213 We then keep tabs on the enemy's health 00:24:21.213 --> 00:24:23.213 inside the fixed update function. 00:24:23.213 --> 00:24:27.124 If it drops to 0 we call the Death function. 00:24:31.229 --> 00:24:33.916 When they die we perform a number of functions. 00:24:33.916 --> 00:24:35.916 Firstly we disable all sprite renderers 00:24:35.916 --> 00:24:37.916 as our 2D characters are made up of a 00:24:37.916 --> 00:24:39.916 number of sprite objects that are animated. 00:24:40.941 --> 00:24:42.941 This is because we simply want to swap out the 00:24:42.941 --> 00:24:44.941 animated elements for a single sprite 00:24:44.941 --> 00:24:46.941 of the dead character 00:24:47.745 --> 00:24:49.745 We do this with the main sprite renderer by 00:24:49.745 --> 00:24:51.745 setting it to use the sprite assigned to 00:24:51.745 --> 00:24:54.165 the deadEnemy variable. 00:24:54.165 --> 00:24:56.165 We then add to the score using the public 00:24:56.165 --> 00:24:58.165 variable in the Score script 00:24:58.165 --> 00:25:00.744 and we add some visual flare to the enemy's death 00:25:00.744 --> 00:25:03.534 by adding torque to spin them as they die. 00:25:04.448 --> 00:25:06.448 Because we need the enemies to fall through the 00:25:06.448 --> 00:25:08.881 environment and land in the river when they die 00:25:08.881 --> 00:25:10.881 we find all colliders on the object 00:25:10.881 --> 00:25:13.589 and set their IsTrigger parameter to true. 00:25:13.589 --> 00:25:15.139 This means that they will pass through the 00:25:15.139 --> 00:25:17.417 environment colliders. 00:25:17.417 --> 00:25:20.054 We then choose from an array of death audio clips 00:25:20.054 --> 00:25:22.054 and play one of them back, before creating 00:25:22.054 --> 00:25:25.470 an instance of the Score animation we showed you earlier. 00:25:27.876 --> 00:25:29.876 To remove the dead enemy from the scene 00:25:29.876 --> 00:25:31.876 we rely on the killTrigger object 00:25:31.876 --> 00:25:34.762 It performs the same function as discussed earlier 00:25:34.762 --> 00:25:36.762 as any non-player object touching it 00:25:36.762 --> 00:25:39.950 will cause a splash animation and remove that object. 00:25:39.950 --> 00:25:41.950 The sound effect of them hitting the water is 00:25:41.950 --> 00:25:43.950 an audio clip attached to the animated 00:25:43.950 --> 00:25:45.950 splash which plays on awake 00:25:45.950 --> 00:25:47.950 so that when we create an instance of the animated 00:25:47.950 --> 00:25:50.634 object we hear the sound right away. 00:25:55.153 --> 00:25:57.153 To finish the game level re decorated the 00:25:57.153 --> 00:25:59.153 background with a number of moving props 00:25:59.153 --> 00:26:02.302 in order to make our game environment feel more dynamic. 00:26:02.302 --> 00:26:05.703 We added flying swans, plus buses and taxis that drive 00:26:05.703 --> 00:26:07.125 along the river bank. 00:26:07.125 --> 00:26:10.634 First was the swan, which was created from a sprite sheet, 00:26:10.634 --> 00:26:12.634 drawn in Photoshop and imported using 00:26:12.634 --> 00:26:14.634 the Multiple Sprite Mode import setting 00:26:14.634 --> 00:26:16.051 in the Inspector. 00:26:16.051 --> 00:26:18.800 By choosing this approach Unity automates choosing 00:26:18.800 --> 00:26:20.800 each frame in the sheet and importing 00:26:20.800 --> 00:26:22.800 it as a separate sprite under the parent 00:26:22.800 --> 00:26:24.579 hierarchy of the asset. 00:26:24.579 --> 00:26:27.279 Because this is a linear set of animation frames 00:26:27.279 --> 00:26:29.279 we could simply drag all of these sprites in to the 00:26:29.279 --> 00:26:32.346 scene to let Unity animate them for us. 00:26:32.346 --> 00:26:35.317 Et voila, our animated swan is ready to add 00:26:35.317 --> 00:26:37.759 as a background element. 00:26:37.759 --> 00:26:40.165 The swan was then given a rigidbody2D 00:26:40.165 --> 00:26:42.165 so that we can use velocity to send it 00:26:42.165 --> 00:26:43.369 across the screen. 00:26:43.369 --> 00:26:47.334 As with the bus and the cab, the swan is saved as a prefab. 00:26:49.257 --> 00:26:51.257 For the bus and taxi prefabs we 00:26:51.257 --> 00:26:53.257 simply separated the bodies and wheels of 00:26:53.257 --> 00:26:55.257 the vehicles in the sprite importer 00:26:55.257 --> 00:26:58.392 and made a simple bobbing animation. 00:26:58.392 --> 00:27:00.793 Applying a 2d rigidbody to these as well, 00:27:00.793 --> 00:27:02.793 we were able to drive them across the screen 00:27:02.793 --> 00:27:04.376 using velocity. 00:27:07.279 --> 00:27:10.271 For all 3 props, the bus, taxi and the swan 00:27:10.271 --> 00:27:12.271 we created a script we could reuse 00:27:12.271 --> 00:27:14.271 which is in charge of spawning them. 00:27:14.271 --> 00:27:16.616 The BackgroundPropsSpawner script 00:27:16.616 --> 00:27:19.838 also handles the frequency, a speed to give them 00:27:19.838 --> 00:27:21.838 and where on screen to spawn them. 00:27:21.838 --> 00:27:24.521 This meant that we could make 3 creator objects 00:27:24.521 --> 00:27:26.521 with the same script on. 00:27:26.521 --> 00:27:28.521 Changing which prefab will be spawned 00:27:28.521 --> 00:27:30.521 and what properties to give it. 00:27:30.521 --> 00:27:33.854 Take a look at the comments in the script to learn more. 00:27:33.854 --> 00:27:36.172 Finally, for more background dynamism, 00:27:36.172 --> 00:27:40.409 we added rolling clouds, panning river details and fog. 00:27:41.323 --> 00:27:44.525 We did this by adding 2 instances of the background sprite 00:27:44.525 --> 00:27:48.004 to a parent object and simply used animation to slowly 00:27:48.004 --> 00:27:50.004 pan them across the screen. 00:27:50.004 --> 00:27:52.652 Because this animation loops our animation will 00:27:52.652 --> 00:27:54.652 continue indefinitely. 00:27:59.185 --> 00:28:01.031 And that's how we made our game. 00:28:01.031 --> 00:28:03.031 We hope this overview has given you some idea of 00:28:03.031 --> 00:28:05.516 how we create 2D games in Unity, 00:28:05.516 --> 00:28:07.516 and we'll be creating more simply projects and 00:28:07.516 --> 00:28:08.971 tutorials in the future. 00:28:08.971 --> 00:28:11.689 We look forward to your feedback on Unity4.3 00:28:11.689 --> 00:28:13.689 and we can't wait to see the great 2D titles 00:28:13.689 --> 00:28:14.959 that you'll come up with. 00:28:14.959 --> 00:28:16.487 Thanks for watching.