You are on page 1of 49

2DGameplayTutorial

Providing2DGameplaywithUnity2

Author:GraveckInteractive
LastRevision:19FEB2008

Contents

1. Introduction
Why2DistheBee'sKnees
Prerequisites

4
6

2. SettingTheScene
Gettinginthe2DMindSet
ACloserLook
SettingtheLevelAttributes
ObjectProfile:LevelAttributes
ObjectProfile:DeathZone
SettingUpthePlatforms
ObjectProfile:Platform(Prefabs)
ObjectProfile:PreAssembledPlatform
IntroducingLerpz,OurLovelyCharacter
PlacingLerpz
DirectingtheCamera
ObjectProfile:Character(Lerpz)
LightingourScene
SpicinguptheCharacter
TheCamera
ObjectProfile:MainCamera
ContinuingourLevel
ScriptProfile:CameraTargetAttributes
HandlingRigidbodies
ObjectProfile:Crate
Exercise
MovingPlatforms
ObjectProfile:MovingPlatform
TheSpaceship
ObjectProfile:Spaceship
WellDone!

7
9
10
12
13
13
15
16
17
18
19
20
22
24
26
27
28
28
29
30
31
32
33
34
35
36

3. DelvingDeeper:ScriptingExamples
StudyingtheScripts
MovingPlatformParticleEffects

38
38

TheCameraScrollingScript
StreamlineYourWorkflow
SpaceshipScriptPart1:DefiningHelperClasses
SpaceshipScriptPart2:ControllingtheSpaceship
SpaceshipScriptPart3:SpecialEffects
Finished!
4. What'sNext?
YourTurn

40
41
43
44
47
47
48

Introduction
Sometimes2Dgameplay
callsandyoucan'tresistits
alluringcharm!Unitycan
handleit.
Thistutorialshowsthe
stepsyouneedtocreatea
basic2Dstyleplatform
game.

Why2DistheBee'sKnees
ItisnosecretthatUnitycanhelpyoucreategreatthreedimensionalgameswithease.
Itsrawpowerandflexibilityallowsevenbeginnerstocreateimpressivegameswith
outmuchdifficulty.Unityisundoubtedlyagreat3Dgameenginesowhyonearth
wouldyouwanttocreatea2Dgamewithit?
Forcertaingametypes,thatextra"D"in3Dcanbeahindrance.Somegamessimply
workbetterwithtwodimensionalgameplaymechanics.Thinkofthosesimpleandfun
2Dsidescrollinggamesyouhaveplayedinthepast,ormaybeyouhaveasimplepuz
zlegameideathatwouldworkbestconstrainedtotwodimensionsthelistkeeps
goingbutthebottomlineismanygamescanbenefitbytheuseofonlytwodimen
sions.
Twodimensionalgamesarealsocommonlyeasierforthecasualgamertounderstand,
whichissomethingtoconsiderifyou'reasmallgamedeveloper(seethearticle"Cas
ualGamesasaBusiness").
Luckily,Unityisextremelyflexibleandcaneasilyhandle2Dgameplay!Itsworldclass
AgeiaPhysXishighlyadaptableandcanbeconstrainedinmanywaysincludingtwo
dimensions.
Inthistutorialwedefinea2DGameasagamewheregraphicsarestillin3D,butre
strictedmotioncausesthephysicsandgameplayonlytooccurinasingle2Dplane.
Thisletsususe3Dmodelsforourcontentandmakeslifeeasierforartistsanddevel
opersalike.Onecouldsaythatwe'reusingthebestofbothworlds:theeaseof2D

gameplayandthebeautyof3Dgraphicswiththeaddedattractionthatexistingde
velopersalreadyhaveagood3Dassetproductionpipelineinplace.
Thistutorialwillguideyouinbuildinga2Dplatformgame.Wehavedesignedthis
tutorialwithbeginner/intermediatelevelusersinmind;weonlyaskthatyouhavea
baselineknowledgeofUnity.Wehavealsoincludedsomeadvancedconceptsthat
maybeofinteresttomoreseasonedusers.
Webeginbygettingyouintothe2Dmindset.Thenwewillwalkyouthroughbuild
inga2Dworldinwhichyourcharacterwillmovearound.Afteraddingafewcoolob
staclesandscenery,we'lllastlyaddarocketshipfortheplayertofly.
Wehopeyouenjoythistutorialasmuchaswehadfuncreatingit!

Thetutorialsdemolevelinaction.

Prerequisites
Herearethetoolsandknowledgeyoushouldhavebeforeyoubeginthistutorial:
Unity2
Althoughyoucanbenefitfromthistutorialifyou'reaUnity1.xuser,therearesome
featuresweusewithinthistutorialthatareonlyfoundinUnity2.0andabove.
BasicScripting.
Weassumethatyoualreadyhaveagraspofbasicscriptingprinciples.
FamiliaritywiththeUnityuserinterface.
YoushouldalsobefamiliarwithUnityskeyinterfaceelements,suchastheInspector,
thevariousViews,andbasicdraganddroptechniques.Ifyouareunfamiliarwith
Unity,pleasetakealookatourIntroductiontoUnityvideos.Youllfindtheseinour
websitesResourcesarea.
3DModelingTools(Recommended).
Althoughnotrequiredsincewesupplythemodels,itisrecommendedthatyouhave
toolstoexaminethe3Dassets.SuchtoolsincludeAutodeskMaya8,3DStudioMax,
Cinema4D,andCheetah3D.(NOTE:BlendercanexportFBXfiles,butcannotcurrently
importthisformat.)
2DGraphicsTools(Recommended)
Again,itisnotrequiredbutwerecommendedthatyouhavetoolstoexaminethe2D
assetswesupply.SuchtoolsmayincludeAdobePhotoshop,CorelPainter,oroneof
thebudgetalternativessuchasPixelmator.
Also,besuretodownloadtheprojectfilemeanttoaccompanythistutorial.Youll
findthefilesinourResourcessection:http://unity3d.com/support/resources/

SettingTheScene
Itstimetoprepareforour
journey.
Inthissectionwestart
puttingourscenetogether
andlookathowUnitycan
bemadetohandle2D
games.

ThissectionofthetutorialwillmostlydealwithhowtosetupGameObjectsinthe
sceneview,addingComponents,andhowtomanipulatethemintheInspector.
Weprovideyouwitharelativelyemptysceneandyourmissionistobuildontothat
scenetomakeupamorecompletelevel.Bottomlineis,weareprovidingthetools
youneedandyouneedtousethemtoconstructalevel.Lateroninthistutorialwe
delveabitdeeperandexplainhowsomeofthespecificscriptswork.

Gettinginthe2DMindSet
Nowweneedtogetinthepropermindsetandcreatesomecommonconventions
thatwillremainconsistentthroughoutourproject.Firstweneedtodefineourplane
ofmotion.Inotherwords,weneedtorestrictmotiontoonlytwoofthethreedimen
sions,traditionallynamedX,Y,andZ.Todothiswemustspecificallydecidewhichaxis
ofmotionwillhavenomovement.
TIP

WhenintheSceneViewyoucanrememberwhichcolorcorrelatestowhich
axiswiththesimplemnemonicdevice"RGB=XYZ"

TheusualconventionisfortheXaxistocorrespondtohorizontalmovementrelative
totheobserver,whiletheYaxiscorrespondstoverticalmovement.TheZaxisthere
forecorrespondstomovementstowardsandawayfromtheobserverforourpur
poses,thismeanstheZaxiscorrespondstomotiontowardsandawayfromourcam
era.
Throughoutthetutorialletskeepthefollowinginmind:

DefiningourPlaneofMotion.
WearegoingtostickwithcommonconventionandhaveourmotionbeintheXY
plane,meaningthatnomovementwilloccurintheZaxis.Verticalmovementwillbe
intheYaxisandhorizontalmovementwillbeintheXaxis.
RestrictedRotation.
Wealsoneedtorestrictourrotation.Asageneralrule,theonlyrotationthatwewill
allowisrotationaroundtheZaxis.RemembertheZaxispassesthroughthecamera;
thereforerotationaroundtheZaxiswillresultinclockwiseandcounterclockwisero
tationastheMainCameraseesit.Thereisoneexceptiontothisrestrictedrotation,
however.Thecharacterisallowedrotationabouttheyaxissohecanturnfromside
toside.

A2Dgameneedsjusttwoaxes:XandY.

Withallthisinmind,it'sfinallytimetoopenourprojectandscene.Ifyouhaven'tal
readydoneso,pleasedownloadtheprojectfilesnow.
SelectFile>OpenProjectandlocatethe2DTutorialprojectthatyouhavedown
loaded.
Onceyouhaveopenedtheproject,findthescene2DPlatformerintheProject
Paneandopenit.
PlaytheScene.

The2DPlatformerScene.

Controls
UsethecursorkeystomoveLerpz.HolddowntheCtrlkeytomakehimrunanduse
thespacebartojump.
TheGUIbuttonsatthetoptogglebetweencontrollingthecharacterandthespace
ship.Everythinginthisscenehasalreadybeenlaidoutforyou.Feelfreetoexplore
andexamineeverythingyoucan.Themorefamiliaryouarewithhowwesetupour
level,theeasieritwillbetocreateyourown.

ACloserLook
Herearetwothingsyoucaninvestigatetobetterunderstandhowtosetupa2D
gamebeforeyoudoityourself:

