You are on page 1of 6

46Tips&Tricksfor2DmobilePerformanceinUnity.

Unitysabeast.Imalwaysimpressedathowversatileandperformantitcanbe.Butlikeanybeastit
requiresalittlebitoftaming(andinsomecasessomeverycounterintuitivetrickery,butthatswhere
thismetaphorfallsapart).IvehadabitofastrugglegettingTruckTosstoplaysmoothlyonmy3GS,
butheresanicebiglistoftipstohelpyouonyourway.
IfthisisyourfirstjumpintotheworldofUnity,myfirsttip(thisonesafreebie)istostoptryingtouse
itlikeotherlanguagesandenvironments.YouwillbeusingGameObjects,youwillbeaddingmultiple
scriptcomponents,andyouwillhavetothinkdifferently.WhenIfirststarted,myapproachwasto
largelyignoreprefabs(orusethemlikeFlashsdisplaylist)andgetacopyofBox2Drunning.Painful
asitistodeviate,getreadytoputinsomework!
Withoutfurtherado,letsgetstarted:Physics:
Usethebuiltinphysics.
Itmightseemlikeawasteofcyclestohaveafully3Dphysicsenginerunningtheshowfora2D
game,butbearinmindthattheNvidiaPhysXenginewillberunninginUnitysnativecore.Were
talkingaboutahyperoptimisedenginemaintainedbylargeprofessionalteams,andnotahobbyist
2Dengine.FreezeZpositionandX/Yrotationforthat2Dfeel.
Trytousea1/1scale.
BythisImean,1unit=1meter.Youcanuselargerorsmallerscales,butyourelikelytoencounter
someweirdnesswhenitcomestocollisions,andthespeedatwhichobjectsfall.Remember,agrand
pianowithoutairresistancewillfallasfastasadeadbabybutifeverythingislarge,itwillseemslow.
Youcanfiddlewithgravity,butagain,yourerunningtheriskofmessingwithcollisions.Iliketousea
1/32scalecomparedtomyspriteswithacamsizeof160.
GetyourobjectMassright.
Justlikewithscale,ifyouhaveagrandpianoweighing2gmoradeadbabyweighing500kgthings
aregoingtogetunpredictable.Trytokeepitrealisticish.
Meshcolliderscanbeslowcomparedtoprimitivebox/spherecolliders.
Whileaspheremayhavemanymorevertsthansayacube,theuniformdistancefromthecentre
wouldmakeitmassivelyeasiertocalculatethanlotsofindividualtriangles.
Youcansimulatemorecomplexshapesbycombiningprimitivecolliders.

IfyouhaveaparentobjectwithsayaBoxColliderandRigidbodycomponent,youcanaddchild
objectswithjustaBoxCollider.Theentireobjectwillcollidelikeonesolidmultipartobject.
Continuingfromtheabove
Ratherthanhavingseveraloftheselinkedtogether,youcanaddmorechildobjectswithRigidBodies
andColliders,anduseJointstoconnectthemtotheparentobject.Youcouldbuildacompoundcar
forexamplewithaparentbodytomovetheentirething.
Multiplebasicjointsarenotsupportedononegameobject
butmultipleconfigurablejointsare.Ratherthanhavinganetworkofjointedobjectsyoucouldfor
examplehaveaspringandasliderfromwheeltoaxlecuttingdownonasuspensionobjectin
between.
ObjectswithacolliderbutnoRigidBodyareconsideredstatic.
Movingtheseisexpensive,soifyourecreatingthemwithcode,addthecolliderandphysicsmaterial
(tothecollider)afterpositioning.
Whileitsconsideredgoodpracticetokeepyoursolveriterationsconstant
youmightfinditbeneficialtousethefullamountonlyevery2ndupdate.I.e.8,4,8,4,8,4.Ifthis
alleviatessomeoftheprocessorloadthesolverforexamplemaynothavetoskipiterations,andwill
actuallyprovideamoreconsistentsimulation.Isaiditwasgoingtobecounterintuitive.
WhiletheuseofInterpolationandExtrapolationonRigidBodiesisdiscouragedenmasse..
insomecasesyoumightfindthatturningtheseon,andreducingtheoverallsolveriterations
providesabettersimulation.Fiddle.
Loweryourtimestep!
Ifyoureaimingforanunrealistic60FPSandthephoneisconstantlystruggling,yourebestjustto
settleforalowerframerateandgiveitsomebreathingroom.Iliketousea0.03fixedtimestepwitha
maximumofabout0.05.Again,itcanbeslightlycounterintuitivedecreasingtimestepstogethigher
framerates,butgiveitashot.
Timescalescaling.
Thiscouldhelp,dependingonthefeelyouregoingfor.Itsimplysimulatesmoretimepassing
betweeneachiteration.Settingthistoohighwillobviouslymesswithcollisions,especiallyifanobject
hastraveledsay,amileinoneframe,itsnotgoingtohitadamnthing.
Sprites&TexturesMyengineusesahybridsystemofSpriteManager2/EZGUIandRageSplinefor
sprites,butIveused2DToolkitandmuchofthefollowingstillapplies.
Easyonthefillrate!
Itmightseemobviousbutifyouhavea6464image,withonlythetopleft3232filled,thatsstilla
6464sprite.Trimyourtransparentimageswherepossible.Lotsoflibrarieswilldothisautomatically.
Hidespritesyourenotusing.
Makeareferencetothemandsetthemactive=falseTheywontbedrawnwhenoffscreenanyway,

