Placeholder Image

Subtitles section Play video

  • In Unity 4.3 we're launching our first set of 2D features.

  • To compliment this we have constructed a

  • demo project with these tools.

  • Our 2D platformer is nicknamed 'Tower Bridge Defence'

  • It depicts London's Tower Bridge in the midst

  • of an alien invasion.

  • It's a completely sprite-based, physics driven

  • 2D sample level that we hope will help you

  • understand how 2D games are put together in Unity.

  • This video will discuss the background and

  • foreground construction, characters, effects,

  • camera tracking, animation and scripting

  • used in the demo.

  • To begin with, let's discuss the basics

  • of working in 2D in Unity.

  • Firstly, when working in 2D, you should set the

  • Editor Behaviour Mode to 2D

  • for various settings.

  • This can be done when making a new project

  • using the drop-down on the project wizard

  • or during a project by choosing

  • Edit - Project Settings - Editor from the top menu.

  • This means that by default textures

  • will be imported as sprites and the

  • Scene View will default to 2D mode.

  • This new mode gives you a completely orthographic

  • view in which to construct 2D games.

  • It also hides the usual 3D gizmo

  • in the top right of the view, giving you more space

  • to work in. Aside from these settings the work

  • flows for 2D have been designed to mirror

  • existing Unity approaches to 3D game creation.

  • So if you already know a little about Unity

  • you'll be in a great position to start making

  • 2D games right away.

  • It's worth noting at this stage that you can

  • still mix 2D and 3D in Unity,

  • so if you want to add 3D elements to your 2D game

  • or vice versa you can do that with no worries.

  • Let's take a look at the demo project itself,

  • and how we built it up one stage at a time.

  • We began by sketching out the level design

  • for this sample level and then went about

  • recreating the layout in Photoshop.

  • Creating and exporting the layers,

  • we were able to import these in to Unity

  • using the new Sprite type.

  • In order to create parallaxing in our background later,

  • we kept some of the background elements separate

  • and placed them on to a Background Sorting Layer.

  • Yet another new feature of 2D development in Unity.

  • Having assigned all of our backgrounds to this layer,

  • we could then use the Order In Layer property

  • of the Sprite Renderer to sort them.

  • Once we were happy with their positions

  • we could lock the Background Sorting Layer

  • so that when we added foreground elements

  • we didn't need to worry about accidentally

  • dragging background elements around.

  • This is done using the Layers pull-down in the

  • top right of the interface.

  • Because the background elements are purely decorative

  • we did not require any additional components

  • on the sprite game object.

  • They were parented to an empty game object

  • that has a simple script to handle parallaxing

  • called BackgroundParallax.

  • For more information you'll find this script

  • fully commented in the Scripts folder.

  • Next up came the creation of the foreground elements

  • that our characters would actually traverse.

  • We designed London's Tower Bridge with a UFO

  • landed in the centre.

  • The character has the run of the environment

  • as enemies spawn from the skies and begin

  • to navigate around the level.

  • As such, each piece of the foreground required

  • a collider for characters to walk upon.

  • For most of the environment we used 2D

  • box colliders for efficiency,

  • but the UFO itself has a more complex shape.

  • Unity's Polygon Collider allowed us to

  • automate creation of the collider itself

  • based on the shape of the sprite.

  • It even meant that we could tweak the shape of

  • the collider later.

  • Moving, adding or subtracting points

  • of the collider shape to make it more

  • appropriate to walk over.

  • To sort these foregrounds we created a

  • Foregrounds Sorting Layer, which was drawn

  • above the backgrounds in the Tags And Layers manager.

  • Next, let's take a look at our hero.

  • Our player character was yet again designed

  • in Photoshop, and for this demo

  • we chose to make a character with independent

  • limbs and features in the style of

  • 2D hits such as Rayman.

  • Our other option would have been to design

  • a sprite sheet-based animation and design each

  • each frame in Photoshop,

  • an approach we use later for the background Swan,

  • which we'll discuss later in the video.

  • Because our character had independent elements

  • that we wish to animate we finalised the design

  • and then moved his bodily elements in to separate

  • spaces on our canvas to allow Unity to isolate them

  • as separate sprites in the Importer.

  • This meant that we could then arrange all of

  • our sprites as separate elements to be animated.

  • We placed these on to a new Character Sorting Layer

  • that we created, and then used Z values in the

  • transform to sort their rendering depth.

  • All of these sprites are then arranged under an

  • empty game object, which has all of our

  • controls scripting, colliders, physics, excetera attached to it.

  • Once we'd done this we were able to use the newly

  • upgraded Animation window to create

  • Idle, Run, Jump, Shoot and Death animations

  • by animating each of the character's sprites over time.

  • With the new Dopesheet View in the Animation window

  • this is easier than ever.

  • We simply add animation to the parent object

  • and then create keyframes for any of the child objects.

  • Moving the playhead to where we want

  • and then moving the various parts of the character

  • to automatically keyframe the animation.

  • The ability to switch between Curve and Dopesheet

  • representation of our animation makes it easier than

  • ever to adjust timing and design.

  • With these animations created we can

  • then design a state machine for our character

  • so that when called upon in code, differing animations

  • could be played.

  • the animator controller for the character is

  • not driving a 3D biped, so we simply deselect

  • Apply Root Motion and select Animate Physics

  • in order to drive our animations in time with

  • the physics engine.

  • In order to traverse the environment our hero has a

  • circle collider at his feet and a box collider

  • to cover the rest of his body outline.

  • This means he can smoothly walk up and down hills

  • and when he jumps his head will hit the ceiling.

  • In order to control the character and it's animations

  • we wrote a script that moves him via 2D physics forces.

  • This means that we can apply physics to him

  • and the enemies during the game for more

  • dynamic game play.

  • In our PlayerControl script for the character

  • we check for player input.

  • We use this to apply physics forces

  • for movement and also send the value of the input

  • to the animator, which in turn defines which

  • animation should be playing and smoothly transitions

  • between the different animation clips that

  • we've created as states.

  • The great thing about using the animator to

  • create states from animation clips is

  • that we can go and tweak speeds of animation

  • to match our physics velocities

  • without having to reanimate anything

  • The FixedUpdate function evaluates with

  • each physics step, and the first thing we

  • do with this is to feed the value of Horizontal

  • input in to the Speed parameter of our animator.

  • The transition between Idle and Run

  • in our simple state machine requires

  • that the Speed parameter is above 0.1.

  • When it is, the animator blends from Idle

  • in to the Run state.

  • We then go on to add forces to the player's

  • 2D physics component, the rigidbody2D,

  • in order to move him around.

  • We also handle which direction the character is facing

  • based on the value of Horizontal input,

  • checking whether it is above or below 0.

  • This is because in Unity, holding the left input key

  • returns a value of -1, where right returns positive 1.

  • Depending on input, we then call a simple flip function,

  • which reverses the X scale of the character,

  • giving him the appearance of facing the opposite direction.

  • To decide whether the player is grounded

  • we added a layer in Unity called Ground

  • and applied it to all of our walkable foreground surfaces.

  • We then used the Linecast function in 2D

  • to check whether something on the Ground layer

  • is below the character's feet.

  • To customise this more easily we created

  • an empty game object to use as a point

  • at which to check for the ground.

  • By adding a gizmo to this empty object

  • we are able to manipulate how far below

  • the character we'll check for the ground.

  • From a gameplay perspective this means that

  • the character can only jump when grounded.

  • Check out the rest of the comments in the script for more

  • information on the control of the player.

  • We will discuss the player's weapon

  • later in this video.

  • Next, let's take a look at how the camera

  • tracks the player in our demo.

  • In 2D games, much like 3D, the motion of

  • the camera tracking the action can make

  • or break your game.

  • For a classic 2D platformer, we looked at the mechanics

  • of one of the most interesting camera in 2D gaming history,

  • the camera from Super Mario World on the Super Nintendo

  • or Super Famicom.

  • In Super Mario world the camera tracks

  • horizontally, but uses a dead zone

  • or margin in the centre of the viewport

  • in which the character can move a little

  • without the camera tracking.

  • Once the character moved beyond this margin

  • the camera tracks back toward the player.

  • The Super Mario World camera used particular heights

  • to snap to vertically, but we didn't need this

  • kind of detail for our game as we

  • do not have a long level in the X axis

  • but more of a stage on which the action takes place.

  • For this reason our camera employs

  • similar tracking vertically as it does horizontally.

  • Take a look at the CameraFollow script on the

  • mainCamera game object to see comments

  • on how it achieves this effect.

  • There are several effects in the game,

  • but most important is our heroes ability

  • to slay the alien onslaught he's faced with.

  • Our hero shoots a bazooka which has animated recoil.

  • This action is made up of several parts.

  • First we listen for key input and when the Fire key is

  • pressed we instantiate a rocket,

  • play an audio clip and trigger an animation state to play.

  • Let's break this down even further.

  • in order to play the Shoot animation while other

  • animations such as Run are playing we

  • created a separate layer within our animator

  • called Shooting.

  • By setting the Weight property to 1 here

  • we can totally override motion in the base layer

  • on any parts of our character that are animated

  • by clips on the shooting layer.

  • In this layer we switch to the Shoot animation

  • from any state, when the Shoot trigger

  • parameter is called from code.

  • Let's take a look at the Gun script in charge of this.

  • Here you can see that we address the animator

  • and set that trigger to True.

  • Triggers simply act as a switch and reset themselves to false

  • on the next frame so that they can be called again,

  • which is perfect for actions such as shooting.

  • In addition to setting the animation we fire the

  • rockets themselves from this script,

  • playing an audio clip and dependent upon

  • the direction that the player is facing

  • we instantiate a rocket and give it a velocity

  • that's positive or negative in the X axis.

  • This script is attached to the Gun empty game object

  • in the hero's hierarchy.

  • We place code like this on to an empty game object

  • as it allows us to easily position

  • where the rockets are created.

  • We do this by placing the empty object

  • at the end of the barrel of the bazooka

  • and then we use it's own position as the

  • point at which to spawn the rockets.

  • The rocket itself has a 2D rigidbody

  • and we assign a velocity to that in order

  • to make it move.

  • It has a sprite swap flame exhaust

  • plus a particle system for smoke.

  • The particle system also accepts the new sprite type of graphics

  • so by adding a sprite sheet of smoke puffs

  • to a material we can assign it to the

  • texture sheet animation module of the particle system

  • and we get instant animation of our

  • sprites for the particle emission.

  • When our rockets hit an enemy or part of the environment

  • the rocket itself is destroyed and

  • an explosion is spawned.

  • The explosion is simply a sprite game object

  • that animates through a sprite sheet that we have created.

  • Yet again using sorting layers to render this

  • at the lowest layer order of our foreground objects.

  • When adding sprite-based animation like this

  • we setup the sprites themselves by

  • selecting the file in our Project Panel

  • and choosing the Sprite Mode Multiple.

  • This gives us access to the sprite editor

  • which allows us to slice manually or automatically.

  • Once happy with the selection of sprites from our file

  • we simply hit Apply and Unity

  • generates the sprites as children of that file

  • to be used in our project.

  • So that's our rocket in a nutshell.

  • We will discuss the mechanics of killing the enemies

  • later in this video in the section about enemies.

  • Let's return to the player character now and look at

  • how we handle health and taking damage.

  • Health is stored as a float and

  • with each interaction with a tagged enemy

  • we call the TakeDamage function.

  • This is only allowed to occur after the

  • repeatDamagePeriod has passed

  • to avoid the player being killed very quickly.

  • To allow the player to escape enemies more easily

  • and to show the player that they are being hurt

  • we make the act of taking damage

  • repel the character physically.

  • To achieve this the TakeDamage function briefly

  • stops the player from jumping

  • and finds a vector from the enemy to the player

  • and repels him in that direction

  • by adding a physics force.

  • The hurtForce variable is exposed in the Inspector

  • as public so that it can be tweaked

  • to adjust this element of game play without

  • returning to the script.

  • In addition to repelling the player,

  • we of course subtract from the player's health.

  • and update the player's health bar.

  • To signify the decrease in health we subtract

  • from the width of the bar and use a colour lerp

  • to transition it's colour between green and red,

  • both by finding the percentage that the current health is

  • of the full health amount.

  • The health bar simply comprises of two sprites,

  • one for the outline of the bar and the other

  • for the bar itself.

  • This was again designed in Photoshop and then

  • the two separate elements were exported.

  • In the import settings for these sprites

  • we set their pivot to the middle left of the graphic

  • so that when it scales down it shrinks towards the left.

  • These two sprites are placed under an empty

  • parent game object which has a simple script

  • on it which makes it follow the player.

  • We do this by setting the position to the

  • same as the player object's position

  • plus an offset that we've made public to allow

  • for adjustment in the Inspector.

  • When the player has 0 health remaining

  • we allow him to fall through the level by

  • setting his colliders to triggers,

  • and we move him to the very front of rendering

  • by placing his sprite renderers on the UI Sorting layer,

  • one we've made to render in front of everything in the game.

  • We have 2 animations for when the player dies.

  • 1 called Death, where he loses his hat and gun

  • and another called Falling.

  • We naturally transition in to Falling once

  • the Death animation completes by using the Exit Time

  • as our transition condition in the animator.

  • Finally, to stop the player moving the character

  • or shooting during the Death sequence

  • we disable the PlayerControl and Gun scripts.

  • Because the Die function is made as public

  • we can call it from elsewhere, such as if the player

  • falls in to the water.

  • To reset the game once the player does hit the water

  • we have a KillTrigger object, which simply

  • comprises of a trigger collider and a script.

  • For most of the game the purpose of the Remover script

  • is to remove our enemy objects that fall in

  • to the river, and instantiate a splash animation

  • and sound effect.

  • However, when the player is detected by this trigger

  • we call the Die function in the PlayerHealth script

  • and also disable CameraTracking

  • whilst moving the player off screen

  • and calling a co-routiene that pauses for 2 seconds

  • and then reloads the level.

  • But let's not dwell on the death of the player,

  • let's look at his survival and the tools that we give

  • him to do that.

  • Our game features 2 airdropped crates that

  • assist the player, 1 containing a bomb,

  • the other a med kit to boost health.

  • These crate drops are made up of 2 parts.

  • The crate itself and a parachute.

  • These 2 elements are nested beneath an empty parent object

  • to allow us to animate them as a group.

  • We position the 2 sprites so that the parachute's

  • centre is at the centre of the parent.

  • This way the animation can swing left and right

  • as if the entire parachuting crate is floating to the ground.

  • We then simply add a rigidbody to cause

  • gravity to pull the object down

  • and add colliders to the crate so that

  • we can detect when it lands and when

  • the player picks up the crate.

  • Upon landing we transition to a second

  • animation state which scales the parachute down.

  • Like other parts of our game, the animator handles

  • the states of the object.

  • We can see that by default it plays the

  • floatDown animation state

  • but then switches to a landing state

  • when the trigger Land is set to true.

  • In our script we do this using an onTriggerEnter function,

  • which detects the ground via a tag.

  • We also detatch the crate itself from the parent object

  • and give it a rigidbody of it's own

  • so that it can interact with the environment

  • resting realistically on a slope if it lands on one.

  • Let's focus on the bomb first of all.

  • Picking up the bomb crate is handled on the

  • BombPickup script, attached to the crate.

  • We pickup the crate by destroying it and adding to

  • the count of bombs that the player has

  • in the script attached to the player called

  • LayBombs

  • The LayBombs script simply checks if

  • the player is carrying a bomb

  • and then instantiates an instance

  • of the Bomb prefab.

  • The Bomb prefab has a timed fuse

  • which waits by using an yield within the

  • BombDetonation co-routiene

  • before calling the Explode function.

  • The Explode function performs several actions.

  • First it resets the bombLaid variable

  • to allow another bomb to be deployed,

  • it tells the pickup spawner it is allowed to

  • spawn a new crate drop and kills

  • enemies within a defined blast radian.

  • Let's take a look at how this last part works.

  • Because bombs are lethal to enemies regardless of

  • their remaining hit points we use the

  • Physics.OverlapCircleAll to collect all objects

  • tagged Enemy within a certain radius of the bomb.

  • We then run a foreach loop for every enemy found

  • setting their health to 0 finding a vector from where the bomb was

  • to where the enemy is, in order to apply

  • a force in the direction of that vector.

  • Once the foreach loop is complete

  • we play and instantiate visual effects,

  • play an audio clip for the explosion

  • and of course destroy the bomb itself.

  • The visual of the explosion is twofold.

  • The main part is a simple circle that appears

  • briefly and is then destroyed

  • and the second part is a particle system of

  • stars that reuses the same sprites

  • as our rocket explosion.

  • For efficiency we keep this particle

  • system in the scene at all times

  • and when it is required we use code

  • to move the system to the desired position and play it.

  • This keeps the particle system in memory

  • and makes the game more efficient.

  • It's worth noting that we can do this

  • because we know we will only have 1

  • single explosion in the scene at any one time

  • as the player can only throw 1 bomb at a time.

  • This is why keeping our particle system in the

  • scene and replaying it is more

  • efficient than creating instances and then removing them.

  • With the rocket explosion however,

  • we can have many at once so we do

  • need to spawn and remove them.

  • Now let's take a look at what happens when our player

  • kills an enemy and scores points.

  • This is done in 2 parts,

  • a scoring animation that plays showing 100 points earned

  • and the score UI at the top of the screen

  • that increments.

  • The score animation is made up to 2 number sprites,

  • a 1 and a 0.

  • We place this in the scene under an empty parent object

  • and animated them using a simple destroyer script to

  • remove them from the scene when the animation is complete.

  • We call the destroyer function in the script

  • by placing an animation event

  • at the end of the timeline.

  • The ScoreUI itself is a simple GUI text component

  • with a custom font and script that manages

  • the score for the player.

  • The Score variable is public, meaning that we can address it

  • from the Enemy script when they are killed

  • and add 100 points to the value.

  • Speaking of the enemies, let's take a look

  • at them more in depth now.

  • In our game we have 2 types of alien enemy,

  • a green slug-like monster and a smarter

  • alien that brought his ship with him for

  • protection during the invasion.

  • These characters share the same script

  • as the behaviour is very similar

  • and we allow for differing movement speeds

  • and amounts of hit points by setting

  • these as public variables in the Inspector.

  • Each enemy has it's own Walk animation.

  • The slug has a moving tail, whist the

  • ship-based enemy rocks back and forth as it approaches.

  • For the slug we used the sprite importer

  • to define the tail section of the graphic

  • as a separate sprite element,

  • meaning that we could animate it individually

  • and avoid having to scale the entire sprite.

  • By setting the pivot to the right

  • we are able to animate the tail expanding and contracting

  • from that point.

  • For added character we then move the eyelid up and down

  • and we use the Z value to sort the sprites

  • amongst one another, the eye being below the eyelid

  • so that we could animate it over the top.

  • The second enemy's animation was much simpler

  • and just meant that we rotated it back and forth.

  • For the mechanics of moving the enemies

  • we drive them by setting the velocity of the rigidbody.

  • When they encounter an obstacle such as a wall

  • they detect this by using a Physics.OverlapPoint function,

  • which checks for a point in space overlapping a collider.

  • Our walls, the towers at each side of the level,

  • are tagged as obstacles.

  • When this function detects them it calls the Flip function,

  • it reverses the X scale of the enemy

  • sending them moving in a different direction.

  • To kill the enemies, each time a rocket collides

  • with them it's script calls the Hurt function on

  • the particular enemy that it's hit.

  • In this function we subtract 1 from the

  • hit points of the particular enemy.

  • We then keep tabs on the enemy's health

  • inside the fixed update function.

  • If it drops to 0 we call the Death function.

  • When they die we perform a number of functions.

  • Firstly we disable all sprite renderers

  • as our 2D characters are made up of a

  • number of sprite objects that are animated.

  • This is because we simply want to swap out the

  • animated elements for a single sprite

  • of the dead character

  • We do this with the main sprite renderer by

  • setting it to use the sprite assigned to

  • the deadEnemy variable.

  • We then add to the score using the public

  • variable in the Score script

  • and we add some visual flare to the enemy's death

  • by adding torque to spin them as they die.

  • Because we need the enemies to fall through the

  • environment and land in the river when they die

  • we find all colliders on the object

  • and set their IsTrigger parameter to true.

  • This means that they will pass through the

  • environment colliders.

  • We then choose from an array of death audio clips

  • and play one of them back, before creating

  • an instance of the Score animation we showed you earlier.

  • To remove the dead enemy from the scene

  • we rely on the killTrigger object

  • It performs the same function as discussed earlier

  • as any non-player object touching it

  • will cause a splash animation and remove that object.

  • The sound effect of them hitting the water is

  • an audio clip attached to the animated

  • splash which plays on awake

  • so that when we create an instance of the animated

  • object we hear the sound right away.

  • To finish the game level re decorated the

  • background with a number of moving props

  • in order to make our game environment feel more dynamic.

  • We added flying swans, plus buses and taxis that drive

  • along the river bank.

  • First was the swan, which was created from a sprite sheet,

  • drawn in Photoshop and imported using

  • the Multiple Sprite Mode import setting

  • in the Inspector.

  • By choosing this approach Unity automates choosing

  • each frame in the sheet and importing

  • it as a separate sprite under the parent

  • hierarchy of the asset.

  • Because this is a linear set of animation frames

  • we could simply drag all of these sprites in to the

  • scene to let Unity animate them for us.

  • Et voila, our animated swan is ready to add

  • as a background element.

  • The swan was then given a rigidbody2D

  • so that we can use velocity to send it

  • across the screen.

  • As with the bus and the cab, the swan is saved as a prefab.

  • For the bus and taxi prefabs we

  • simply separated the bodies and wheels of

  • the vehicles in the sprite importer

  • and made a simple bobbing animation.

  • Applying a 2d rigidbody to these as well,

  • we were able to drive them across the screen

  • using velocity.

  • For all 3 props, the bus, taxi and the swan

  • we created a script we could reuse

  • which is in charge of spawning them.

  • The BackgroundPropsSpawner script

  • also handles the frequency, a speed to give them

  • and where on screen to spawn them.

  • This meant that we could make 3 creator objects

  • with the same script on.

  • Changing which prefab will be spawned

  • and what properties to give it.

  • Take a look at the comments in the script to learn more.

  • Finally, for more background dynamism,

  • we added rolling clouds, panning river details and fog.

  • We did this by adding 2 instances of the background sprite

  • to a parent object and simply used animation to slowly

  • pan them across the screen.

  • Because this animation loops our animation will

  • continue indefinitely.

  • And that's how we made our game.

  • We hope this overview has given you some idea of

  • how we create 2D games in Unity,

  • and we'll be creating more simply projects and

  • tutorials in the future.

  • We look forward to your feedback on Unity4.3

  • and we can't wait to see the great 2D titles

  • that you'll come up with.

  • Thanks for watching.

In Unity 4.3 we're launching our first set of 2D features.

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it