ObjectPositions
IfyoubringupanelementintheInspector,youllseethatallobjectsareplacedat
zerointheZaxis,keepingtotheconventionwedefinedabove.
Whenmodelingyour3Dassets,itmaymakeyourlifeeasiertomodeltheminyour
modelingapplicationwiththesameorientationasinUnity.Althoughnotcrucial,this
avoidstheinconvenienceofhavingtorotatethemafteryouimportthem.

PlatformTiling
Ifyouinvestigatetheplatformsinthissceneyou'llnoticethattheyaremadeupof
smaller,tileablepieces,withendcapsforthebeginningsandendsofplatforms.This
cansavehoursofmodelingtimesoplatformscanbebuiltwithinUnityandeasily
changed.Everythingfromthesizetothetexturesaremodeledwithtilinginmind.

NOTE Tilingwasaverycommontechniqueintheearlydaysofcomputergames.It
hadtheveryusefuladvantageofreducingtheamountofgraphicalassetsre
quired,keepingtheprojectsoverallsizedown.Inthedayswhencomputer
memorywasmeasuredinkilobytes,thiswasanimportantfactor.Today,tiling
remainsausefultechniqueasitreducesbothassetproductiontimeanddown
loadsize.

SettingtheLevelAttributes
Afterplayingourprebuiltlevel,it'stimetobeginourown.
CreateanewscenebygoingtoFile>New.Younowhaveacompletelyemptyscene
thatisreadytorock.Beforeyoubegin,makesurethatyourinterfaceissetuphow
youprefer.BesurethattheSceneView,ProjectPane,HierarchyPane,andInspector
areallpresent.
FirstthingtodoistodefineourSkybox:
GotoEdit>RenderSettingsinthemenu.IntheInspector,youshouldseean
emptyslotforaSkybox.
IntheProjectPane,expandthefolderStandardAssets>Skyboxes.
DragMartianStratosphereintotheSkyboxMaterialslotintheInspectorforthe
RenderSettings.

TheRenderSettings

Nowweshouldhaveaniftyskyboxthatwewillseeinthebackgroundatalltimesin
ourgame.

10

TheGameView,showingtheSkybox.

Next,weneedtoaddsomethingwhichwillmanagesomeimportantattributes.
LookintheProjectPaneandfindthePrefabnamedLevelAttributeswithinthe
LevelPrefabsfolder.
DragthePrefabintotheHierarchyPanesoitisloadedinyourscene.
EnsurethatitsPositionisat(0,0,0).Thiswillmakelifeeasierinthelongrunfor
thechildobject"DeathZone."

TheLevelAttributesPrefabintheSceneView.Weseetwonewobjectshere:thesmallrectanglerisingup
wardsdefinesthelevelsboundaries.ThelongoblonglyingflatistheDeathZone(displayingtheskull).

11

IntheSceneViewyoushouldnowbeabletoseeagreenrectanglethatrepresentsthe
sizeofyourlevel.Ifyoucannotseethegreenrectangle,adjustyourviewingposition
sothatyoucanclearlyseeit.
Adjustthesettingsaccordingtohowbigyouwantyourleveltobe.
Asareferencepoint,thecompletedlevelthatwesuppliedwas44.25unitswide
by60unitstall.MakesurethateverythingislocatedatzerointheZaxis.The
sizeofyourlevelcaneasilybechangedlatersodontworryaboutgettingitab
solutelyright.
Finally...
SAVEyourscene!

Sowhatsgoingonhere?LetstakeamuchcloserlookattheLevelAttributesand
DeathZoneGameObjects...

ObjectProfile:LevelAttributes
TheLevelAttributesobjectstartedasanemptyGameObjectatposition(0,0,0).The
scriptLevelAttributeshasbeenappliedtoit.

Functions
OnDrawGizmos()
Displaysthelevelsdimensions.Thelevelssizeisdenotedbythegreenborderedrec
tangledrawninthesceneview.

Start()
CreatesphysicsCollidersatstartupthatactasbordersaroundtheworldtoprevent
thecharacterfromleavingthelevelboundaries.

Script:LevelAttributes
ThisscriptdefinesthelevelskeyattributesbasedonthevaluesyousetintheInspec
tor:
Bounds
X:Thexcoordinatethatyourlevelwillstartat.
Y:Theycoordinatethatyourlevelwillstartat.
Width:ThewidthofyourlevelstartingattheXcoordinateabove.
Height:TheheightofyourlevelstartingattheYcoordinateabove.

12

FallOutBuffer:Thiscreatesabufferzoneatthebottomofyourlevel.Itspurposeis
togiveyourcharactersomeroomtofallwithoutthecamerafollowinguntilithitsthe
bottomCollider.
ColliderThickness:ThethicknessoftheCollidersthatcreateyourborders.

FurtherAnalysis
IfyouselecttheLevelAttributesGameObjectafterpressingplay,thenlookatthe
greenboundaryrectangleinthesceneview,youwillnoticeColliders(representedby
lightgreenboxes)attheedges.ThesearetheautomaticallygeneratedphysicsCollid
erscreatedbytheLevelAttributesscript.

ObjectProfile:DeathZone
TheDeathZoneobjectstartedasanemptyGameObjectatposition(0,0,0).Itisa
childobjectofLevelAttributes.ItdoesnotneedtobeachildofLevelAttributes,but
fororganizationalpurposesworkswellthere.Thescript"DeathTrigger"hasbeenap
pliedtoit.

Function
ProvidesaColliderdefinedasaTriggerwhichcausesthecharactertorespawnif
he/shefallsontoit.Thisisusefulforpitsthattheplayercanfallinto.

Script:DeathTrigger
Thisscriptdrawsthelittleskullandcrossbonesthatyouseeinthesceneviewbytak
ingadvantageofGizmoicons.Althoughit'snotnecessary,itisuseful.(SettingUp
thePlatformshasmoreinformationonGizmos.)

SettingUpthePlatforms
Nowit'stimetocreatethefoundationofourlevel:theplatforms.
IntheProjectPaneyouwillseeaprefabcalled"PreAssembledPlatform."Drag
itintotheScene.
Ensuretheplatformislocatedatzeroalongthezaxis.
Positiontheplatforminaplaceyou'rehappywith.

13

PlacingthePreAssembledPlatformPrefab.

Thisplatformwaspreassembledforyou,butyouwillhavetomaketherestyourself.
LookintheHierarchyPaneandyou'llseethatthePreAssembledPlatformhasseveral
childobjects.Thesechildrenobjectsarewhatmakeuptheplatform.Ifyouinvestigate
theplatformsyou'llnoticethattheyaremadeupofsmaller,tileablepieces,with
endcapsforthebeginningsandends:

LookinginsidethePreAssembledPlatformPrefab.

Usingtheseplatformtiles,createmoreplatformsforyourcharactertorunwild!
Keepthesepointersinmind:
Alwaysmakesurethezpositionisatzero.
Lookatthepreassembledplatformforreference.

14

Wehighlyrecommendthatyouparentgroupsofplatformtilestogether,forreasons
describedinObjectProfile:PreAssembledPlatform,below.
Todothis,createanemptyGameObjectbygoingtoGameObject>CreateEmptyand
nameitappropriately.MakesuretheGameObjectislocatedatzeroalongtheZaxis.
AlsomakesurethattheXandYcoordinatesarewhereyouwanttheplatformtobe
located.ThenyoucandragtheplatformtilesinsidetheemptyGameObjectyoujust
created.Last,applythescriptCombineChildrensoyoumimicthefunctionofthePre
AssembledPlatformGameObjectdescribedabove.
Thetilescanbepreciselypositionedeasilybecausetheirlengthsarenicewhole
numbervalues.
Theplatformsmuststayinsideofthegreenlevelboundaryyousetupintheprevious
section!Ifyourplatformsareoutsidethisareatheywillbeunreachable.Youcanal
wayschangethesizeoftheboundaries.
Savefrequently!
Youcanalwayscreatemoreplatformslater,butyouatleastwantanareathatthe
charactercanrunaround.

ObjectProfile:Platform(Prefabs)
IntheProjectPaneyoucanfindtheseprefabsinsideLevelPrefabs/Platforms.

Functions
Thesearethetileablepiecesthatmakeupthelargerplatforms.You'llfindfivedif
ferentpieceswithinthePlatformTilesfolder:
PlatformLevel:
Alevelpieceofplatformthatis6unitslong.
PlatformSlopeUp:
Apieceofplatformthatslopesupmovingfromlefttoright.Itis3unitslong.
PlatformSlopeDown:
Apieceofplatformthatslopesdownmovingfromlefttoright.Itis3unitslong.
PlatformEndCapLeft:
Thisbelongsattheleftedgeofanarrayofplatformstocapitoff.
PlatformEndCapRight:
Thisbelongsattherightedgeofanarrayofplatformstocapitoff.

15

Thelengthofthesepieces,(withtheexceptionoftheendcapssinceitisnotneces
sary,)arenicewholenumberssotheycanbepreciselytiledbyeditingthenumbersin
theInspector.

Components
BoxCollider
Withoutthis,thecharacterandspaceshipwouldfallrightthroughtheplatform!This
isneededtophysicallyinteractwiththecharacter.TheBoxCollidersizehasbeenad
justedtofittheplatformtile,otherwiseallsettingsaredefault.Sincetheplatform
doesnotmoveatall,wedonothavetoapplyaRigidbodycomponent.
Pipeline,MeshFilter,andMaterial:
Theseassignthepropermeshandtexturesoitrendersinthescene.

