You are on page 1of 49

2DGameplayTutorial

Providing2DGameplaywithUnity2 Author:GraveckInteractive LastRevision:19FEB2008

Contents

1. Introduction Why2DistheBee'sKnees Prerequisites 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! 3. DelvingDeeper:ScriptingExamples StudyingtheScripts MovingPlatformParticleEffects

4 6 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 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
184

Green
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
238

Green
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