butsomethinghastodeterminewhetherornottheyrevisibleandchancesareyouknowbest,
especiallywhenonespritemaybefullyhiddenbehindanotherandisstilldrawn.
Batchingisyourfriend.Butnotalways.
Ifyouhave40collectablecoinsinyourlevel,allusingthesamespritethenbatchingwillusetheone
texturesourcemultipletimesonagiantmesh,savingondrawcalls.Drawcalls=time.Insomevery
rarecasesthebatchcalculationscanbeahinderance,dependingonhowyourgamessetup,butif
thatsthecase,chancesareyouredoinitwrong.
ResizeyourspritesQuad(thespriteitself)ratherthanitstransform.
IfyouhavesayaspritecomponentonaGameObject,thenresizetheGameObjectstransform,
youregoingtobreakbatchingonthatsprite.Insteadconsiderthenextpoint.WithSM2forexample,
youdjustsettheSprite/PackedSpritesWidthandHeightpropertiesintheinspector.
Ifyouhavea6464sprite,ona6pxwidecube
thenitsgoingtolooklikeasmallversionofyourimage,butuponzoomingin,youllseethatthefull
6464spritehasbeenUVmappedtothecubeinperfectdetail.RememberwhatIsaidaboutfillrate.
Unlessyourezoominginandout,youmightnotwanttousesuchalargetexture.
UseaSpriteSheet/Atlaswherepossible.
Thisoneoughttogohigher,butwhatthehell.Aspritesheetwillallowyoutousecommonlygrouped
itemslikeyourcharacter,coins,platforms,etcinasingleimage/texture.Why?Lessdrawcalls!The
samepartofatexturecanbeUVmappedtodifferentpartsofa3Dshapemultipletimes.I.e.ifyou
weremodellingaredandwhitestripycandycane,youddrawonewhiteandoneredline,thenapply
themmultipletimes.Thisisasimilarconcept.
Usetherightshaders!
Theresnopointusinglitshadersifyouvenolighting,andtheresnopointusingatransparent
shaderonasolidsquaresprite.YoucanfinddedicatedmobileshadersintheUnityStore,by
googlinganddoingalittlecopypastaviaMonoDeveloporusingthosethatcomewithSM2/Unity.As
of3.5Ibelievethedefaultshadersdoaprettydecentjob.Comingfromvariousotherbackgroundsit
mightbeeasytounderestimatetheimportanceoftheseevenina2Denvironment.
Doyoureallyneedantialiasing/filteringonyoursprites?
Besuretocheckonyourtargetdevice.Somethingswilllookprettyhorrificscaleduponyour
monitor,butabsolutelyfineonthosetinyhighdensityscreens.Giveitashot,andremembertoapply
changestoyourSpriteAtlaswherepossible.
Easyonthecompression!
DXT(DirectX)compressionwilldoafantasticjobonyourPC,withhardwaredecoding,butmobile
deviceslackthishardwaredecoderandwillhavetodoitinsoftware.I.e.Slowly.GenerallyIOS
deviceswillsupporthardwarePVRTCcompressionandAndroidsETC,andkeepinmindwhatIsaid
inthelastpoint.DXTmightbefinegiventhatitoffersbetterclarityduringsaylevelloads,butyou
certainlydontwanttobedecompressingthemduringgameplay.