Script:CollisionSoundEffect
ThefootscriptattachedtoourplayerchecksGameObjectitcomesintocontactwith
forthepresenceofthisscriptandplaysthesoundeffectitholds(ifyouhavesetone).
Inthiswayourplayercharactersfootstepscanbemadetosounddifferentondiffer
entsurfacese.g.ametallicsoundonmetalplatforms;awoodenfootstepsoundon
woodensurfaces,andsoon.

Script:CollisionParticleEffect
Thisscript,liketheoneabove,providesasimilarserviceforparticleeffects.The
playersfootscriptlookstoseeifwevesetaparticleeffectGameObjectandstartsitif
so.Thisishowthecharacterraisesthecloudsofdustasherunsaroundtheexample
level.
TIP

Ifyou'recurious,examinethetexture(whichisthesameforeachtile)tosee
howitloops.

ObjectProfile:PreAssembledPlatform
It'stheparentobjectthatcontainsplatformtilesthatcreateasinglelargeplatform.

Function:
ThisGameObjectservestwopurposes.
Asacontainerusedtoorganizetheleveland
Toaidperformanceseethescriptdescribedbelow.
Itisrecommendedthatyoustructureyourentirelevelusingthismethod.Inother
words,foreachgroupofplatformtilesthatmakeupalargeplatform,createaparent
objectforthemwiththeCombineChildrenscriptapplied.

16

Script:CombineChildren
IntheInspectoryoucanseethisscriptwithitsselfexplanatoryoptions.Whatthisdoes
istakeallofthechildrenGameObjectsi.e.theplatformtilesandcombinetheir
meshessoinsteadofrendering6differentobjects,only1objectisrendered.Thisen
hancesperformance,especiallywhenyoureachalargenumberofplatforms.
TIP

ThisscriptactuallycomesintheStandardAssetspackage,whichisshipped
withUnity.

IntroducingLerpz,OurLovelyCharacter

Lerpz,ourzanycharacter,isgettinganxiousforaction!
Letsgetourspawnpointsetupfirst.Thespawnpointiswherethecharacterwillap
pearwhenyoustartthegame.It'sprettysimpletodo,justfollowthesesteps:
CreateanewemptyGameObjectbygoingtoGameObject>CreateEmpty.Re
nameittoCharacterSpawnPoint.

17

ApplythescripttitledSpawnPointtotheGameObjectyoujustcreated.This
scriptcreatesthatlittle2DiconofLerpzinsidetheSceneViewsoyoucansee
wherethespawnpointis.(ThislittledrawingiscalledaGizmo.TheDeathZone
alsohasoneofthesetodisplaytheskullandcrossbonesicon.)
PositionthespawnpointwhereyouwantLerpztoappear.Makesureitisatz=
0withaplatformunderfoot,soheactuallyhasaplacetostandwhenheap
pears.

WhatexactlyisaGizmo?
Gizmosareshapes,iconsandothervisualaidsthatappearintheSceneViewsuchas
lines,lamps,cameras,andaudiosourcestoassistinvisualdebuggingorlayout.Giz
mosdrawnexclusivelyinthis2DtutorialaretheDeathZone,andCharacterSpawn
Point.
Allittakesisaverysimplescript.Here'sanexampleofthescriptSpawnPointthatis
appliedtotheCharacterSpawnPoint:

function OnDrawGizmos()
{
Gizmos.DrawIcon(transform.position, "Player Icon.tif");
}

