1 00:00:00,000 --> 00:00:04,295 In Unity 4.3 we're launching our first set of 2D features. 2 00:00:04,295 --> 00:00:06,295 To compliment this we have constructed a 3 00:00:06,295 --> 00:00:08,295 demo project with these tools. 4 00:00:08,295 --> 00:00:11,527 Our 2D platformer is nicknamed 'Tower Bridge Defence' 5 00:00:11,527 --> 00:00:13,776 It depicts London's Tower Bridge in the midst 6 00:00:13,776 --> 00:00:15,556 of an alien invasion. 7 00:00:15,556 --> 00:00:17,955 It's a completely sprite-based, physics driven 8 00:00:17,955 --> 00:00:20,216 2D sample level that we hope will help you 9 00:00:20,216 --> 00:00:23,472 understand how 2D games are put together in Unity. 10 00:00:23,472 --> 00:00:25,472 This video will discuss the background and 11 00:00:25,472 --> 00:00:28,184 foreground construction, characters, effects, 12 00:00:28,184 --> 00:00:30,184 camera tracking, animation and scripting 13 00:00:30,184 --> 00:00:31,639 used in the demo. 14 00:00:31,639 --> 00:00:33,639 To begin with, let's discuss the basics 15 00:00:33,653 --> 00:00:36,139 of working in 2D in Unity. 16 00:00:36,860 --> 00:00:39,291 Firstly, when working in 2D, you should set the 17 00:00:39,291 --> 00:00:41,221 Editor Behaviour Mode to 2D 18 00:00:41,221 --> 00:00:43,040 for various settings. 19 00:00:43,040 --> 00:00:45,040 This can be done when making a new project 20 00:00:45,040 --> 00:00:47,040 using the drop-down on the project wizard 21 00:00:47,040 --> 00:00:49,543 or during a project by choosing 22 00:00:49,543 --> 00:00:53,172 Edit - Project Settings - Editor from the top menu. 23 00:00:53,172 --> 00:00:55,172 This means that by default textures 24 00:00:55,172 --> 00:00:57,172 will be imported as sprites and the 25 00:00:57,172 --> 00:00:59,630 Scene View will default to 2D mode. 26 00:00:59,630 --> 00:01:01,630 This new mode gives you a completely orthographic 27 00:01:01,630 --> 00:01:04,420 view in which to construct 2D games. 28 00:01:04,420 --> 00:01:06,806 It also hides the usual 3D gizmo 29 00:01:06,806 --> 00:01:09,197 in the top right of the view, giving you more space 30 00:01:09,197 --> 00:01:11,941 to work in. Aside from these settings the work 31 00:01:11,941 --> 00:01:14,244 flows for 2D have been designed to mirror 32 00:01:14,244 --> 00:01:17,040 existing Unity approaches to 3D game creation. 33 00:01:17,040 --> 00:01:19,040 So if you already know a little about Unity 34 00:01:19,040 --> 00:01:21,040 you'll be in a great position to start making 35 00:01:21,040 --> 00:01:22,929 2D games right away. 36 00:01:22,929 --> 00:01:24,929 It's worth noting at this stage that you can 37 00:01:24,929 --> 00:01:27,219 still mix 2D and 3D in Unity, 38 00:01:27,219 --> 00:01:29,722 so if you want to add 3D elements to your 2D game 39 00:01:29,722 --> 00:01:32,870 or vice versa you can do that with no worries. 40 00:01:33,366 --> 00:01:35,496 Let's take a look at the demo project itself, 41 00:01:35,496 --> 00:01:38,312 and how we built it up one stage at a time. 42 00:01:38,812 --> 00:01:40,812 We began by sketching out the level design 43 00:01:40,812 --> 00:01:42,812 for this sample level and then went about 44 00:01:42,812 --> 00:01:44,812 recreating the layout in Photoshop. 45 00:01:45,312 --> 00:01:47,312 Creating and exporting the layers, 46 00:01:47,312 --> 00:01:49,312 we were able to import these in to Unity 47 00:01:49,312 --> 00:01:51,312 using the new Sprite type. 48 00:01:58,373 --> 00:02:01,306 In order to create parallaxing in our background later, 49 00:02:01,306 --> 00:02:03,666 we kept some of the background elements separate 50 00:02:03,666 --> 00:02:06,515 and placed them on to a Background Sorting Layer. 51 00:02:06,515 --> 00:02:09,658 Yet another new feature of 2D development in Unity. 52 00:02:10,158 --> 00:02:12,841 Having assigned all of our backgrounds to this layer, 53 00:02:12,841 --> 00:02:15,157 we could then use the Order In Layer property 54 00:02:15,157 --> 00:02:17,379 of the Sprite Renderer to sort them. 55 00:02:17,379 --> 00:02:19,379 Once we were happy with their positions 56 00:02:19,379 --> 00:02:21,379 we could lock the Background Sorting Layer 57 00:02:21,379 --> 00:02:23,379 so that when we added foreground elements 58 00:02:23,379 --> 00:02:25,379 we didn't need to worry about accidentally 59 00:02:25,379 --> 00:02:27,751 dragging background elements around. 60 00:02:27,751 --> 00:02:29,751 This is done using the Layers pull-down in the 61 00:02:29,751 --> 00:02:31,751 top right of the interface. 62 00:02:32,817 --> 00:02:35,531 Because the background elements are purely decorative 63 00:02:35,531 --> 00:02:37,531 we did not require any additional components 64 00:02:37,531 --> 00:02:39,531 on the sprite game object. 65 00:02:39,531 --> 00:02:41,531 They were parented to an empty game object 66 00:02:41,531 --> 00:02:44,201 that has a simple script to handle parallaxing 67 00:02:44,201 --> 00:02:46,201 called BackgroundParallax. 68 00:02:46,201 --> 00:02:48,643 For more information you'll find this script 69 00:02:48,643 --> 00:02:50,643 fully commented in the Scripts folder. 70 00:02:54,914 --> 00:02:56,914 Next up came the creation of the foreground elements 71 00:02:56,914 --> 00:02:59,400 that our characters would actually traverse. 72 00:02:59,790 --> 00:03:02,280 We designed London's Tower Bridge with a UFO 73 00:03:02,280 --> 00:03:03,466 landed in the centre. 74 00:03:03,466 --> 00:03:05,466 The character has the run of the environment 75 00:03:05,466 --> 00:03:07,466 as enemies spawn from the skies and begin 76 00:03:07,466 --> 00:03:09,216 to navigate around the level. 77 00:03:09,216 --> 00:03:11,216 As such, each piece of the foreground required 78 00:03:11,216 --> 00:03:13,632 a collider for characters to walk upon. 79 00:03:13,632 --> 00:03:15,632 For most of the environment we used 2D 80 00:03:15,632 --> 00:03:17,632 box colliders for efficiency, 81 00:03:17,632 --> 00:03:21,239 but the UFO itself has a more complex shape. 82 00:03:22,505 --> 00:03:24,505 Unity's Polygon Collider allowed us to 83 00:03:24,505 --> 00:03:26,878 automate creation of the collider itself 84 00:03:26,878 --> 00:03:28,724 based on the shape of the sprite. 85 00:03:28,724 --> 00:03:30,724 It even meant that we could tweak the shape of 86 00:03:30,724 --> 00:03:32,053 the collider later. 87 00:03:32,053 --> 00:03:34,164 Moving, adding or subtracting points 88 00:03:34,164 --> 00:03:36,164 of the collider shape to make it more 89 00:03:36,164 --> 00:03:38,164 appropriate to walk over. 90 00:03:38,664 --> 00:03:40,664 To sort these foregrounds we created a 91 00:03:40,664 --> 00:03:43,154 Foregrounds Sorting Layer, which was drawn 92 00:03:43,154 --> 00:03:45,599 above the backgrounds in the Tags And Layers manager. 93 00:03:48,875 --> 00:03:50,875 Next, let's take a look at our hero. 94 00:03:53,709 --> 00:03:55,598 Our player character was yet again designed 95 00:03:55,598 --> 00:03:57,598 in Photoshop, and for this demo 96 00:03:57,598 --> 00:03:59,598 we chose to make a character with independent 97 00:03:59,598 --> 00:04:01,598 limbs and features in the style of 98 00:04:01,598 --> 00:04:03,598 2D hits such as Rayman. 99 00:04:03,598 --> 00:04:05,598 Our other option would have been to design 100 00:04:05,598 --> 00:04:08,140 a sprite sheet-based animation and design each 101 00:04:08,140 --> 00:04:09,643 each frame in Photoshop, 102 00:04:09,643 --> 00:04:12,365 an approach we use later for the background Swan, 103 00:04:12,365 --> 00:04:14,365 which we'll discuss later in the video. 104 00:04:15,072 --> 00:04:17,072 Because our character had independent elements 105 00:04:17,072 --> 00:04:20,196 that we wish to animate we finalised the design 106 00:04:20,196 --> 00:04:22,196 and then moved his bodily elements in to separate 107 00:04:22,196 --> 00:04:25,408 spaces on our canvas to allow Unity to isolate them 108 00:04:25,408 --> 00:04:27,959 as separate sprites in the Importer. 109 00:04:28,763 --> 00:04:30,763 This meant that we could then arrange all of 110 00:04:30,763 --> 00:04:33,096 our sprites as separate elements to be animated. 111 00:04:33,096 --> 00:04:35,495 We placed these on to a new Character Sorting Layer 112 00:04:35,495 --> 00:04:38,167 that we created, and then used Z values in the 113 00:04:38,167 --> 00:04:40,921 transform to sort their rendering depth. 114 00:04:48,811 --> 00:04:50,811 All of these sprites are then arranged under an 115 00:04:50,811 --> 00:04:52,811 empty game object, which has all of our 116 00:04:52,811 --> 00:04:56,591 controls scripting, colliders, physics, excetera attached to it. 117 00:04:56,591 --> 00:04:58,591 Once we'd done this we were able to use the newly 118 00:04:58,591 --> 00:05:01,041 upgraded Animation window to create 119 00:05:01,041 --> 00:05:03,906 Idle, Run, Jump, Shoot and Death animations 120 00:05:03,906 --> 00:05:07,095 by animating each of the character's sprites over time. 121 00:05:07,095 --> 00:05:09,795 With the new Dopesheet View in the Animation window 122 00:05:09,795 --> 00:05:11,795 this is easier than ever. 123 00:05:13,414 --> 00:05:16,006 We simply add animation to the parent object 124 00:05:16,006 --> 00:05:19,403 and then create keyframes for any of the child objects. 125 00:05:19,403 --> 00:05:21,403 Moving the playhead to where we want 126 00:05:21,403 --> 00:05:23,403 and then moving the various parts of the character 127 00:05:23,403 --> 00:05:25,403 to automatically keyframe the animation. 128 00:05:27,313 --> 00:05:29,644 The ability to switch between Curve and Dopesheet 129 00:05:29,644 --> 00:05:32,448 representation of our animation makes it easier than 130 00:05:32,448 --> 00:05:35,064 ever to adjust timing and design. 131 00:05:36,730 --> 00:05:38,730 With these animations created we can 132 00:05:38,730 --> 00:05:41,370 then design a state machine for our character 133 00:05:41,370 --> 00:05:43,801 so that when called upon in code, differing animations 134 00:05:43,801 --> 00:05:45,277 could be played. 135 00:05:45,277 --> 00:05:47,277 the animator controller for the character is 136 00:05:47,277 --> 00:05:50,574 not driving a 3D biped, so we simply deselect 137 00:05:50,574 --> 00:05:53,673 Apply Root Motion and select Animate Physics 138 00:05:53,673 --> 00:05:55,673 in order to drive our animations in time with 139 00:05:55,673 --> 00:05:57,287 the physics engine. 140 00:05:57,287 --> 00:05:59,858 In order to traverse the environment our hero has a 141 00:05:59,858 --> 00:06:02,231 circle collider at his feet and a box collider 142 00:06:02,231 --> 00:06:04,564 to cover the rest of his body outline. 143 00:06:04,564 --> 00:06:07,067 This means he can smoothly walk up and down hills 144 00:06:07,067 --> 00:06:09,454 and when he jumps his head will hit the ceiling. 145 00:06:09,802 --> 00:06:12,537 In order to control the character and it's animations 146 00:06:12,537 --> 00:06:16,038 we wrote a script that moves him via 2D physics forces. 147 00:06:16,038 --> 00:06:18,038 This means that we can apply physics to him 148 00:06:18,038 --> 00:06:20,038 and the enemies during the game for more 149 00:06:20,038 --> 00:06:21,427 dynamic game play. 150 00:06:21,427 --> 00:06:23,814 In our PlayerControl script for the character 151 00:06:23,814 --> 00:06:25,814 we check for player input. 152 00:06:25,814 --> 00:06:27,814 We use this to apply physics forces 153 00:06:27,814 --> 00:06:30,766 for movement and also send the value of the input 154 00:06:30,766 --> 00:06:33,487 to the animator, which in turn defines which 155 00:06:33,487 --> 00:06:36,475 animation should be playing and smoothly transitions 156 00:06:36,475 --> 00:06:38,475 between the different animation clips that 157 00:06:38,475 --> 00:06:40,475 we've created as states. 158 00:06:40,475 --> 00:06:42,475 The great thing about using the animator to 159 00:06:42,475 --> 00:06:44,475 create states from animation clips is 160 00:06:44,475 --> 00:06:46,861 that we can go and tweak speeds of animation 161 00:06:46,861 --> 00:06:48,861 to match our physics velocities 162 00:06:48,861 --> 00:06:51,278 without having to reanimate anything 163 00:07:23,129 --> 00:07:25,129 The FixedUpdate function evaluates with 164 00:07:25,129 --> 00:07:27,588 each physics step, and the first thing we 165 00:07:27,588 --> 00:07:29,588 do with this is to feed the value of Horizontal 166 00:07:29,588 --> 00:07:32,994 input in to the Speed parameter of our animator. 167 00:07:33,950 --> 00:07:35,950 The transition between Idle and Run 168 00:07:35,950 --> 00:07:37,950 in our simple state machine requires 169 00:07:37,950 --> 00:07:41,718 that the Speed parameter is above 0.1. 170 00:07:41,718 --> 00:07:44,025 When it is, the animator blends from Idle 171 00:07:44,025 --> 00:07:46,025 in to the Run state. 172 00:07:51,857 --> 00:07:53,857 We then go on to add forces to the player's 173 00:07:53,857 --> 00:07:57,184 2D physics component, the rigidbody2D, 174 00:07:57,184 --> 00:07:58,822 in order to move him around. 175 00:07:59,626 --> 00:08:02,521 We also handle which direction the character is facing 176 00:08:02,521 --> 00:08:04,702 based on the value of Horizontal input, 177 00:08:04,702 --> 00:08:07,710 checking whether it is above or below 0. 178 00:08:07,710 --> 00:08:10,557 This is because in Unity, holding the left input key 179 00:08:10,557 --> 00:08:14,573 returns a value of -1, where right returns positive 1. 180 00:08:15,073 --> 00:08:18,700 Depending on input, we then call a simple flip function, 181 00:08:18,700 --> 00:08:21,477 which reverses the X scale of the character, 182 00:08:21,477 --> 00:08:24,566 giving him the appearance of facing the opposite direction. 183 00:08:26,848 --> 00:08:28,848 To decide whether the player is grounded 184 00:08:28,848 --> 00:08:31,605 we added a layer in Unity called Ground 185 00:08:31,605 --> 00:08:34,982 and applied it to all of our walkable foreground surfaces. 186 00:08:43,397 --> 00:08:45,969 We then used the Linecast function in 2D 187 00:08:45,969 --> 00:08:47,969 to check whether something on the Ground layer 188 00:08:47,969 --> 00:08:50,234 is below the character's feet. 189 00:08:50,234 --> 00:08:52,777 To customise this more easily we created 190 00:08:52,777 --> 00:08:54,777 an empty game object to use as a point 191 00:08:54,777 --> 00:08:56,777 at which to check for the ground. 192 00:08:56,777 --> 00:08:59,083 By adding a gizmo to this empty object 193 00:08:59,083 --> 00:09:01,083 we are able to manipulate how far below 194 00:09:01,083 --> 00:09:03,083 the character we'll check for the ground. 195 00:09:03,083 --> 00:09:05,486 From a gameplay perspective this means that 196 00:09:05,486 --> 00:09:07,958 the character can only jump when grounded. 197 00:09:08,456 --> 00:09:10,456 Check out the rest of the comments in the script for more 198 00:09:10,456 --> 00:09:12,648 information on the control of the player. 199 00:09:12,648 --> 00:09:14,648 We will discuss the player's weapon 200 00:09:14,648 --> 00:09:15,879 later in this video. 201 00:09:15,879 --> 00:09:17,879 Next, let's take a look at how the camera 202 00:09:17,879 --> 00:09:19,879 tracks the player in our demo. 203 00:09:21,291 --> 00:09:24,352 In 2D games, much like 3D, the motion of 204 00:09:24,352 --> 00:09:26,352 the camera tracking the action can make 205 00:09:26,352 --> 00:09:27,824 or break your game. 206 00:09:27,824 --> 00:09:30,581 For a classic 2D platformer, we looked at the mechanics 207 00:09:30,581 --> 00:09:33,625 of one of the most interesting camera in 2D gaming history, 208 00:09:33,625 --> 00:09:36,651 the camera from Super Mario World on the Super Nintendo 209 00:09:36,651 --> 00:09:38,651 or Super Famicom. 210 00:09:38,651 --> 00:09:40,651 In Super Mario world the camera tracks 211 00:09:40,651 --> 00:09:42,651 horizontally, but uses a dead zone 212 00:09:42,651 --> 00:09:45,119 or margin in the centre of the viewport 213 00:09:45,119 --> 00:09:47,119 in which the character can move a little 214 00:09:47,119 --> 00:09:49,342 without the camera tracking. 215 00:09:49,342 --> 00:09:51,635 Once the character moved beyond this margin 216 00:09:51,635 --> 00:09:54,047 the camera tracks back toward the player. 217 00:09:54,047 --> 00:09:56,867 The Super Mario World camera used particular heights 218 00:09:56,867 --> 00:09:59,544 to snap to vertically, but we didn't need this 219 00:09:59,544 --> 00:10:01,544 kind of detail for our game as we 220 00:10:01,544 --> 00:10:03,878 do not have a long level in the X axis 221 00:10:03,878 --> 00:10:06,848 but more of a stage on which the action takes place. 222 00:10:07,210 --> 00:10:09,210 For this reason our camera employs 223 00:10:09,210 --> 00:10:12,787 similar tracking vertically as it does horizontally. 224 00:10:18,779 --> 00:10:20,779 Take a look at the CameraFollow script on the 225 00:10:20,779 --> 00:10:23,138 mainCamera game object to see comments 226 00:10:23,138 --> 00:10:25,138 on how it achieves this effect. 227 00:10:26,135 --> 00:10:27,845 There are several effects in the game, 228 00:10:27,845 --> 00:10:29,845 but most important is our heroes ability 229 00:10:29,845 --> 00:10:32,732 to slay the alien onslaught he's faced with. 230 00:10:32,732 --> 00:10:36,338 Our hero shoots a bazooka which has animated recoil. 231 00:10:36,338 --> 00:10:38,898 This action is made up of several parts. 232 00:10:38,898 --> 00:10:41,643 First we listen for key input and when the Fire key is 233 00:10:41,643 --> 00:10:43,962 pressed we instantiate a rocket, 234 00:10:43,962 --> 00:10:47,969 play an audio clip and trigger an animation state to play. 235 00:10:47,969 --> 00:10:49,969 Let's break this down even further. 236 00:10:49,969 --> 00:10:52,418 in order to play the Shoot animation while other 237 00:10:52,418 --> 00:10:54,418 animations such as Run are playing we 238 00:10:54,418 --> 00:10:56,418 created a separate layer within our animator 239 00:10:56,418 --> 00:10:57,677 called Shooting. 240 00:10:57,677 --> 00:10:59,677 By setting the Weight property to 1 here 241 00:10:59,677 --> 00:11:02,532 we can totally override motion in the base layer 242 00:11:02,532 --> 00:11:04,532 on any parts of our character that are animated 243 00:11:04,532 --> 00:11:06,980 by clips on the shooting layer. 244 00:11:20,499 --> 00:11:22,499 In this layer we switch to the Shoot animation 245 00:11:22,499 --> 00:11:25,351 from any state, when the Shoot trigger 246 00:11:25,351 --> 00:11:27,351 parameter is called from code. 247 00:11:27,351 --> 00:11:30,543 Let's take a look at the Gun script in charge of this. 248 00:11:32,700 --> 00:11:35,140 Here you can see that we address the animator 249 00:11:35,140 --> 00:11:37,402 and set that trigger to True. 250 00:11:37,402 --> 00:11:40,513 Triggers simply act as a switch and reset themselves to false 251 00:11:40,513 --> 00:11:43,247 on the next frame so that they can be called again, 252 00:11:43,247 --> 00:11:45,511 which is perfect for actions such as shooting. 253 00:11:46,011 --> 00:11:48,673 In addition to setting the animation we fire the 254 00:11:48,673 --> 00:11:50,673 rockets themselves from this script, 255 00:11:50,673 --> 00:11:52,673 playing an audio clip and dependent upon 256 00:11:52,673 --> 00:11:54,673 the direction that the player is facing 257 00:11:54,673 --> 00:11:57,775 we instantiate a rocket and give it a velocity 258 00:11:57,775 --> 00:12:00,555 that's positive or negative in the X axis. 259 00:12:01,276 --> 00:12:03,933 This script is attached to the Gun empty game object 260 00:12:03,933 --> 00:12:05,294 in the hero's hierarchy. 261 00:12:05,294 --> 00:12:08,078 We place code like this on to an empty game object 262 00:12:08,078 --> 00:12:10,078 as it allows us to easily position 263 00:12:10,078 --> 00:12:11,663 where the rockets are created. 264 00:12:11,663 --> 00:12:13,663 We do this by placing the empty object 265 00:12:13,663 --> 00:12:16,010 at the end of the barrel of the bazooka 266 00:12:16,010 --> 00:12:18,010 and then we use it's own position as the 267 00:12:18,010 --> 00:12:20,010 point at which to spawn the rockets. 268 00:12:40,248 --> 00:12:42,804 The rocket itself has a 2D rigidbody 269 00:12:42,804 --> 00:12:44,804 and we assign a velocity to that in order 270 00:12:44,804 --> 00:12:46,804 to make it move. 271 00:12:46,804 --> 00:12:49,096 It has a sprite swap flame exhaust 272 00:12:49,096 --> 00:12:51,096 plus a particle system for smoke. 273 00:12:52,826 --> 00:12:56,482 The particle system also accepts the new sprite type of graphics 274 00:12:56,482 --> 00:12:58,482 so by adding a sprite sheet of smoke puffs 275 00:12:58,482 --> 00:13:00,482 to a material we can assign it to the 276 00:13:00,482 --> 00:13:04,149 texture sheet animation module of the particle system 277 00:13:04,149 --> 00:13:06,232 and we get instant animation of our 278 00:13:06,232 --> 00:13:08,232 sprites for the particle emission. 279 00:13:16,122 --> 00:13:18,935 When our rockets hit an enemy or part of the environment 280 00:13:18,935 --> 00:13:20,935 the rocket itself is destroyed and 281 00:13:20,935 --> 00:13:22,935 an explosion is spawned. 282 00:13:22,935 --> 00:13:24,935 The explosion is simply a sprite game object 283 00:13:24,935 --> 00:13:27,731 that animates through a sprite sheet that we have created. 284 00:13:27,731 --> 00:13:30,311 Yet again using sorting layers to render this 285 00:13:30,311 --> 00:13:33,699 at the lowest layer order of our foreground objects. 286 00:13:36,174 --> 00:13:38,174 When adding sprite-based animation like this 287 00:13:38,174 --> 00:13:40,174 we setup the sprites themselves by 288 00:13:40,174 --> 00:13:42,174 selecting the file in our Project Panel 289 00:13:42,174 --> 00:13:44,576 and choosing the Sprite Mode Multiple. 290 00:13:44,576 --> 00:13:46,576 This gives us access to the sprite editor 291 00:13:46,576 --> 00:13:49,757 which allows us to slice manually or automatically. 292 00:13:49,757 --> 00:13:52,406 Once happy with the selection of sprites from our file 293 00:13:52,406 --> 00:13:54,406 we simply hit Apply and Unity 294 00:13:54,406 --> 00:13:56,765 generates the sprites as children of that file 295 00:13:56,765 --> 00:13:58,765 to be used in our project. 296 00:13:59,707 --> 00:14:01,693 So that's our rocket in a nutshell. 297 00:14:01,693 --> 00:14:03,693 We will discuss the mechanics of killing the enemies 298 00:14:03,693 --> 00:14:06,533 later in this video in the section about enemies. 299 00:14:07,102 --> 00:14:09,448 Let's return to the player character now and look at 300 00:14:09,448 --> 00:14:12,194 how we handle health and taking damage. 301 00:14:12,194 --> 00:14:14,194 Health is stored as a float and 302 00:14:14,194 --> 00:14:16,194 with each interaction with a tagged enemy 303 00:14:16,190 --> 00:14:18,548 we call the TakeDamage function. 304 00:14:18,548 --> 00:14:20,548 This is only allowed to occur after the 305 00:14:20,548 --> 00:14:22,548 repeatDamagePeriod has passed 306 00:14:22,548 --> 00:14:25,347 to avoid the player being killed very quickly. 307 00:14:26,524 --> 00:14:29,136 To allow the player to escape enemies more easily 308 00:14:29,136 --> 00:14:31,136 and to show the player that they are being hurt 309 00:14:31,136 --> 00:14:33,136 we make the act of taking damage 310 00:14:33,136 --> 00:14:34,847 repel the character physically. 311 00:14:34,847 --> 00:14:37,540 To achieve this the TakeDamage function briefly 312 00:14:37,540 --> 00:14:39,540 stops the player from jumping 313 00:14:39,540 --> 00:14:42,125 and finds a vector from the enemy to the player 314 00:14:42,125 --> 00:14:44,125 and repels him in that direction 315 00:14:44,125 --> 00:14:46,125 by adding a physics force. 316 00:14:46,125 --> 00:14:48,684 The hurtForce variable is exposed in the Inspector 317 00:14:48,684 --> 00:14:51,323 as public so that it can be tweaked 318 00:14:51,323 --> 00:14:53,323 to adjust this element of game play without 319 00:14:53,323 --> 00:14:55,323 returning to the script. 320 00:14:55,323 --> 00:14:57,323 In addition to repelling the player, 321 00:14:57,323 --> 00:14:59,810 we of course subtract from the player's health. 322 00:14:59,810 --> 00:15:02,209 and update the player's health bar. 323 00:15:02,209 --> 00:15:04,624 To signify the decrease in health we subtract 324 00:15:04,624 --> 00:15:06,885 from the width of the bar and use a colour lerp 325 00:15:06,885 --> 00:15:09,825 to transition it's colour between green and red, 326 00:15:09,825 --> 00:15:12,640 both by finding the percentage that the current health is 327 00:15:12,640 --> 00:15:14,640 of the full health amount. 328 00:15:14,640 --> 00:15:17,873 The health bar simply comprises of two sprites, 329 00:15:17,873 --> 00:15:19,965 one for the outline of the bar and the other 330 00:15:19,965 --> 00:15:21,744 for the bar itself. 331 00:15:21,744 --> 00:15:23,744 This was again designed in Photoshop and then 332 00:15:23,744 --> 00:15:25,954 the two separate elements were exported. 333 00:15:25,954 --> 00:15:27,954 In the import settings for these sprites 334 00:15:27,954 --> 00:15:30,470 we set their pivot to the middle left of the graphic 335 00:15:30,470 --> 00:15:34,053 so that when it scales down it shrinks towards the left. 336 00:15:48,573 --> 00:15:50,573 These two sprites are placed under an empty 337 00:15:50,573 --> 00:15:52,573 parent game object which has a simple script 338 00:15:52,573 --> 00:15:54,573 on it which makes it follow the player. 339 00:15:54,573 --> 00:15:56,621 We do this by setting the position to the 340 00:15:56,621 --> 00:15:58,621 same as the player object's position 341 00:15:58,621 --> 00:16:00,621 plus an offset that we've made public to allow 342 00:16:00,621 --> 00:16:02,621 for adjustment in the Inspector. 343 00:16:16,215 --> 00:16:18,215 When the player has 0 health remaining 344 00:16:18,215 --> 00:16:20,215 we allow him to fall through the level by 345 00:16:20,215 --> 00:16:22,629 setting his colliders to triggers, 346 00:16:22,629 --> 00:16:24,629 and we move him to the very front of rendering 347 00:16:24,629 --> 00:16:28,194 by placing his sprite renderers on the UI Sorting layer, 348 00:16:28,194 --> 00:16:31,594 one we've made to render in front of everything in the game. 349 00:16:31,594 --> 00:16:34,223 We have 2 animations for when the player dies. 350 00:16:34,223 --> 00:16:37,252 1 called Death, where he loses his hat and gun 351 00:16:37,252 --> 00:16:38,631 and another called Falling. 352 00:16:38,631 --> 00:16:40,631 We naturally transition in to Falling once 353 00:16:40,631 --> 00:16:44,002 the Death animation completes by using the Exit Time 354 00:16:44,002 --> 00:16:47,239 as our transition condition in the animator. 355 00:16:50,778 --> 00:16:52,778 Finally, to stop the player moving the character 356 00:16:52,778 --> 00:16:55,278 or shooting during the Death sequence 357 00:16:55,278 --> 00:16:58,340 we disable the PlayerControl and Gun scripts. 358 00:16:58,340 --> 00:17:00,731 Because the Die function is made as public 359 00:17:00,731 --> 00:17:03,332 we can call it from elsewhere, such as if the player 360 00:17:03,332 --> 00:17:05,040 falls in to the water. 361 00:17:05,040 --> 00:17:07,733 To reset the game once the player does hit the water 362 00:17:07,733 --> 00:17:09,733 we have a KillTrigger object, which simply 363 00:17:09,733 --> 00:17:12,463 comprises of a trigger collider and a script. 364 00:17:12,463 --> 00:17:15,012 For most of the game the purpose of the Remover script 365 00:17:15,012 --> 00:17:17,012 is to remove our enemy objects that fall in 366 00:17:17,012 --> 00:17:19,789 to the river, and instantiate a splash animation 367 00:17:19,789 --> 00:17:21,442 and sound effect. 368 00:17:21,442 --> 00:17:24,001 However, when the player is detected by this trigger 369 00:17:24,001 --> 00:17:27,092 we call the Die function in the PlayerHealth script 370 00:17:27,092 --> 00:17:29,092 and also disable CameraTracking 371 00:17:29,092 --> 00:17:31,092 whilst moving the player off screen 372 00:17:31,092 --> 00:17:34,527 and calling a co-routiene that pauses for 2 seconds 373 00:17:34,527 --> 00:17:36,527 and then reloads the level. 374 00:17:37,079 --> 00:17:39,079 But let's not dwell on the death of the player, 375 00:17:39,079 --> 00:17:41,079 let's look at his survival and the tools that we give 376 00:17:41,079 --> 00:17:42,481 him to do that. 377 00:17:42,481 --> 00:17:44,481 Our game features 2 airdropped crates that 378 00:17:44,481 --> 00:17:47,124 assist the player, 1 containing a bomb, 379 00:17:47,124 --> 00:17:49,911 the other a med kit to boost health. 380 00:17:50,411 --> 00:17:52,963 These crate drops are made up of 2 parts. 381 00:17:52,963 --> 00:17:55,695 The crate itself and a parachute. 382 00:17:58,046 --> 00:18:01,311 These 2 elements are nested beneath an empty parent object 383 00:18:01,311 --> 00:18:03,768 to allow us to animate them as a group. 384 00:18:03,768 --> 00:18:05,768 We position the 2 sprites so that the parachute's 385 00:18:05,768 --> 00:18:08,476 centre is at the centre of the parent. 386 00:18:09,045 --> 00:18:11,907 This way the animation can swing left and right 387 00:18:11,907 --> 00:18:15,307 as if the entire parachuting crate is floating to the ground. 388 00:18:15,307 --> 00:18:17,307 We then simply add a rigidbody to cause 389 00:18:17,307 --> 00:18:19,307 gravity to pull the object down 390 00:18:19,307 --> 00:18:21,307 and add colliders to the crate so that 391 00:18:21,307 --> 00:18:23,307 we can detect when it lands and when 392 00:18:23,307 --> 00:18:24,962 the player picks up the crate. 393 00:18:24,962 --> 00:18:26,962 Upon landing we transition to a second 394 00:18:26,962 --> 00:18:30,513 animation state which scales the parachute down. 395 00:18:30,513 --> 00:18:33,308 Like other parts of our game, the animator handles 396 00:18:33,308 --> 00:18:34,916 the states of the object. 397 00:18:34,916 --> 00:18:36,916 We can see that by default it plays the 398 00:18:36,916 --> 00:18:38,916 floatDown animation state 399 00:18:38,916 --> 00:18:40,916 but then switches to a landing state 400 00:18:40,916 --> 00:18:43,472 when the trigger Land is set to true. 401 00:18:43,972 --> 00:18:47,383 In our script we do this using an onTriggerEnter function, 402 00:18:47,383 --> 00:18:49,732 which detects the ground via a tag. 403 00:18:49,732 --> 00:18:52,822 We also detatch the crate itself from the parent object 404 00:18:52,822 --> 00:18:55,098 and give it a rigidbody of it's own 405 00:18:55,098 --> 00:18:57,490 so that it can interact with the environment 406 00:18:57,490 --> 00:19:00,624 resting realistically on a slope if it lands on one. 407 00:19:00,624 --> 00:19:03,672 Let's focus on the bomb first of all. 408 00:19:03,672 --> 00:19:05,672 Picking up the bomb crate is handled on the 409 00:19:05,672 --> 00:19:08,475 BombPickup script, attached to the crate. 410 00:19:08,475 --> 00:19:11,057 We pickup the crate by destroying it and adding to 411 00:19:11,057 --> 00:19:13,057 the count of bombs that the player has 412 00:19:13,057 --> 00:19:15,057 in the script attached to the player called 413 00:19:15,057 --> 00:19:16,739 LayBombs 414 00:19:17,557 --> 00:19:19,557 The LayBombs script simply checks if 415 00:19:19,557 --> 00:19:21,557 the player is carrying a bomb 416 00:19:21,557 --> 00:19:23,557 and then instantiates an instance 417 00:19:23,557 --> 00:19:25,557 of the Bomb prefab. 418 00:19:27,424 --> 00:19:29,952 The Bomb prefab has a timed fuse 419 00:19:29,952 --> 00:19:32,147 which waits by using an yield within the 420 00:19:32,147 --> 00:19:34,147 BombDetonation co-routiene 421 00:19:34,147 --> 00:19:36,147 before calling the Explode function. 422 00:19:36,799 --> 00:19:39,545 The Explode function performs several actions. 423 00:19:39,545 --> 00:19:41,545 First it resets the bombLaid variable 424 00:19:41,545 --> 00:19:43,797 to allow another bomb to be deployed, 425 00:19:43,797 --> 00:19:45,797 it tells the pickup spawner it is allowed to 426 00:19:45,797 --> 00:19:47,797 spawn a new crate drop and kills 427 00:19:47,797 --> 00:19:49,797 enemies within a defined blast radian. 428 00:19:50,518 --> 00:19:53,058 Let's take a look at how this last part works. 429 00:19:53,058 --> 00:19:55,058 Because bombs are lethal to enemies regardless of 430 00:19:55,058 --> 00:19:57,180 their remaining hit points we use the 431 00:19:57,180 --> 00:19:59,976 Physics.OverlapCircleAll to collect all objects 432 00:19:59,976 --> 00:20:03,470 tagged Enemy within a certain radius of the bomb. 433 00:20:03,470 --> 00:20:06,612 We then run a foreach loop for every enemy found 434 00:20:06,612 --> 00:20:10,663 setting their health to 0 finding a vector from where the bomb was 435 00:20:10,663 --> 00:20:12,663 to where the enemy is, in order to apply 436 00:20:12,663 --> 00:20:15,542 a force in the direction of that vector. 437 00:20:16,304 --> 00:20:18,538 Once the foreach loop is complete 438 00:20:18,538 --> 00:20:21,381 we play and instantiate visual effects, 439 00:20:21,381 --> 00:20:23,381 play an audio clip for the explosion 440 00:20:23,381 --> 00:20:25,907 and of course destroy the bomb itself. 441 00:20:26,875 --> 00:20:29,252 The visual of the explosion is twofold. 442 00:20:29,252 --> 00:20:31,252 The main part is a simple circle that appears 443 00:20:31,252 --> 00:20:33,583 briefly and is then destroyed 444 00:20:33,583 --> 00:20:35,583 and the second part is a particle system of 445 00:20:35,583 --> 00:20:37,583 stars that reuses the same sprites 446 00:20:37,583 --> 00:20:39,583 as our rocket explosion. 447 00:20:42,265 --> 00:20:44,265 For efficiency we keep this particle 448 00:20:44,265 --> 00:20:46,265 system in the scene at all times 449 00:20:46,265 --> 00:20:48,265 and when it is required we use code 450 00:20:48,265 --> 00:20:51,735 to move the system to the desired position and play it. 451 00:20:52,511 --> 00:20:54,511 This keeps the particle system in memory 452 00:20:54,511 --> 00:20:56,511 and makes the game more efficient. 453 00:20:57,011 --> 00:20:59,011 It's worth noting that we can do this 454 00:20:59,011 --> 00:21:01,011 because we know we will only have 1 455 00:21:01,011 --> 00:21:04,668 single explosion in the scene at any one time 456 00:21:04,668 --> 00:21:07,794 as the player can only throw 1 bomb at a time. 457 00:21:07,794 --> 00:21:09,794 This is why keeping our particle system in the 458 00:21:09,794 --> 00:21:11,794 scene and replaying it is more 459 00:21:11,794 --> 00:21:14,936 efficient than creating instances and then removing them. 460 00:21:15,714 --> 00:21:17,618 With the rocket explosion however, 461 00:21:17,618 --> 00:21:19,618 we can have many at once so we do 462 00:21:19,618 --> 00:21:21,618 need to spawn and remove them. 463 00:21:22,118 --> 00:21:24,118 Now let's take a look at what happens when our player 464 00:21:24,118 --> 00:21:26,118 kills an enemy and scores points. 465 00:21:26,618 --> 00:21:28,436 This is done in 2 parts, 466 00:21:28,436 --> 00:21:31,668 a scoring animation that plays showing 100 points earned 467 00:21:31,668 --> 00:21:33,668 and the score UI at the top of the screen 468 00:21:33,668 --> 00:21:35,528 that increments. 469 00:21:35,528 --> 00:21:38,303 The score animation is made up to 2 number sprites, 470 00:21:38,303 --> 00:21:40,193 a 1 and a 0. 471 00:21:40,193 --> 00:21:42,872 We place this in the scene under an empty parent object 472 00:21:42,872 --> 00:21:46,036 and animated them using a simple destroyer script to 473 00:21:46,036 --> 00:21:49,186 remove them from the scene when the animation is complete. 474 00:21:49,186 --> 00:21:51,186 We call the destroyer function in the script 475 00:21:51,186 --> 00:21:53,186 by placing an animation event 476 00:21:53,186 --> 00:21:55,186 at the end of the timeline. 477 00:22:06,142 --> 00:22:09,703 The ScoreUI itself is a simple GUI text component 478 00:22:09,703 --> 00:22:11,703 with a custom font and script that manages 479 00:22:11,703 --> 00:22:13,703 the score for the player. 480 00:22:13,703 --> 00:22:16,759 The Score variable is public, meaning that we can address it 481 00:22:16,759 --> 00:22:18,980 from the Enemy script when they are killed 482 00:22:18,980 --> 00:22:20,980 and add 100 points to the value. 483 00:22:20,980 --> 00:22:22,980 Speaking of the enemies, let's take a look 484 00:22:22,980 --> 00:22:24,980 at them more in depth now. 485 00:22:25,480 --> 00:22:28,260 In our game we have 2 types of alien enemy, 486 00:22:28,260 --> 00:22:30,854 a green slug-like monster and a smarter 487 00:22:30,854 --> 00:22:32,854 alien that brought his ship with him for 488 00:22:32,854 --> 00:22:34,563 protection during the invasion. 489 00:22:34,563 --> 00:22:36,563 These characters share the same script 490 00:22:36,563 --> 00:22:38,563 as the behaviour is very similar 491 00:22:38,563 --> 00:22:40,881 and we allow for differing movement speeds 492 00:22:40,881 --> 00:22:42,881 and amounts of hit points by setting 493 00:22:42,881 --> 00:22:45,765 these as public variables in the Inspector. 494 00:22:46,638 --> 00:22:49,093 Each enemy has it's own Walk animation. 495 00:22:49,093 --> 00:22:51,093 The slug has a moving tail, whist the 496 00:22:51,093 --> 00:22:54,444 ship-based enemy rocks back and forth as it approaches. 497 00:22:55,994 --> 00:22:57,994 For the slug we used the sprite importer 498 00:22:57,994 --> 00:22:59,994 to define the tail section of the graphic 499 00:22:59,994 --> 00:23:01,994 as a separate sprite element, 500 00:23:01,994 --> 00:23:04,438 meaning that we could animate it individually 501 00:23:04,438 --> 00:23:07,475 and avoid having to scale the entire sprite. 502 00:23:07,475 --> 00:23:09,475 By setting the pivot to the right 503 00:23:09,475 --> 00:23:12,124 we are able to animate the tail expanding and contracting 504 00:23:12,124 --> 00:23:14,124 from that point. 505 00:23:16,475 --> 00:23:19,918 For added character we then move the eyelid up and down 506 00:23:19,918 --> 00:23:21,918 and we use the Z value to sort the sprites 507 00:23:21,918 --> 00:23:24,859 amongst one another, the eye being below the eyelid 508 00:23:24,859 --> 00:23:26,859 so that we could animate it over the top. 509 00:23:28,865 --> 00:23:31,268 The second enemy's animation was much simpler 510 00:23:31,268 --> 00:23:34,046 and just meant that we rotated it back and forth. 511 00:23:35,798 --> 00:23:37,798 For the mechanics of moving the enemies 512 00:23:37,798 --> 00:23:41,229 we drive them by setting the velocity of the rigidbody. 513 00:23:41,229 --> 00:23:43,889 When they encounter an obstacle such as a wall 514 00:23:43,889 --> 00:23:47,826 they detect this by using a Physics.OverlapPoint function, 515 00:23:47,826 --> 00:23:51,317 which checks for a point in space overlapping a collider. 516 00:23:51,317 --> 00:23:53,854 Our walls, the towers at each side of the level, 517 00:23:53,854 --> 00:23:55,854 are tagged as obstacles. 518 00:23:55,850 --> 00:23:59,161 When this function detects them it calls the Flip function, 519 00:23:59,161 --> 00:24:01,767 it reverses the X scale of the enemy 520 00:24:01,767 --> 00:24:04,070 sending them moving in a different direction. 521 00:24:04,070 --> 00:24:06,070 To kill the enemies, each time a rocket collides 522 00:24:06,070 --> 00:24:09,036 with them it's script calls the Hurt function on 523 00:24:09,036 --> 00:24:11,036 the particular enemy that it's hit. 524 00:24:14,962 --> 00:24:16,962 In this function we subtract 1 from the 525 00:24:16,962 --> 00:24:19,213 hit points of the particular enemy. 526 00:24:19,213 --> 00:24:21,213 We then keep tabs on the enemy's health 527 00:24:21,213 --> 00:24:23,213 inside the fixed update function. 528 00:24:23,213 --> 00:24:27,124 If it drops to 0 we call the Death function. 529 00:24:31,229 --> 00:24:33,916 When they die we perform a number of functions. 530 00:24:33,916 --> 00:24:35,916 Firstly we disable all sprite renderers 531 00:24:35,916 --> 00:24:37,916 as our 2D characters are made up of a 532 00:24:37,916 --> 00:24:39,916 number of sprite objects that are animated. 533 00:24:40,941 --> 00:24:42,941 This is because we simply want to swap out the 534 00:24:42,941 --> 00:24:44,941 animated elements for a single sprite 535 00:24:44,941 --> 00:24:46,941 of the dead character 536 00:24:47,745 --> 00:24:49,745 We do this with the main sprite renderer by 537 00:24:49,745 --> 00:24:51,745 setting it to use the sprite assigned to 538 00:24:51,745 --> 00:24:54,165 the deadEnemy variable. 539 00:24:54,165 --> 00:24:56,165 We then add to the score using the public 540 00:24:56,165 --> 00:24:58,165 variable in the Score script 541 00:24:58,165 --> 00:25:00,744 and we add some visual flare to the enemy's death 542 00:25:00,744 --> 00:25:03,534 by adding torque to spin them as they die. 543 00:25:04,448 --> 00:25:06,448 Because we need the enemies to fall through the 544 00:25:06,448 --> 00:25:08,881 environment and land in the river when they die 545 00:25:08,881 --> 00:25:10,881 we find all colliders on the object 546 00:25:10,881 --> 00:25:13,589 and set their IsTrigger parameter to true. 547 00:25:13,589 --> 00:25:15,139 This means that they will pass through the 548 00:25:15,139 --> 00:25:17,417 environment colliders. 549 00:25:17,417 --> 00:25:20,054 We then choose from an array of death audio clips 550 00:25:20,054 --> 00:25:22,054 and play one of them back, before creating 551 00:25:22,054 --> 00:25:25,470 an instance of the Score animation we showed you earlier. 552 00:25:27,876 --> 00:25:29,876 To remove the dead enemy from the scene 553 00:25:29,876 --> 00:25:31,876 we rely on the killTrigger object 554 00:25:31,876 --> 00:25:34,762 It performs the same function as discussed earlier 555 00:25:34,762 --> 00:25:36,762 as any non-player object touching it 556 00:25:36,762 --> 00:25:39,950 will cause a splash animation and remove that object. 557 00:25:39,950 --> 00:25:41,950 The sound effect of them hitting the water is 558 00:25:41,950 --> 00:25:43,950 an audio clip attached to the animated 559 00:25:43,950 --> 00:25:45,950 splash which plays on awake 560 00:25:45,950 --> 00:25:47,950 so that when we create an instance of the animated 561 00:25:47,950 --> 00:25:50,634 object we hear the sound right away. 562 00:25:55,153 --> 00:25:57,153 To finish the game level re decorated the 563 00:25:57,153 --> 00:25:59,153 background with a number of moving props 564 00:25:59,153 --> 00:26:02,302 in order to make our game environment feel more dynamic. 565 00:26:02,302 --> 00:26:05,703 We added flying swans, plus buses and taxis that drive 566 00:26:05,703 --> 00:26:07,125 along the river bank. 567 00:26:07,125 --> 00:26:10,634 First was the swan, which was created from a sprite sheet, 568 00:26:10,634 --> 00:26:12,634 drawn in Photoshop and imported using 569 00:26:12,634 --> 00:26:14,634 the Multiple Sprite Mode import setting 570 00:26:14,634 --> 00:26:16,051 in the Inspector. 571 00:26:16,051 --> 00:26:18,800 By choosing this approach Unity automates choosing 572 00:26:18,800 --> 00:26:20,800 each frame in the sheet and importing 573 00:26:20,800 --> 00:26:22,800 it as a separate sprite under the parent 574 00:26:22,800 --> 00:26:24,579 hierarchy of the asset. 575 00:26:24,579 --> 00:26:27,279 Because this is a linear set of animation frames 576 00:26:27,279 --> 00:26:29,279 we could simply drag all of these sprites in to the 577 00:26:29,279 --> 00:26:32,346 scene to let Unity animate them for us. 578 00:26:32,346 --> 00:26:35,317 Et voila, our animated swan is ready to add 579 00:26:35,317 --> 00:26:37,759 as a background element. 580 00:26:37,759 --> 00:26:40,165 The swan was then given a rigidbody2D 581 00:26:40,165 --> 00:26:42,165 so that we can use velocity to send it 582 00:26:42,165 --> 00:26:43,369 across the screen. 583 00:26:43,369 --> 00:26:47,334 As with the bus and the cab, the swan is saved as a prefab. 584 00:26:49,257 --> 00:26:51,257 For the bus and taxi prefabs we 585 00:26:51,257 --> 00:26:53,257 simply separated the bodies and wheels of 586 00:26:53,257 --> 00:26:55,257 the vehicles in the sprite importer 587 00:26:55,257 --> 00:26:58,392 and made a simple bobbing animation. 588 00:26:58,392 --> 00:27:00,793 Applying a 2d rigidbody to these as well, 589 00:27:00,793 --> 00:27:02,793 we were able to drive them across the screen 590 00:27:02,793 --> 00:27:04,376 using velocity. 591 00:27:07,279 --> 00:27:10,271 For all 3 props, the bus, taxi and the swan 592 00:27:10,271 --> 00:27:12,271 we created a script we could reuse 593 00:27:12,271 --> 00:27:14,271 which is in charge of spawning them. 594 00:27:14,271 --> 00:27:16,616 The BackgroundPropsSpawner script 595 00:27:16,616 --> 00:27:19,838 also handles the frequency, a speed to give them 596 00:27:19,838 --> 00:27:21,838 and where on screen to spawn them. 597 00:27:21,838 --> 00:27:24,521 This meant that we could make 3 creator objects 598 00:27:24,521 --> 00:27:26,521 with the same script on. 599 00:27:26,521 --> 00:27:28,521 Changing which prefab will be spawned 600 00:27:28,521 --> 00:27:30,521 and what properties to give it. 601 00:27:30,521 --> 00:27:33,854 Take a look at the comments in the script to learn more. 602 00:27:33,854 --> 00:27:36,172 Finally, for more background dynamism, 603 00:27:36,172 --> 00:27:40,409 we added rolling clouds, panning river details and fog. 604 00:27:41,323 --> 00:27:44,525 We did this by adding 2 instances of the background sprite 605 00:27:44,525 --> 00:27:48,004 to a parent object and simply used animation to slowly 606 00:27:48,004 --> 00:27:50,004 pan them across the screen. 607 00:27:50,004 --> 00:27:52,652 Because this animation loops our animation will 608 00:27:52,652 --> 00:27:54,652 continue indefinitely. 609 00:27:59,185 --> 00:28:01,031 And that's how we made our game. 610 00:28:01,031 --> 00:28:03,031 We hope this overview has given you some idea of 611 00:28:03,031 --> 00:28:05,516 how we create 2D games in Unity, 612 00:28:05,516 --> 00:28:07,516 and we'll be creating more simply projects and 613 00:28:07,516 --> 00:28:08,971 tutorials in the future. 614 00:28:08,971 --> 00:28:11,689 We look forward to your feedback on Unity4.3 615 00:28:11,689 --> 00:28:13,689 and we can't wait to see the great 2D titles 616 00:28:13,689 --> 00:28:14,959 that you'll come up with. 617 00:28:14,959 --> 00:28:16,487 Thanks for watching.