DoyouneedMipMaps?
Mipmapsarescaleddownversionsofatexturestoredwithinthecompressedtextureitself.So
dependingonhowfarawayyouare,alowerrescopycanbeused.Obviouslythistakesmore
memoryandmoredecompressiontime.Youprobablydontneedemfora2Dgame.
Conversely
ratherthanusinggiantspritesonanonretinadisplayandtinyspritesonaretinadisplay,itmight
beworthyourwhilemakingasmallandlargeversionoftexturesandusingeachaccordingly.
Read/Writeenabledtexturesgenerateasecondcopy.
Secondcopyneedsmorememory.Inmostcases,youcanjustleavethisturnedoff.
Tintingaspritewillbreakbatching
andcreateanewcopyofthesourcetextureinmemory.Avoidwherepossible,ortrytopremake
anycolorsyoullneed!E.g.ifallyourNumbersinatextspritesheetaretobered..doitinphotoshop.
Loading,SavingandObjectAccess:DoyoureallyneedtorecreateyourGUIforeachlevel?
Youcanhideitandhaveitpersistwhenloadingdifferentscenes,reducingloadingtime.
GameObject.Instantiate()isslow!
Onecommontechnique(whichprovedabsolutelyvitalinTruckToss)istocreateapoolofobjects
duringloading.E.g.4ofeachenemytype.Whenanobjectsnolongerneeded,disableitandshove
itbackinthepoolinsteadofrecreatingit.Soyoudhaveafunctionalongthelinesof
MakePrefab(path/to/prefab)whichwillonlyonlycallResources.Load()providedtherearenonein
thepool.Resources.Load()isevenslower!
Thisfunctiondoesnotcache,andinvolvesreadingfromthedevicesHDorequivalent.Ideallyyou
wantahybridpoolsystemifyouredoingalotofloading\unloading.I.e.yourstandardpoolsystem
whichpreloadsobjects,butwhentheinstantiatefunctioniscalled,itkeepsadifferentcopyina
differentlist.Wheneverinstantiatescalledandtherearentenoughinthepoolbuttheresacopyin
thesparelist,InstantiatefromthatratherthandoingaResources.Loadfreshagain.Thisisa
balancingactofmemoryuseandprocessoruse,sotargetitforyourdevice.GameObject.Find()
andGetCompoenent()..
areslow(Yousawthatonecoming,right?).Ifyouregoingtobeusinganobjectorcomponent
repeatedly,thenitmakessensetocreateareferencetoitinalocalvariableratherthanlookingitup
repeatedly.Reflectivefunctionscanbenoticeablyslower.
Reflectionistheabilityforalanguage\codetolookwithinitselfandgetmethodnames\types\scope
etcandpotentiallyalterthem.I.e.callingafunctionbystringname,orusingdelegates.Trytoavoid
thiskindaofbehaviourforperformancecriticalcode.Thegarbagecollectorissloweryet.
Ithastoscantreesofobjectslookingfororphanedclassesandobjects,andislandsofobjectswith
referencesonlytoeachother,determinehowlongtheyvebeenthatway,andthenfreeupthe
memory.Sureyoucancallitmanually,butthatsgenerallymoreofahinttoitthanacommand,and
shouldntgenerallybeusedduringgameplay.Usingtoomuchmemory
willcauseIOSdevicestocrash\quitandyourappwontbeacceptedtotheappstore.Thats
actuallysecondarytothepointthatwhenmemoryslow,yourgamewillslowdowndramatically,

especiallyduringgarbagecollectionsandwhenyouretryingtoinstantiatenewobjects.