GizmoiconsmustbeplacedintheAssets/Gizmosfolder.
TheLevelAttributesscriptalsotakesadvantageofGizmos:Thegreenborderyousee
representingthelevelboundariesisaGizmo.ForacompletereferenceonGizmos,you
canrefertothedocumentation
(http://unity3d.com/Documentation/ScriptReference/Gizmos.html).

PlacingLerpz
ThenextstepistoaddLerpzhimselftoourScene:
DragthePrefab"Character(Lerpz)"inourLevelPrefabsdirectoryintothe
Scene.Sincewehaveaspawnpointsetup,youcanplacehimanywhereyou'd
like,justaslongashe'ssomewhereintheScene.
Ifitsnotalreadyvisible,bringupourCharacterintheInspectorandopenup
thePlatformControllerScriptComponent.NotetheSpawnPointslot:

18

Character(Lerpz)withnoSpawnPointset.

DragourearlierCharacterSpawnPointobjectintothisslot,soitlookslikethis:

Character(Lerpz)withtheSpawnPointset.

ThenextstepistogettheMainCameratofollowLerpzaround...

DirectingtheCamera
Atthemoment,ourmaincamerawillsimplysitwhereitisandpointatwhateverits
aimedat.MuchlikeinamovieorTVproduction,weneedtodirectthecameratell
ithowtomove,whentodosoandwhatitshouldbeaimedat.Weachievethiswith
twoscripts:
DroptheCameraScrollingscript(fromScripts>2D>Camera)ontotheMain
CameraGameObject.
DroptheCameraFocusscript(fromthesamelocation)ontotheMainCamera.
Thenextstepistogivethescriptstheinformationtheyneedtowork:
SelecttheMainCameraintheHierarchyPaneandopenuptheCameraFocus
scriptComponentintheInspector.
OpentheTargetsgroupandchangeSizeto1.Element0shouldappearbelowit.
DragourCharacter(Lerpz)GameObjectontotheElement0slot.
OpentheTargetButtonNamesgroupandchangeSizeto1.(Again,Element0
shouldappear.)
TypePlayerintoElement0sslot.

19

Theresultshouldlookliketheimagebelow:

SettinguptheCameraFocusscriptcomponent.

Weshouldnowhaveaworkingcameraandcharacterrunningandjumpingoverour
platforms.
ItwasveryeasytogetthecharacterinthelevelusingPrefabs,butoncloserinspection
Lerpzisanythingbutsimple:

ObjectProfile:Character(Lerpz)
Lerpzisthemaincharacterofourgame.Hecanwalk,run,jump,andfall.Hemoves
aroundourlevelwreakinghavocwhereverhegoes.

Components
Animation
Thiscomponentstoresalistofanimationsforthecharacterthatcanbeaccessedby
scripting.PlatformPlayerAnimation(listedbelow)makesuseofthiscomponentbyac
cessingdifferentanimations.
CharacterController
Thetraditionalsidescrollingcharactercontrolsaregenerallynotphysicallyrealistic.
Thecharactercomestoahaltimmediatelyandturnsonadime,makingitdifficultand
impracticaltouseRigidbodyphysics.Asaresult,weuseanalternatemethodtomove
thecharacteraroundbyusingtheCharacterController.Seemoredetailonthiscom
ponentinthedocumentation.
(http://unity3d.com/Documentation/Components/classCharacterController.html)

ScriptApplied:PlatformerController
Thisscriptisacustomscriptmadeforthis2Dtutorial.Thisscript,incooperationwith
theCharacterControllercomponent,isusedtodefineitsphysicalmechanicswithinour
world.Mostoftheadjustablesettingsareselfexplanatoryandwewillnotgointo
muchdetail,butafewrequiresomefurtherdiscussion:

20

SpeedSmoothing
Howquicklydoesthecharacterchangespeeds?Forexample,howquicklycanthe
charactergofromnotmovingtorunning.Highermeansfaster.
RotationSmoothing
Howfastthecharactervisuallychangesdirections.Itdoesnotaffectthemotion.
CanControl
Thissimplystateswhethertheplayercancontrolthecharacter.Thiscanbeturnedoff
byanotherscriptifatanytimeyouwantusertoloseorgaincharactercontrol.Anex
ampleofthisbeingtogglediswhenyoutogglebetweenthespaceshipandtheplayer.
SpawnPoint
YoumustdefinethespawnpointbydraggingaTransformobjectintotheslot.Then
thecharacterwillspawnatthatpoint.

Script:PlatformerPlayerAnimation
ThisscripttakestheanimationslistedintheAnimationComponentandplaysthemat
theappropriatetimes.Forexampleitdetectswhenaplayerisonthegroundand
movingatacertainspeed,andthenplaystheappropriateanimationsuchas"run."

Script:PlatformerPushBodies
SincethecharacterisnotaRigidbody,itdoesnotautomaticallyphysicallyinteract
witheverythingaroundit.ThisscriptallowsthecharactertoapplyforcestoRigidbod
iessuchasthecrateswithinthelevel.
ThesettingPushPoweristhestrengthofthepushappliedbythecharacter.
ThePushLayerssettingdetermineswhatlayersthecharactercanactuallypush.Some
times,youmaynotwantaspecificRigidbodytobepushedbythecharacterbutstill
interactphysicallywiththeworldaroundit,soyoucancreatealayerforthatobject
makesurethatthecharactercannotpushthatlayerwiththissetting.

Script:CameraTargetAttribute
Thisdefinessomecamerabehaviors,andisalsoappliedtotheSpaceship.Thisscriptis
morethoroughlydiscussedinthenextsection.

FurtherAnalysis
Wehavejustscratchedthesurfaceofexplainingthecharacter.Tofullybenefityou,it
wouldbewisetoexamineandexperimentwithallofthescriptsattachedtothechar
actertoseehowtheywork.Wehavesuppliedcommentsinthecodetohelpguide
youalong.
TakeafewmomentstoplayaroundwithLerpz'ssettings.Adjustthedifferentsettings
toseewhattheydo,andifthingsgettoocrazyyoucanalwaysdeletehimfromthe
sceneandaddanewoneusingthePrefab!

21

LightingourScene
AtthisstagewehaveourcharacterrunningaroundourScene,butitsallverydark.
Weneedsomelightstomakeeverythingeasierontheeye!
WelladdtwoDirectionalLights:
CreateanEmptyGameObject.NameitMainLights.(Wellusethistoorganize
ourlightsandkeeptheminoneplace.)
CreateaDirectionalLight.(GameObject>CreateOther>DirectionalLight).
RenameitDownlight.
DragthelightintoourMainLightsobject.
RotateourDownlightobjecttopointabout60degreesdownwards.
Setitasshownbelow(Intensityisalsochangedfromthedefault,to0.5):

Color
Light

Red

Green

184

233

Blue Opacity
255

100

Thelightbluedownlightssettings.

Nowwellrepeattheprocessagain,butforouruplighter.Thiswilllighttheunder
sidesoftheplatforms:
CreateaDirectionalLight.(GameObject>CreateOther>DirectionalLight).
RenameitUplight.
DragthelightintoourMainLightsobject.
RotateourUplighttopointabout60degreesupwards.
Setitasshownbelow(Intensityisagainchangedfromthedefault,to0.5):

22

Color
Light

Red

Green

238

71

Blue Opacity
255

100

Thepurpleuplightssettings.

Thenextstepispurelyforourownconvenience:
SelectourMainLightsparentobjectanddragitbackwards,awayfromtheplat
forms(seescreenshotbelow).Precisionisntimportanthere:thisisjusttokeep
thelightsoutofthewaywhileweworkastheyreDirectionalLights,their
distancefromtheplatformshasnoeffect.
Ourcompletedlightingrigshouldlooksomethinglikethis,(althoughyourlevels
platformswillprobablybeverydifferent):

Ourlights,positionedawayfromourCameraandlevel,sowecanseethemmoreclearly.TheMainLights
objectishighlightedhere,showingboththechildlights.

TIP

Thelightcolorschoseninthisexamplearehardlysubtle,buttheyclearlyshow
howeachlightaffectsthescenery.Feelfreetochangethecolors!

23

SpicinguptheCharacter
Lerpzhasacoupleofsimplevisualtouches:aworkingjetpackanddustcloudskicked
upwhenhewalks.Letslookattheseinmoredetail:

JetPackParticleEffects
Ifyouwatchthecharacter'sjetpackitonlyfireswhenhejumpsandismovingup
wards.Additionalscriptingisneededtoaccomplishthis.Wealsoneedtomakesome
particleeffects.
IntheHierarchyPane,expandtheCharacter,thenexpandrootJointandlastly
expandtorso.HereyouwillseewheretheRocketJetGameObjectsarelocated.
ThecodetostartthejetsisinsidethePlatformerControllerscriptwithintheUp-

date()function.
TIP

UnitysParticleSystemfeaturesarecoveredindepthinourResourcesarea.
CheckoutForestYoggyJohnsonsvideoonthesubject,aswellasour3D
PlatformerTutorial.

Footstepsinthedust
AsLerpzwalks,wehearhisfootstepsandseehimkickingupplentyofdust.(Clearly
itsbeensometimesincetheseplatformsweregivenagoodclean!)
IfyouexpandthemanylevelsofLerpz'slegsintheHierarchyPane,you'llnoticethat
eachfoothasaFootEffectGameObjectattachedtoit.ThiscontainsthreeComponents
andascript:
RigidBody
ThiscomponentisrequiredifwewantUnitytodetectcollisions.
AudioSource
Essentiallyaplaceholderforafootstepsound.Whenourscriptdetectsthatourfoot
hasstruckanotherobject,itchecksifthatobjecthasaCollisionSoundEffectscript.Ifit
does,itgrabsthatsoundeffect,dropsitintothisAudioSourcecomponentandplays
it,addingasubtle,randomvariationtothepitcheachtimeforvariety.
SphereCollider
Unitysphysicsengineusesthistodeterminewhenthefoothastouchedsomething.
Thisissetasatrigger.WhenthisCollidertouchesthecolliderinaplatformobject,the
footscriptreactsaccordinglybyscanningtheobjectwevestruckforCollisionSoun
dEffect(seeabove)andCollisionParticleEffectscripts,playingtherelevanteffectsac
cordingly.
Thefootscriptdoesnothingotherthanthetasksmentionedaboveandistherefore
veryshortandsimple:

24

var baseFootAudioVolume = 1.0;


var soundEffectPitchRandomness = 0.05;

Thesetwovariablesdefinethevolumeofthefootstepsoundeffect,aswellashow
muchvariationisappliedtoitspitch.(Thisvariationisusedtopreventthefootstep
soundingtooartificial.)
ThefirstfunctionwedefineisOnTriggerEnter().Thisiscalledwheneverthe
SphereCollidertouchesanotherCollider,suchasthatattachedtoaplatformelement:

function OnTriggerEnter (other : Collider) {


var collisionParticleEffect : CollisionParticleEffect =
other.GetComponent(CollisionParticleEffect);
if (collisionParticleEffect) {
Instantiate(collisionParticleEffect.effect, transform.position, transform.rotation);
}

TheabovecodelooksforaCollisionParticleEffectscriptintheobjectwevecollided
with.Ifitfindsone,itfetchestheparticlesystemPrefabwevestoredinthereandin
stantiatesitatthefootsposition.Thisishowweproducethelittlecloudsofdust.
Thenextsectionofcodedoessomethingverysimilarforthefootstepsoundeffect:

var collisionSoundEffect : CollisionSoundEffect =


other.GetComponent(CollisionSoundEffect);
if (collisionSoundEffect) {
audio.clip = collisionSoundEffect.audioClip;
audio.volume = collisionSoundEffect.volumeModifier * baseFootAudioVolume;
audio.pitch = Random.Range(1.0 - soundEffectPitchRandomness, 1.0 +
soundEffectPitchRandomness);
audio.Play();
}
}

Thiscodelooksforafootstepsampleintheobjectwevecollidedwith.Ifitfindsone,
itgrabsit,copiesitintotheFootEffectGameObjectsownAudioSourcecomponent,
addsabitofrandomvariationtoitspitch,thenplaysit.
TheonlyotherfunctioninthisscriptisReset(),whichsimplyensurestwokeyprop
ertiesaresettothecorrectdefaultvalues.Thisfunctioniscalledautomaticallyby

25

UnitywhenthescriptisfirstaddedtoaGameObject,anditcanalsobecalledmanu
allybyclickingonthecogwheelicontotherightofthescriptcomponentsnamein
theInspector.

function Reset() {
rigidbody.isKinematic = true;
collider.isTrigger = true;
}
@script RequireComponent(AudioSource, SphereCollider, Rigidbody)

TheverylastlineinthecodeisaUnitydirectivewhichensuresthethreecomponents
listedarepresentinourGameObject.Thissaveshavingtoremembertoaddthem
manually.

TheCamera
ItsnowtimetolookatoperatingtheCamera.Weneedittofollowourplayeraround
thelevel.
SavethesceneyouhavebuiltsofarandreopentheScenenamed2DPlatformer
thatcamepremadewiththistutorial.
PlaytheSceneforamomentandobservethecameramovement.
Youshouldseethatnotonlydoesthecamerafollowthecharacter,butthecharacter's
positionshiftsashewalksfurtherinasingledirection.Thissubtlemovementallows
theplayertomoreeasilyviewwhat'sahead.Thisisatechniquewhichcanbeseenin
gamesasoldasWilliamsclassicarcadegame,Defender.
Inadditiontothisbasicmovement,wealsoaddeda"Springiness"propertytoour
camerasscript:Whenthecharacterjumps,itispreferablenottohavethecamerafol
lowtheentirejumpingmotionbecauseitmakesforsomejerkycameramovement.To
solvethisproblem,weprovideasettingthatallowsthecameratolagalittlesoit
doesn'tfolloweverysinglemotion.
Thethirdandfinalpointtonoteisthecamerasbehaviorattheboundariesofthe
world.Noticehowthecameradoesnotmovepasttheboundaries.
Havingawellplacedcameraisalmostalwaysdifficultnomatterwhattypeofgame
youaremaking,andthereforecanoftengetcomplicated.Thecameramotionwe
provideinthistutorialmaynotbeperfectineveryway,butitisagoodplacetostart.

26

ObjectProfile:MainCamera
ThisprovidestheplayersviewofourSceneandisanimportantpartofourgame.

Components
Camera
ThisisthecorecomponentforaUnitycamera.Itisacomplexcomponentwhichrelies
onthefollowingComponents,(whichUnitywillnormallyaddautomatically):
GUILayer
Thisallows2DGUIstoberendered.
FlareLayer
Thisallowslensflareeffectstoberendered.Thesearebeyondthescopeofthistu
torial.
AudioListener
Thisisbasicallyamicrophoneattachedtothecamera.Traditionally,themicrophone
isattachedtothecamerabecauseitallowsformorerealisticstereosoundasitrep
resentstheplayerspointofview.Withoutthiscomponent,wewouldnothearany
audiowhileplayingourgame.

Script:CameraScrolling
Thisisthescriptthatmakesthecameramovehowwewant.Thereisn'tmuchtoad
justhereexceptfor:
Distance
Thisisthedistanceinthezdirectionthatthecameraisfromthetargetobject.
Springiness
Aswestatedearlier,whenthecharacterjumpsitispreferablenottohavethecamera
followtheentirejumpingmotionbecauseitmakesforjerkymotion.Thissettingde
fineshowresponsiveourcamerawillbetothetarget'smotion.

Script:CameraFocus
Thisscriptallowsustoeasilyswitchbetweendifferenttargetsforthecamera.Inour
case,thetargetswillbeLerpzandtheSpaceship.
NOTE ThisscriptalsotakesadvantageofthenewGUIfeaturesinUnity2.0.Inthe
premadescenewehavesetupforyou,thisscriptiswhatallowsyoutotoggle
betweentheLerpzandtheSpaceship.
Letstakealookattheadjustablesettings:
Targets
Youcansetasmanytargetsasyoulike.Ourpreassembledscenehastwo.Youneed
todragaTransformobjectfromtheHierarchyintotheslot.

27

TargetButtonNames
Thisshouldhaveasmanynamesastherearetargets.Thesearethenamesthatappear
onthebuttonsoftheGUIdisplaypanel.

FurtherAnalysis
Wewilltakeacloserlookatthecamerascriptsinthenextsectionofthistutorial.

ContinuingourLevel
Nowthatwehaveanideawhatcomponentsandscriptsweneed,itstimetogetthe
cameraworkinginournewScene...
Reopenyourscene,ifitsnotalreadyopen.
ExperimentwiththeSpringinessandDistancesettingsintheCameraScrolling
script.Setthemaccordingtoyourpreference.
Thereisanothercamerarelatedscriptwhichisnotappliedtothecameraitself.We
needtoexaminethistoo.ItistheCameraTargetAttributesscript.
ThisscriptisappliedtotheCharacter,andlaterwillbeappliedtotheSpaceship.

ScriptProfile:CameraTargetAttributes
Providesafewadditionalcameramovementpropertiesthataren'tappliedontothe
cameraitself.

AppliedTo:

Character(Lerpz)andSpaceship

KeyProperties
HeightOffset
Whenat0,thetargetwillbesittingverticallyinthecenterofthescreen.Ifitissetto
apositivenumber,thatmeansthecamerawillshiftupwards,resultinginavertically
offcentertarget.
DistanceModifier
ThedistanceofthecamerafromthetargetisdefinedintheCameraScrollingscript,
butthissettingaddsontothatvalue.Inthepreassembledscenetherockethasa
higherdistancemodifier,sothecamerapullsbackalittlewhenyouchoosetocontrol
it.
VelocityLookAhead
Thisdefineshowquicklythecamerashiftsto"lookahead"whenacharacterismov
ing.

28

MaxLookAhead
Thisdistanceiswherethe"lookingahead"willstopsothecharacterdoesn'tleavethe
screen.Xrepresentsthehorizontaldistance,Yrepresentstheverticaldistance.
Beforeyoumoveon,playaroundwiththeLerpz'sCameraTargetAttributesset
tingstounderstandwhatthisscriptdoes.

OrthographicProjection
Eventhoughweareworkingwith2Dmechanics,thegraphicsarestill3Dandevery
thingstillhasabitofperspectivetoit.Foryoutraditionalistsoutthere,justfollow
thesestepssoit'sstrictlysidevieworthographicwithnoperspective:
IntheHierarchy,selectyourMainCamera,andchecktheboxintheInspector
thatsays"Isorthographic."
IntheGameViewyoushouldseeastrictorthographicviewofyourlevelwithoutper
spective.Butthere'saproblemnow,theSkyboxhasdisappearedbecauseitdoesn't
workfororthographicviews.Noneedtoworry,afewquickadjustmentsandwe're
backinbusiness!
AdjustasettingoftheMainCameraintheInspector.Bydefault,thesetting
ClearFlagsissettoSkyboxbutwewantittobesettoDepthOnly.
Nowweneedtoaddanewcameratorenderthebackdrop.
GotoGameObject>CreateOther>Camera.
ThisnewcamerawillbesettoonlyrendertheSkyboxandnothingelse.
ChangetheDepthsettingto"2",whichsetsittorenderbeforetheMainCam
eraandthereforewillappearinthebackground.
NowtheCullingMasksettingneedstobechangedtoNothing,otherwiseyour
levelmayberenderedmorethanonce.
YoucanalsoadjusttheFieldofViewsothatyoucanseeasmuchoraslittleof
theskyboxasyoudesire.
Nowyouhaveasidescrollerthathasamoretraditionalfeelwithoutperspective!

HandlingRigidbodies
Rigidbodiesarethegatewayforapplyingphysicstoyourobjects.(Ifyouareunfamil
iarwiththeconceptofaRigidbody,pleaseviewthedocumentation.)
OurjobistotelltheRigidbodieshowtobehaveinthisrestrictive2Dplaneofmotion.
TheplatformswillnevermovesotheRigidbodycomponentisnotnecessary,butthe

29

rocketshipandthecratesneedtomoveandphysicallyinteractwiththeirsurround
ings.ThissectionexplainshowtorestrictmotionoftheseRigidbodies.
IfyouweretoexamineboththecrateandtherocketintheInspectorViewofourpre
assembledscene,youwouldnoticetwomajorthingsthatarespecifictoour2Dgame:
Theyarebothlocatedat0alongtheZaxis.Thisisimportantbecauseeveryobject
needstobeatthesameplacealongtheZaxis.
Theyalsohaveacomponentcalled"ConfigurableJoint."Thisisanewcomponentin
Unity2.0whichofferscountlesspossibilities,butforourpurposesitisusedforrestrict
ingmotion.
NoticethatZMotionislocked,whichdisallowsmotionintheZaxis.AngularXMotion
andAngularYMotionarealsolocked,preventinganyforbiddenrotationsconforming
withwhatwedecidedinthepreviouschapter.TheConfigureInWorldSpacecheck
boxisalsoselected.Allothersettingsareleftattheirdefaultvalues.
Letstakeacloserlookatthecrate.(TheSpaceshiphasadditionalcomponentsadded,
andwewilllookatthatlater.)

ObjectProfile:Crate
IntheProjectPaneyoucanfindthisprefabinsideofthedirectoryLevelPrefabs.The
crateisnotmeanttobestationary,butratherinteractwiththecharacterandthe
worldaroundit.

Components
BoxCollider
WithouttheBoxCollider,theobjectwouldnotbeabletophysicallyinteractwithits
environment.Allofthesettingsherearethedefaultsettings.
Rigidbody
Thisalsoallowsthecratetophysicallyinteractwithitsenvironment.Thesettingshere
arealsothedefaultvalues,butyoucanadjustthemtomakeitmoremassive,toig
noregravity,ortobeimmovable.
ConfigurableJoint
Thisisthecomponentthatrestrictsourmovementtoour2Dplane.Allsettingsare
defaultexceptforthefollowingfour:
ZMotion:Locked
AngularXMotion:Locked

30

AngularYMotion:Locked
ConfigureinWorldSpace:Checked
Pipeline,MeshFilter,andMaterial
Theseassignthepropermeshandtexturesoitrendersinthescene.

Script:CollisionSoundEffect
Thisscriptassignsasoundforwhenanobjectcollideswithit.Thecollidingobject
mustactivatethesoundthroughscripting.

Thehumblecrate.Soversatile!Soeasytomodel!Wherewouldthegamesindustrybewithoutthem?

Exercise
Addasmanycratestoyoursceneasyouwant.Youcanorientthemhowever
youwantaslongasthey'relocatedatzeroalongthezaxis.
Afteryouhaveaddedcrates,stepitupbycreatingyourownRigidbodytobe
loadedinthescene.
Trycreatingaspherethatthecharactercanrollwhenitispushed.Applythe
samecomponentsandsettingstothesphere,butmakesureyouaddaSphere
ColliderinsteadofaBoxCollider.
Don'tforgettosaveyourscene!

31

MovingPlatforms
Acommoningredientinasidescrolling2Dgameisamovingplatform.Tocreatea
movingplatformweregoingtopositiontwowaypointsintheScenethatthemoving
platformwilloscillatebetween.
DroptheMovingPlatformPrefabintoyourscene.
DropaPlatformWayPointPrefabintoyoursceneandpositionitwhereyou
wanttheMovingPlatformtostartfrom.
DuplicatethePlatformWayPointandpositionitwhereyouwanttheMoving
Platformtomoveto.
IntheMovingPlatformsInspectorthereisascriptnamedPlatformMoverwith
twoslots,TargetAandTargetB.DropyourtwoPlatformWayPointGameOb
jectsfromtheHierarchyintotheirrespectiveslotsintheInspector.
ThereisalsoasettingforSpeedwhichcontrolshowfasttheMovingPlatform
willmovebetweenthetwoPlatformWayPoints.
Nowifyouhitplay,theplatformshouldbemovinghowyou'dexpect.Ifitisn'tbehav
ingcorrectly,adjustyourtwoPlatformWayPointsandtheSpeedvariableuntilyou
achievethedesiredresult.
TIP

Youcanaddasmanymovingplatformsasyou'dlike.Eachmovingplatform
shouldhaveitsownsetoftwoPlatformWayPointstomovebetween.

32

ObjectProfile:MovingPlatform
Description:Themovingplatformthatthecharactercanstandon.Themovingplat
forminthepreassembled2DTutorialscenemovesvertically,buttheycanbemadeto
movewhicheverdirectionyoudesire.

Components
BoxCollider
WithouttheBoxCollider,thecharacterandotherobjectswouldfallrightthroughit!
Rigidbody
Thisalsoallowsthecratetophysicallyinteractwiththecharacterandotherobjects.A
fewsettingsdeviatefromthedefault."UseGravity"settingisoff.The"IsKinematic"
settingison.The"IsKinematic"settingpreventsthecharacterorotherRigidbodies
frommovingtheplatformsomewherebesidesitspredefinedpath.
ConfigurableJoint
LiketheRigidbodiesdescribedintheprevioussection,thiscomponentrestrictsour
movement.EverythingisthesameexceptnowALLrotationisforbidden:
ZMotion:Locked
AngularXMotion:Locked
AngularYMotion:Locked
AngularZMotion:Locked
ConfigureinWorldSpace:Checked

33

Pipeline,MeshFilter,andMaterial
Theseassignthepropermeshandtexturesoitrendersinthescene.

Script:MovingPlatformEffects
Thisscriptisusedtoactivatetheparticleeffectsonthebottomoftheplatform.The
HorizontalSpeedtoEnableEmitterspropertydefineshowfasttheplatformneedsto
movehorizontallyforthejetstofire.Itautomaticallyfiresforanyverticalmovement.
Welltakeamoreindepthlookatthisscriptlater.

TheSpaceship
Bynowyoushouldhavealmosteverythingsetup.Lerpz,thecharacter,shouldbe
movingaroundandnavigatingovercratesandmovableplatforms.Thelastthingyou
havetosetupistheSpaceship.Addingaspaceshipinthistutorialwillshowyouhow
toaddforcestoaRigidbodyandmakeitmove.
ThereareonlytwothingsyouneedtodotogettheSpaceshipfullyfunctional:
FirstdragtheSpaceshipPrefabintotheScene.
Positionitwhereyouwantinyourlevel.
NowweneedtoadjustafewsettingsintheMainCamerasothatthecamerawill
switchbetweentheSpaceshipandLerpz.It'stimetorevisittheCameraFocusscript:
ChangethenumberofTargetsto2withElement0asCharacter(Lerpz)and
Element1asSpaceship.Thiseasilyachievedbydraggingtherespective
GameObjectsontotheElementslots.
YoualsoneedtochangethesizeofTargetButtonNamesto2,withElements0
and1namedPlayerandSpaceshiprespectively.Youcanseethefinalsettingsin
thefollowingscreenshot.
Nowyou'regoodtogo!

34

TheupdatedCameraFocusscriptsettings.

Youshouldbynowhaveacompleteandworkinglevel!Ifanythingisn'tworking
properly,readbackandseeifyoumissedanything.Alsorememberthatyoucanal
waysopenthescene2DTutorialandusethatasareference.
Don'tforgettosave!

ObjectProfile:Spaceship
TheSpaceshipprefabcanbefoundinthedirectorLevelPrefabs.It'stheSpaceshipyou
flyaroundthelevelwith.

Components
MeshCollider
Allowstheobjecttophysicallyinteractwithitssurroundings.ItisimportantthatCon
vexischecked.AconvexMeshColliderisabletomoveinrealtime,otherwiseitistoo
computationallyexpensivetorun.ToseethedefinitionofaConvexMesh,youcan
viewthedocumentation
(http://unity3d.com/Documentation/Components/classMeshCollider.html).
Rigidbody
ThisalsoallowstheSpaceshiptophysicallyinteractwithitsenvironment.Thesettings
usedarethedefaultsettingswhenyouapplyaRigidbodytoanobject.
ConfigurableJoint
ThestandardsettingsthatweapplytootherRigidbodiesinthesceneasseenonour
crate:
ZMotion:Locked

35

AngularXMotion:Locked
AngularYMotion:Locked
ConfigureinWorldSpace:Checked
Pipeline,MeshFilter,MeshRenderer,andMaterial:Theseassignthepropermeshand
texturesoitrendersinthescene.

Script:Spaceship
SofartheSpaceshipisnotmuchdifferentfromthecrate,butthisscriptiswhatsetsit
apartfromaninanimatephysicsobject.
TheSpaceshipscriptdefineshowitmoveswiththeinputfromthekeyboard.Thead
justablesettingsonthescriptare:
ForwardDirection
PositionalMovement
RotationalMovement.
ForbothPositionalandRotationalMovement,you'llseethatthereisamaxspeed
and,bydefault,ifthatspeedisexceededthedragdrasticallyincreases,makingit
muchmoredifficulttoaccelerate.
ThesettingCanControlistoggledwiththecamerascriptCameraFocus,soyouneed
notworryaboutthatsetting.

WellDone!
Congratulations!Youarefinishedwithbuildingyour2Dlevel.Thiswasnoeasytask
throughoutthetutorialsofaryouhavebeenintroducedtoahandfuloffundamental
concepts...andsomemoreadvancedconcepts.Here'swhatyoushouldhaveaccom
plishedsofar:
Learnedhowtorestrictmovementtoa2Dplane;
Builtyourlevelwithtileableplatforms;
Setyourlevelboundaries;
BeenintroducedtoGizmos;
ExploredthefundamentalsofsettingupaCharacter;
Exploredthecomplexitiesofsettingupyourcamera;

36

Seenhowtomakeastrictorthographiccameraview;
LearnedhowtoplaceandmakeRigidbodies;
Usedwaypointsystemtocreatemovingplatforms;
SetuptheSpaceship.

Takeamomentforadeepbreathandenjoyplayingyourlevel.Then,ifyou'reambi
tiousyoucandiveintothenextchapter.

37

DelvingDeeper:ScriptingExamples
Nowwevelearnedhow
theprojectisorganized
andhowtousethetools
provided,itstimetopeer
underthehoodandsee
howthesetoolswork.

StudyingtheScripts
Therearealotofscriptswithinthisproject,andwewillonlycoverafewofthemore
importantones.Fortheoneswedonotcoverinthetutorialtext,youwillseethatthe
scriptsarethoroughlycommentedsoyoucanwalkthroughthembyyourself.These
scriptscoverbothbasicandadvancedconcepts,sowhetheryou'renewtoUnityora
seasoneduseryouwillbenefitfromreadingthem.

MovingPlatformParticleEffects
Ifyouwatchthemovingplatform,you'llnoticethattheparticleeffectonlyoccurs
whenitismovingupwards.ThiseffectwasaccomplishedwiththescriptMovingPlat
formEffects.
Inanutshell,thisscriptcomparesthepreviouspositionwiththecurrentpositionand
ifit'smovingupwardstheparticleemittersturnon.NotetheusageoftheLateUp-

date()functioninsteadofUpdate()thisistostoptheparticleemitterfromre
actingoneframelate.
// We will turn on our special effects when the platform is raising, but if it is moving side
// to side, how fast does it have to be moving to cause our special effects to turn on?
var horizontalSpeedToEnableEmitters = 1.0;
// A true/false (boolean) variable to keep track of whether or not our special effects are
// currently turned on.
private var areEmittersOn : boolean;

38

// A reference to our other Moving Platform script that is handling all our movement.
// We'll need it to query the current platform velocity for our special effects.
private var movingPlatform : MovingPlatform;
// We are going to use these later to calculate the current velocity.
private var oldPosition : Vector3;
private var currentVelocity : Vector3;
function Start() {
// Grabs the initial position of the platform.
oldPosition = transform.position;
}
function Update() {
// Remember if our emitters were on, then we'll see if they are currently on.
wereEmittersOn = areEmittersOn;
// The emitters are on if the vertical (y) velocity is greater than 0 (positive), or if the
// horizontal velocity in either direction (positive or negative speed) is greater than
// our horizontalSpeedToEnableEmitters threshold.
areEmittersOn = (currentVelocity.y > 0) || (Mathf.Abs(currentVelocity.x) >
horizontalSpeedToEnableEmitters);
// We only have to update the particle emitters if the state of them has changed.
// This saves needless computation.
if (wereEmittersOn != areEmittersOn) {
// Get every child ParticleEmitter in the moving platform.
for (var emitter in GetComponentsInChildren(ParticleEmitter)) {
//Simply set them to emit or not emit depending on the value of
areEmittersOn
emitter.emit = areEmittersOn;
}
}
}

function LateUpdate () {
currentVelocity = transform.position - oldPosition;
oldPosition = transform.position;
}
// This line tells Unity to nicely place this script in a submenu of the Component menu.
@script AddComponentMenu("2D Platformer/Moving Platform/Moving Platform Effects")

39

TheCameraScrollingScript
Nowletsexaminehowwegetthecameratofollowthecharacter.Toaccomplishthis
weusescripting.Asimpleyetfunctionalcamerascriptcouldbeappliedtothemain
camera,readthecharacter'sXandYcoordinates,andusethosevaluesforitsownpo
sitionwhilekeepingacertaindistanceawayintheZaxis.Thisworksperfectlywell,
butifyoucloselyexaminepopularsidescrollinggamesyou'llnoticethatit'snever
quitethatsimple:thereareahandfulofsubtletouchestobemadeinordertoget
effectivecamerascrolling.
AllofthismovementisdefinedinCameraScrollingfoundinScripts>2D>Camera.
Openthescriptandexamineit.Usethecommentswesuppliedtounderstandhowit
works.Herewewillbrieflydescribewhateachfunctiondoes:

SetTarget()
Lookatthetopofthescriptandyou'llnoticeaprivatevariablecalledtarget.The
SetTarget()functionisusedbyotherscriptstochangetheprivatevariabletarget.
Morespecifically,theCameraFocusscriptusesthisfunctionwhenyouclickonthebut
tonsatthetopofthescreentochoosewhethertocontrolLerpzorhisspaceship.
Whynotallowsettingofthevariabledirectly?Simple:thiswaywecanensurethatthe
variableisalwayssetbycallingourSetTarget()functions,makingiteasierto
checkthatthevalueweresettingittoisavalidoneforourpurposes.
NotealsothatwedefinetheSetTarget()functionmorethanonce.Eachdefinition
acceptsadifferentnumberofarguments(otherwiseUnitywillcomplain).Wecanuse
thesemultipledefinitionsasaneasywaytodefaultthesecondargumenttoFALSE
andalsotomakeourscriptseasiertofollow.(Thisprogrammingtechniqueismost
commonlyreferredtoasOverloading.)

GetTarget()
Thisisasimpleaccessorfunction,(sometimescalleda"getter").Itisapubliclycallable
functionthatreturnsaprivatevariable.Noticehowtarget,definedatthetopofthe
script,ismarked"private"?Wecannotaccessitdirectlyfromanotherscript,butan
otherscriptcanaccessthisfunction.
Functionslikethisenforceaconceptcalledencapsulation.InUnity,thismeansour
scriptiscompletelyselfcontained.Otherscriptsdontneedtoknowhowitworksin
ternallyandthishelpsusreducebugs,aswellasmakingourscriptseasiertoreusein
otherprojects.

LateUpdate()
We'reusingLateUpdate()insteadofUpdate()toensurethatthecameraisn't

40

laggingaframebehindofthemotion.ThisfunctionusesthefunctionGetGoalPo-

sition()tointerpolatebetweenthecurrentcamerapositionandthegoalposition.
GetGoalPosition()
Thisfunctioncalculateswherethecamerashouldbewhenthenextframeisdrawn.
(Thispartofourscriptseemsfairlylongwinded,butmuchofitdealswithhowthe
camerabehavesattheboundariesofthelevel,whichinvolvesperformingsimilar,but
notidentical,testsforeachedge.)

StreamlineYourWorkflow
Animportantconcepttokeepinmindforanyprojectishowtooptimizeyourwork
flow.
Onewaytooptimizeyourworkflowisincludedwithinthistutorial.Byharnessingthe
flexibilityofUnity,youcancreatescriptsthatautomatecertainproceduresforyou.
Morespecifically,inthistutorialyou'llnoticeamenuatthetopofthescreentitled
"2D"thatcontainstwoitemsthatautomatetheprocesswejustdescribed.
GiveoneofthesemenuitemsatrybydraggingacrateprefabintotheSceneView.
SelectthecrateintheSceneView,goto2D>MoveOnto2DPlane.Ifitwasn't
already,you'llnoticethatthecrate'sZpositionhaschangedtozero.
Theothermenuitemisnotnecessaryforthecratesincethatprefabalreadyhasthe
Rigidbody(andotherrequiredcomponents)attached.
Creatingcustommenucommandscanbesurprisinglysimple!Belowweexplainthe
scriptusedtocreatethesemenuitems.Thescriptbelow,titledTwoDHelpercanbe
foundintheProjectPanewithintheEditorfolder.
NOTE ScriptsthataddcustommenuitemsmustbelocatedintheEditorfolder.
Firstup,wehavethe2DmenusMoveOnto2DPlanefunction.
Thismenuitemhastwofunctions:MoveOnto2DPlane()itself,whichperformsthe
functionwewant;andValidateMoveOnto2DPlane(),whichtellstheUnityEdi
torwhentoenablethemenuitem.(Notallmenucommandswillneedthelatterfunc
tion.)
@MenuItem ("2D/Move Onto 2D Plane ^2")
static function MoveOnto2DPlane () {
for (var transform in Selection.transforms) {
transform.position.z = 0;
}

41

}
@MenuItem ("2D/Move Onto 2D Plane ^2", true)
static function ValidateMoveOnto2DPlane () {
return (Selection.activeTransform != null);
}

ThevalidationfunctionmerelychecksthatwehaveaGameObjectselected.(Weactu
allycheckifthecurrentlyselectedobjecthasaTransformasallGameObjectshaveone
oftheseComponents.)

Thesecondmenuitemperformsthesamemoveto2Dplaneactionbycalling
MoveOnto2DPlane()first,thengoesaheadandaddstheRigidBodyandConfigur
ableJointComponentsweneedforaGameObjecttoworkinour2Dgame.Iteven
ensurestheConfigurableJointComponentszMotion,angularXMotionandangu
larYMotionpropertiesaresettoLockedforus.
NOTE BothourmenucommandswillloopthroughwhateverGameObjectwevese
lectedandapplythesameinstructionsonanychildGameObjectsitcontains.

@MenuItem ("2D/Make Selection 2D Rigidbody")


static function MakeSelection2DRigidbody () {
MoveOnto2DPlane();
for (var transform in Selection.transforms) {
var Rigidbody : Rigidbody = transform.GetComponent(Rigidbody);
if (!Rigidbody)
transform.gameObject.AddComponent(Rigidbody);
var configurableJoint : ConfigurableJoint =
transform.GetComponent(ConfigurableJoint);
if (!configurableJoint)
configurableJoint =
transform.gameObject.AddComponent(ConfigurableJoint);
//configurableJoint.configuredInWorldSpace = true;
configurableJoint.xMotion = ConfigurableJointMotion.Free;
configurableJoint.yMotion = ConfigurableJointMotion.Free;
configurableJoint.zMotion = ConfigurableJointMotion.Locked;
configurableJoint.angularXMotion = ConfigurableJointMotion.Locked;
configurableJoint.angularYMotion = ConfigurableJointMotion.Locked;
configurableJoint.angularZMotion = ConfigurableJointMotion.Free;

42

}
}
@MenuItem ("2D/Make Selection 2D Rigidbody", true)
static function ValidateMakeSelection2DRigidbody () {
return (Selection.activeTransform != null);
}

SpaceshipScriptPart1:DefiningHelperClasses
ThenextscriptwewillbeexaminingiscalledSpaceshipandcanbefoundinthePro
jectPaneinScripts>2D>Spaceship.Forthesakeofsavingspacetheentirescriptwill
notbelistedinthistext,butcanbeexaminedonyourownbyusingthecommentswe
providethroughout.
Whilethespaceshipisselectedinthehierarchy,lookintheInspectoratthe
Spaceshipcomponent.
NoticethePositionalMovementsettingsandRotationalMovementsettingsareiden
tical.TheybothhaveMaxSpeed,NegativeAcceleration,DragWhileCoasting,etc.
Sincethesesettingsareidentical,thisisaperfectopportunitytocreateahelperclass.
Ifusedcorrectly,ahelperclasscanbeusedtocreatemuchcleanerandreusablecode.
Youwillseelaterwhereandhowweusethisclass,butfornowwewilljustdefineit.
(Anotheradvantagetodefiningahelperclasssuchasthisisitspropertieswillbe
groupedtogetherbytheInspector,makingforamuchcleanerinterface.)
...
class MovementSettings {
var maxSpeed : float;
var
var
var
var
var

positiveAcceleration : float;
negativeAcceleration : float;
dragWhileCoasting : float;
dragWhileBeyondMaxSpeed : float;
dragWhileAcceleratingNormally : float;

//A function that determines which drag variable to use.


function ComputeDrag(input : float, velocity : Vector3) {
var drag = 0.0;
//Is the input not zero (the 0.01 allows for some error since we're working with
floats)
//If the input is zero, use dragWhileCoasting
if (Mathf.Abs(input) > 0.01) {
//Are we greater or less than our max speed? and assign the appropriate
drag

43

if (velocity.magnitude > maxSpeed)


drag = dragWhileBeyondMaxSpeed;
else
drag = dragWhileAcceleratingNormally;
}
else
drag = dragWhileCoasting;
return drag;
}
}

ThefunctionComputeDrag()definedintheMovementSettingsclassabovewillbe
usedlaterinthescript.Computingthedragisthesameforbothangularandposi
tionalmovement,soputtingitinthehelperclassmeanswedon'thavetowritethe
samecodetwicewhendeterminingwhichdragtouse.
Nextwewilldefineonemorehelperclasstouselaterforaddingparticleeffectsto
thespaceship.Thisoneisabitshorterandsweeter.
//...continued from Spaceship
//Generally always need this next line for your helper classes.
@script System.Serializable
class SpecialEffects {
var positiveThrustEffect : GameObject;
var negativeThrustEffect : GameObject;
var positiveTurnEffect : GameObject;
var negativeTurnEffect : GameObject;
var collisionVolume = 0.01;
}

SpaceshipScriptPart2:ControllingtheSpaceship
Thenextchunkofcodeshownbelowissimplydefiningourvariablesthatwillshow
upintheInspector.
We'reputtingourMovementSettingshelperclassintogooduse.Wedefinebothpo
sitionalSettingsandrotationalSettingsasaMovementSettingsclasstype.
//...continued from Spaceship
//What is our forward direction? Our spaceship moves in the positive y direction.
var forwardDirection : Vector3 = Vector3(0.0, 1.0, 0.0);
//We create two instances using our MovementSettings helper class.

44

//One will be for translational (position) movement, the other for rotational.
var positionalMovement : MovementSettings;
var rotationalMovement : MovementSettings;
//We create an instance using our SpecialEffects helper class.
var specialEffects : SpecialEffects;

Nowwefinallygettotheheartofthescript.Abovewehavedefinedeverythingthat
weneed,andnowweputthoseitemstouse.
//...continued from Spaceship
//FixedUpdate() is advantageous over Update() for working with Rigidbody physics.
function FixedUpdate() {
// Retrieve input. Note the use of GetAxisRaw(), which in this case helps
responsiveness of the controls.
// GetAxisRaw() bypasses Unity's builtin control smoothing.
thrust = Input.GetAxisRaw("Vertical");
turn = Input.GetAxisRaw("Horizontal");
//Use the MovementSettings class to determine which drag constant should be used
for the positional movement.
//Remember the MovementSettings class is a helper class we defined ourselves. See
the top of this script.
Rigidbody.drag = positionalMovement.ComputeDrag(thrust, Rigidbody.velocity);
//Then determine which drag constant should be used for the angular movement.
Rigidbody.angularDrag = rotationalMovement.ComputeDrag(turn,
Rigidbody.angularVelocity);
//Determines which direction the positional and rotational motion is occurring, and
then modifies thrust/turn with
//the given accelerations.
//If you are not familiar with the ?: conditional, it is basically shorthand for an
"if...else" statement pair. See
//http://www.javascriptkit.com/jsref/conditionals.shtml
thrust *= (thrust > 0.0) ? positionalMovement.positiveAcceleration :
positionalMovement.negativeAcceleration;
turn *= (turn > 0.0) ? rotationalMovement.positiveAcceleration :
rotationalMovement.negativeAcceleration;
// Add torque and force to the Rigidbody. Torque will rotate the body and force will
move it.
// Always modify your forces by Time.deltaTime in FixedUpdate(), so if you ever
need to change your Time.fixedTime
// setting, your setup won't break.
Rigidbody.AddRelativeTorque(Vector3(0.0, 0.0, -1.0) * turn * Time.deltaTime,
ForceMode.VelocityChange);
Rigidbody.AddRelativeForce(forwardDirection * thrust * Time.deltaTime,
ForceMode.VelocityChange);

45

}
// The Reset() function is called by Unity when you first add a script, and when you
choose Reset on the
// gear popup menu for the script.

Next,wedefinesomedefaultvaluesthatappearifyouchooseResetintheInspector.
//...continued from Spaceship
// The Reset() function is called by Unity when you first add a script, and when you
choose Reset on the
// gear popup menu for the script.
function Reset() {
// Set some nice default values for our MovementSettings.
// Of course, it is always best to tweak these for your specific game.
positionalMovement.maxSpeed = 3.0;
positionalMovement.dragWhileCoasting = 3.0;
positionalMovement.dragWhileBeyondMaxSpeed = 4.0;
positionalMovement.dragWhileAcceleratingNormally = 0.01;
positionalMovement.positiveAcceleration = 50.0;
// By default, we don't have reverse thrusters.
positionalMovement.negativeAcceleration = 0.0;
rotationalMovement.maxSpeed = 2.0;
rotationalMovement.dragWhileCoasting = 32.0;
rotationalMovement.dragWhileBeyondMaxSpeed = 16.0;
rotationalMovement.dragWhileAcceleratingNormally = 0.1;
// For rotation, acceleration is usually the same in both directions.
// It could make for interesting unique gameplay if it were significantly
// different, however!
rotationalMovement.positiveAcceleration = 50.0;
rotationalMovement.negativeAcceleration = 50.0;
}

Last,wetellUnitywhichcomponentsareneededwhenthisscriptisattached.Thisis
actuallyfoundattheverybottomofthescript.Itisnotrequiredtobeatthebottom,
butforthesakeofconsistencyyouwillnoticethateverytimeRequireCompo-

nent()isusedinourscriptsitisatthebottom.

//...continued from Spaceship


// In order for this script to work, the object its applied to must have a Rigidbody and
AudioSource component.

46

// This tells Unity to always have the components when this script is attached.
@script RequireComponent(Rigidbody, AudioSource)

SpaceshipScriptPart3:SpecialEffects
Withthescriptabove,wehaveafullyfunctionalspaceshipthatiscontrolledbythe
player.However,togiveitalittlemoremojowewanttoaddsomespecialeffects.
TheremainingsectionsoftheSpaceshipscriptdealwiththespecialeffects.
Briefly,alltheparticleeffectsaretakencareofwithintheUpdate()function.Itends
upbeingpartitionednicelysinceallofthephysicsandcontrolsaretakencareof
withintheFixedUpdate()function.
ThesoundeffectsareexecutedwiththeOnCollisionEnter()function.
Readthroughthescripttounderstandhowitworks,usingthecommentsweincluded
toassistyou.
NOTE Thespaceshipcurrentlyhasonlyoneparticleeffectthatoccurswhenforward
thrustisoccurring,butthescriptallowsforparticleeffectsinalldirections.
Thisisagoodexampleofreusablecodeforvariousdifferentpurposes.
Asanexercise,wesuggestaddingmoreparticleeffectsforthrustintheotherdirec
tions.

Finished!
Ifyouhavereachedtheendofthissectionyoushouldbeproud.Youdidn'treallyadd
muchtoyourlevelinthissection,butyoudidexpandyourknowledgebase.Youcan
usesomeofthetoolsandconceptsyoulearnedhereandapplythemtocountless
otherprojects.Evenifyoudidn'tcompletelygraspallofthescripts,that'sokayjust
storethisprojectawayandkeepthesescriptsinmindtouseasaresourcelateron.
Now,propyourfeetonthedeskandenjoyanicetallglassofbeerlemonadeyou've
earnedit.
(Disclaimer:UnityTechnologiesandGraveckInteractivedonotcondonedrinkingon
thejoboranyotherinappropriateorillegalalcoholicconsumption.)

47

What'sNext?
Hereareafewchallenges
wegiveyoutomakethis
2Dplatformgamemore
complete.

YourTurn
Inthistutorialwehavelookedintothebasicsofbuilding2Dgamesusing3Dtools.
Nowitstimetotakeoffthoselittlestabilizingwheelsfromthebicycleofwisdomand
rideoffonourown!Herearesomesuggestions...

ImprovethegamesUI
Atthemoment,theonlywaytoswitchbetweenLerpzandtheSpaceshipisbyclicking
onabuttonwiththemouse.Thisbreaksthecontinuityofthegameworldbyrequir
ingtheuseofacompletelydifferentinputdevice.Therearetwopossiblesolutionsto
this:
Usethekeyboardinstead.
ReplacetheGUIwithakeyboardcommandtotogglebetweenLerpzandthe
Spaceship.(AddingandchangingcontrolsinUnityiscoveredintheUserGuide.)
AllowLerpztoentertheSpaceship.
HavethecontrolautomaticallyswitchtotheSpaceshipwhenLerpztouchesit.
ThetrickypartistomakeitlookasifLerpzhassteppedinsideyoullneedto
hidetheCharacter(Lerpz)modelwhiletheSpaceshipisbeingcontrolled.
YoullalsoneedtoaddawaytoexittheSpaceshipperhapsbyhavingLerpz
reappearwhenitlands,orbyaddinganewkeyboardcommand.

48

Addsomebling
Whatsidescrollingplatformerwouldbecompletewithoutsomesortofcoin,ring,or
othersortofbling.
Here'sastartingpointifyouneedit:
Createanobject(acylinderperhaps)thathasRigidbodyandCollidercompo
nents.
Don'tforgettoapplytheusual2Drestrictions.
Onemethodofcompletingthistaskwouldbetohavetheblingbeatrigger.When
thecharacterhitsthetrigger,amessageissentfromthecharactertotheobjectthat
inturntriggersforces/torquetomakeitspinandflyoffthescreen.
Ifyou'rereallyambitiousyoucouldhaveittriggersoundandparticleeffects.

Addmorepizzazztothespaceship
Currently,thespaceshiphasoneparticleeffectfortheforwardthrust.Tryadding
particleeffectsforturningthespaceship.Thiswillbegoodpracticeworkingwithpar
ticleeffects.Don'tjustreusethesameflameeffectexperimentandchangeitupa
little!Additionally,youcouldhavethespaceshipthrustbackwards.Thisentiretask
requiresnoadditionalscripting!

HavetheDeathZonerespawntheSpaceship
Lookthroughthescriptstoexplorehowthecharacterisrespawnedandapplythe
samemethodtotheSpaceshipthroughscripting.

Turnitintoagame
Lerpzdoesntreallyhaveagoalatthemoment.Thistutorialwasdesignedtoeducate
andhasntdippedintogamedesignissues.Considerthetutorialasastartingpoint
andtrymakingacompletegamewithit!Addsomeenemiestofight,puzzlestoto
solveandalltheothertrappingsofaplatformer.

49

You might also like