Sounds:
SetyourBGmusictodecompressonload.
Anythingyoullbeusingalotshouldprobablybedecompressedonloadratherthanstreamingfrom
thedisk(whichisslowandcanbeespeciallytroublesomeonAndroid.)Thisisanothertradeoff
situationhowever,giventhatdecompressioncantaketimeandmemory.Balanceit!
Infrequentlyusedclips
..maybeleftcompressedinmemory,especiallyiftherearelotsofthem.
Forcetomono?
Yesyes!Unlessyoureallywantstereoandyouvegotsomebitchinmusicorsoundeffects,youll
saveyourselfsomespaceonthisone.Rememberthephonehasamonospeaker
Hardwaredecodingisfaster.
Well,thatsageneralisation,butfasterisbetter.
UI:
UnitysUIsystemisslow.
Wherepossibletrytouseapluginorspritepackagethatrenderstomeshesin3Dspace.
OnGUIisslow!
Eveninablanksceneyoucanseeitspike.Trytohavenomorethanoneoftheseinyourcode,and
centralisebranchesoutfromit.Itsfairlyeasilydone.
TrytokeepyourUIanimationsinFixedTimestep()functions.
Thiswaytheyllstayconsistentacrossmultipledevicesandframerates.Youmightbenefitfrom
havingallofyourgamelogicforeveryclassbranchoutformasinglebasecalltoFixedTimeStep()
DoesyourUIhavetoupdate*every*frame?
Youmightgainamassiveperformanceboostbydeferringittoevery2ndorthirdframe.Withtruck
toss,thegamerunsmuchsmootherwiththeentiretyofthegamelogicrunningoneverysecond
FixedUpdate.Iknow,right?
MoarCameras!
Ifyourgamedoesalotofscaling\zooming,thenwhyhavetoscaletheUIandriskbreaking
batching?AddanothercamerafortheUI,andsetUIobjectslayerstothatofthecamera.Again,it
soundslikealotofextrablitting,butcouldpotentiallyspeedyourgameupwithverylittleinthewayof
changes.
BuildOptions:
Disabletheaccelerometer!
InolderUnities,thatwasdonevia#definekaccelerometer_frequency0intheAppControlerclassvia

XCode.NowadaysyoucandisableitfromwithinUnityitself,andcanfreeup23FPS.
InsomecasesOpenGLES1.0or2.0
willofferbetterperformanceonyourdevice.ThisseemstovarybetweendevicesandAndroid\iOS.
Tryonasmanydevicesasyoucan.
Stripthingsdown!
Whenyourgamesrunningniceandstable,switchcompatibilitytothe.NET2.0subset,Stripping
LeveltomicromscorlibandScriptCallOptimisationtoFastbutnoExceptions.Thiswillgeneratea
smallerbinarywithlessredundantcodeanddebugsymbols.Isuccessfullynavigatedthatone
withoutastripperreference.Jugs.
TargetiOS5wherepossible.
Therereallyisnodiscerniblespeeddifference.However,makesureyourXCodeprojectssettings
match,oruploadingtoiTunesmightfail.Perhapsitsworthexportinganotherproject.
BonusContentBuildingFaster!:
SymlinkUnityLibraries
fromthebuildsettingswherepossible,thiswillsavecopyingmorefilesovertoxCode,by
effectivelycreatingashortcut.Muchloveforsymlinks.
SetyourDebugInformationFormat
FromwithinXcode(BuildSettings)toSTABS,otherwisehavefunwatchingDWARFtakingages.
Stabs..dwarfLols
SometimesusingBuildfor
withinXCodewillbuildandrunfaster.Deletethepreviousversiononyourdeviceandgiveitashot.
Ihavenoideawhythisisso,butyourewelcome.
BonusContent2Fasterphysicsmodelling:ThisisafunlittletechniqueIusetoconvertedge
chainstosolidblocks!Createafakeedgechain,whereeachlinkbetween2pointsisactuallya
stretchedout,rotatedcubeparentedtosomething,formingtheoutlineofshapeofyourchoice
(cloud\star\car\whatever).Hitplay,andwhilethegameisrunning,dragyourchainbackintothe
editortomakeaprefab.Younowhaveagroupofparentedobjectsyoucanfillinandmakesolid.
Thisletsyouuseyourowncodetogeneratephysicsshapes.
Andfinally,
Breakeveryrule.Inthespiritofhackingawayatthings,youmustfiddleandseewhatsgoingon.If
somethingseemslikeasillyideaatfirst,youmightjustnothavethoughtaboutitfromallangles.
Letmeknowifyouveanythinginterestingtoadd.Happyhacking!

You might also like