Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such...

419
http://freepdf-books.com

Transcript of Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such...

Page 1: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 2: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 3: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Unity5GameOptimization

http://freepdf-books.com

Page 4: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TableofContents

Unity5GameOptimization

Credits

AbouttheAuthor

Acknowledgments

AbouttheReviewers

www.PacktPub.com

Supportfiles,eBooks,discountoffers,andmore

Whysubscribe?

FreeaccessforPacktaccountholders

Preface

Whatthisbookcovers

Whatyouneedforthisbook

Whothisbookisfor

Conventions

Readerfeedback

Customersupport

Downloadingtheexamplecode

Errata

Piracy

Questions

1.DetectingPerformanceIssues

TheUnityProfiler

LaunchingtheProfiler

Editororstandaloneinstances

Editorprofiling

TheUnityWebplayerconnection

RemoteconnectiontoaniOSdevice

RemoteconnectiontoanAndroiddevice

TheProfilerwindow

http://freepdf-books.com

Page 5: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Controls

CPUArea

TheGPUArea

TheRenderingArea

TheMemoryArea

TheAudioArea

ThePhysics3D/2DArea

Bestapproachestoperformanceanalysis

Verifyingscriptpresence

Verifyingscriptcount

Minimizingongoingcodechanges

Minimizinginternaldistractions

Minimizingexternaldistractions

Targetedprofilingofcodesegments

Profilerscriptcontrol

CustomCPUProfiling

SavingandloadingProfilerdata

SavingProfilerdata

LoadingProfilerdata

FinalthoughtsonProfilingandAnalysis

UnderstandingtheProfiler

Reducingnoise

Focusingontheissue

Summary

2.ScriptingStrategies

CacheComponentreferences

ObtainingComponentsusingthefastestmethod

Removingemptycallbackdeclarations

AvoidingtheFind()andSendMessage()methodsatruntime

Staticclasses

SingletonComponents

http://freepdf-books.com

Page 6: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Assigningreferencestopre-existingobjects

Aglobalmessagingsystem

Agloballyaccessibleobject

Registration

Messageprocessing

Implementingthemessagingsystem

Messagequeuingandprocessing

Implementingacustommessage

Messageregistration

Messagesending

Messagecleanup

Wrappingupthemessagingsystem

Disablingunusedscriptsandobjects

Disablingobjectsbyvisibility

Disablingobjectsbydistance

Considerusingdistance-squaredoverdistance

AvoidretrievingstringpropertiesfromGameObjects

Update,Coroutines,andInvokeRepeating

ConsidercachingTransformchanges

FasterGameObjectnullreferencechecks

Summary

3.TheBenefitsofBatching

DrawCalls

MaterialsandShaders

DynamicBatching

Vertexattributes

Uniformscaling

DynamicBatchingsummary

StaticBatching

TheStaticflag

Memoryrequirements

http://freepdf-books.com

Page 7: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Materialreferences

StaticBatchingcaveats

EditModedebuggingofStaticBatching

Avoidinginstantiatingstaticmeshesatruntime

Visibilityandrendering

StaticBatchingsummary

Summary

4.KickstartYourArt

Audio

Loadingaudiofiles

Profilingaudio

Additionalloadingoptions

Encodingformatsandqualitylevels

Audioperformanceenhancements

MinimizeactiveAudioSourcecount

MinimizeAudioClipreferences

EnableForcetoMonofor3Dsounds

Resampletolowerfrequencies

Considerallencodingformats

Bewareofstreaming

ApplyFiltereffectsthroughMixergroupstoreduceduplication

Use“WWW.audioClip”responsibly

ConsiderAudioModulefilesforbackgroundmusic

Texturefiles

Compressionformats

Textureperformanceenhancements

ReduceTexturefilesize

UseMipMapswisely

Manageresolutiondownscalingexternally

AdjustAnisotropicFilteringlevels

ConsiderAtlasing

http://freepdf-books.com

Page 8: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Adjustcompressionratesfornon-squareTextures

SparseTextures

ProceduralMaterials

Meshandanimationfiles

Reducingpolygoncount

TweakingMeshCompression

UseRead-WriteEnabledappropriately

Import/calculateonlywhat’sneeded

Considerbakedanimations

LetUnityoptimizemeshes

Combinemeshes

Summary

5.FasterPhysics

PhysicsEngineinternals

Physicsandtime

TheFixedUpdateloop

MaximumAllowedTimestep

Physicsupdatesandruntimechanges

StaticandDynamicColliders

Collisiondetection

Collidertypes

TheCollisionMatrix

Rigidbodyactiveandsleepingstates

Rayandobjectcasting

Physicsperformanceoptimizations

Scenesetup

Scaling

Positioning

Mass

UseStaticCollidersappropriately

OptimizetheCollisionMatrix

http://freepdf-books.com

Page 9: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Preferdiscretecollisiondetection

ModifytheFixedUpdatefrequency

AdjusttheMaximumAllowedTimestep

Minimizecastandbounding-volumechecks

AvoidcomplexMeshColliders

Usesimplerprimitives

UsesimplerMeshColliders

Avoidcomplexphysicscomponents

Letphysicsobjectssleep

ModifySolverIterationCount

Optimizingragdolls

ReduceJointsandColliders

Avoidinter-ragdollcollisions

Disableorremoveinactiveragdolls

Knowwhentousephysics

ConsiderupgradingtoUnity5

Summary

6.DynamicGraphics

Profilingrenderingissues

GPUprofiling

TheFrameDebugger

Bruteforcetesting

CPU-bound

Multithreadedrendering

GPUSkinning

Frontendbottlenecks

LevelOfDetail

DisableGPUSkinning

Reducetessellation

Backendbottlenecks

Fillrate

http://freepdf-books.com

Page 10: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Overdraw

OcclusionCulling

Shaderoptimization

ConsiderusingShadersintendedformobileplatforms

Usesmalldatatypes

Avoidchangingprecisionwhileswizzling

UseGPU-optimizedhelperfunctions

Disableunnecessaryfeatures

Removeunnecessaryinputdata

Onlyexposenecessaryvariables

Reducemathematicalcomplexity

Reducetexturelookups

Avoidconditionalstatements

Reducedatadependencies

SurfaceShaders

UseShader-basedLOD

Memorybandwidth

Uselesstexturedata

TestdifferentGPUTextureCompressionformats

Minimizetexturesampling

Organizeassetstoreducetextureswaps

VRAMlimits

Texturepreloading

Texturethrashing

LightingandShadowing

ForwardRendering

DeferredShading

VertexLitShading(legacy)

Real-timeShadows

Lightingoptimization

UsetheappropriateShadingMode

http://freepdf-books.com

Page 11: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UseCullingMasks

UseBakedLightmaps

OptimizeShadows

Optimizinggraphicsformobile

MinimizeDrawCalls

MinimizetheMaterialcount

MinimizetexturesizeandMaterialcount

Maketexturessquareandpowerof2

UsethelowestpossibleprecisionformatsinShaders

AvoidAlphaTesting

Summary

7.MasterfulMemoryManagement

TheMonoplatform

Thecompilationprocess

ManualJITcompilation

Memoryusageoptimization

Unitymemorydomains

Nativememory

Managedmemory

Garbagecollection

Memoryfragmentation

Garbagecollectionatruntime

Threadedgarbagecollection

Garbagecollectiontactics

ValuetypesandReferencetypes

Passbyvalueandpassbyreference

StructsareValuetypes

ArraysareReferencetypes

StringsareimmutableReferencetypes

Stringconcatenation

Boxing

http://freepdf-books.com

Page 12: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Theimportanceofdatalayout

TheUnityAPI

Theforeachloops

Coroutines

Closures

.NETlibraryfunctions

Temporaryworkbuffers

Objectpooling

Prefabpooling

PoolableComponents

ThePrefabpoolingsystem

Prefabpools

Objectspawning

Instanceprespawning

Objectdespawning

Prefabpooltesting

PrefabpoolingandSceneloading

Prefabpoolingsummary

ThefutureofMonoandUnity

Summary

8.TacticalTipsandTricks

Editorhotkeytips

GameObjects

SceneView

Arrays

Interface

Other

Editorinterfacetips

General

TheInspectorView

TheProjectView

http://freepdf-books.com

Page 13: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheHierarchyView

TheSceneandGameViews

PlayMode

Scriptingtips

General

Attributes

Variableattributes

Classattributes

Logging

Usefullinks

Customeditors/menustips

Externaltips

Othertips

Summary

Index

http://freepdf-books.com

Page 14: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 15: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Unity5GameOptimization

http://freepdf-books.com

Page 16: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 17: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Unity5GameOptimizationCopyright©2015PacktPublishing

Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.

Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.

PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.

Firstpublished:November2015

Productionreference:1281015

PublishedbyPacktPublishingLtd.

LiveryPlace

35LiveryStreet

BirminghamB32PB,UK.

ISBN978-1-78588-458-0

www.packtpub.com

http://freepdf-books.com

Page 18: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 19: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CreditsAuthor

ChrisDickinson

Reviewers

CliffordChampion

Dr.SebastianT.Koenig

AcquisitionEditor

IndrajitDas

ContentDevelopmentEditor

AthiraLaji

TechnicalEditor

PrajaktaMhatre

CopyEditor

CharlotteCarneiro

ProjectCoordinator

BijalPatel

Proofreader

SafisEditing

Indexer

RekhaNair

Graphics

JasonMonteiro

ProductionCoordinator

AparnaBhagat

CoverWork

AparnaBhagat

http://freepdf-books.com

Page 20: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 21: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AbouttheAuthorChrisDickinsongrewupinEnglandwithastrongpassionforscience,mathematics,andvideogames.Hereceivedhismaster’sdegreeinphysicswithelectronicsfromtheUniversityofLeedsin2005,andimmediatelytraveledtoCaliforniatoworkonscientificresearchintheheartofSiliconValley.Findingthatcareerpathunsuitable,hebeganworkinginthesoftwareindustry.

Overthelastdecade,hehasmadeacareerinsoftwaredevelopment,becomingaseniorsoftwaredeveloper.Chrishasprimarilyworkedinsoftwareautomationandinternaltesttooldevelopment,buthispassionforvideogamesneverfullyfaded.In2010,hetookthepathofdiscoveringthesecretsofgamedevelopmentand3Dgraphicsbycompletingaseconddegree—abachelor’sdegreeingameandsimulationprogramming.Heauthoredatutorialbookongamephysics(LearningGamePhysicswithBulletPhysicsandOpenGLbyPacktPublishing).Hecontinuestoworkinsoftwaredevelopment,creatingindependentgameprojectsinhissparetimewithtoolssuchasUnity3D.

http://freepdf-books.com

Page 22: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 23: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AcknowledgmentsI’vemanagedtograspanabsolutelyridiculousamountofknowledgeinjust5years.Noneofthiswouldhavebeenpossiblewithouttheconstantmotivationfrommycoworkers,tutors,friends,andfamily.

ThankstomycomradesinsoftwaredevelopmentforbeingsounderstandingofmyerraticschedulewhileIwaslearninggamedevelopmentatschool.

Thanksalsotomycollegetutorsforhelpingacceleratemepastthecorematerialandlearnsomuchaboutgamedevelopmentsoquickly.

ThankstomyfriendsforalwaysbeingaconstantsourceofharassmentandinquisitivenessaboutwhatI’vebeenworkingon.

Thankstomyfamilyforgivingmetheopportunitytolearn,live,andlovesomuchinsuchashorttime.

Andofcourse,thankstomywonderfulwifeandbestfriend,Jamie,forbeingsocaringandsupportiveofallthelatenightsandhelpingmestaycreative.

http://freepdf-books.com

Page 24: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 25: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AbouttheReviewersCliffordChampionhasabroadbackgroundinsoftwareengineering,withyearsofexperiencespanning3Dgames,Internetapplications,andartificialintelligence.HeholdsdegreesinmathematicsandcomputersciencefromUCLAandUCSD,respectively.Inthepast,CliffordworkedforvideogametechnologycompanyHavok(nowpartofMicrosoft),andinteractivemediaanddesigncompanyPlainJoeStudios.Currently,heleadsasoftwareteamatzSpace(zspace.com),aVRcompanyspecializingin3Dforclassroomsandindustry.

CliffordcanbefoundonTwitterat@duckmaestroandwelcomesdiscussionsonanytopic.

Dr.SebastianT.KoenigreceivedhisPhDinhumaninterfacetechnologyfromtheUniversityofCanterbury,NewZealand,developingaframeworkforindividualizedvirtualrealitycognitiverehabilitation.HeobtainedhisdiplomainpsychologyfromtheUniversityofRegensburg,Germany,intheareasofclinicalneuropsychologyandvirtualrealityrehabilitation.

SebastianisthefounderandCEOofKatanaSimulations,whereheoverseesthedesign,development,andevaluationofcognitiveassessmentandtrainingsimulations.Hisprofessionalexperiencespansover10yearsofclinicalworkincognitiverehabilitationandover8yearsofvirtualrealityresearch,development,andusertesting.Hehasextensiveexperienceasaspeakeratinternationalconferencesandasareviewerofscientificpublicationsintheareasofrehabilitation,cognitivepsychology,neuropsychology,softwareengineering,gamedevelopment,gameuserresearch,andvirtualreality.

Sebastianhasdevelopednumeroussoftwareapplicationsforcognitiveassessmentandtraining.Forhisworkonthevirtualmemorytask,hewasawardedtheprestigiousLavalVirtualAwardin2011,fortheMedicineandHealthcategory.OtherapplicationsofhisincludethevirtualrealityexecutivefunctionassessmentincollaborationwiththeKesslerFoundation,NewJersey,USA,andthepatent-pendingMicrosoftKinect-basedmotorandcognitivetrainingJewelMine/MysticIsleattheUSCInstituteforCreativeTechnologies,California,USA.

Hemaintainsthewebsiteatwww.virtualgamelab.com,whichfeatureshisresearchandhissoftwaredevelopmentprojects.HiswebsitealsocontainsacomprehensivelistoftutorialsfortheUnitygameengine.

http://freepdf-books.com

Page 26: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 27: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

www.PacktPub.com

http://freepdf-books.com

Page 28: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Supportfiles,eBooks,discountoffers,andmoreForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.

DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusat<[email protected]>formoredetails.

Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.

https://www2.packtpub.com/books/subscription/packtlib

DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt’sonlinedigitalbooklibrary.Here,youcansearch,access,andreadPackt’sentirelibraryofbooks.

http://freepdf-books.com

Page 29: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser

http://freepdf-books.com

Page 30: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

FreeaccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandview9entirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.

http://freepdf-books.com

Page 31: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 32: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PrefaceUserexperienceisacriticalcomponentofanygame.Userexperienceincludesnotonlyourgame’sstoryanditsgameplay,butalsohowsmoothlythegraphicsrun,howreliablyitconnectstomultiplayerservers,howresponsiveitistouserinput,andevenhowlargethefinalapplicationfilesizeisduetotheprevalenceofappstoresandclouddownloads.Thebarriertoenteringgamedevelopmenthasbeenloweredconsiderablythankstothereleaseofcheap,AAA-industry-levelgamedevelopmenttoolssuchasUnity.However,thefeaturesandqualityofthefinalproductthatourplayersexpectustoprovideisincreasingwitheverypassingday.Weshouldexpectthateveryfacetofourgamecanandwillbescrutinizedbyplayersandcriticsalike.

Thegoalsofperformanceoptimizationaredeeplyentwinedwithuserexperience.Poorlyoptimizedgamescanresultinlowframerates,freezes,crashes,inputlag,longloadingtimes,inconsistentandjitteryruntimebehavior,physicsenginebreakdowns,andevenexcessivelyhighbatterypowerconsumption(particularlyimportantinthiseraofmobiledevices).Havingjustoneoftheseissuescanbeagamedeveloper’sworstnightmareasreviewswilltendtofocusontheonethingthatwedidbadly,inspiteofallthethingsthatwedidwell.

Performanceisallaboutmakingthebestuseoftheavailableresources,whichincludestheCPUresourcessuchasCPUcyclesandmainmemoryspace,GraphicsProcessingUnit(GPU)resourcessuchasmemoryspace(VRAM)andmemorybandwidth,andsoon.Butoptimizationalsomeansmakingsurethatnosingleresourcecausesabottleneckataninappropriatetime,andthatthehighestprioritytasksgettakencareoffirst.Evensmall,intermittenthiccupsandsluggishnessinperformancecanpulltheplayeroutoftheexperience,breakingimmersionandlimitingourpotentialtocreatetheexperienceweintended.

Itisalsoimportanttodecidewhentotakeastepbackandstopmakingperformanceenhancements.Inaworldwithinfinitetimeandresources,therewouldalwaysbeanotherwaytomakeitbetter,faster,oreasiertomaintain.Theremustbeapointduringdevelopmentwherewedecidethattheproducthasreachedacceptablelevelsofquality.Ifnot,weriskdoomingourselvestoimplementingfurtherchangesthatresultinlittleornotangiblebenefit.

Thebestwaytodecideifaperformanceissueisworthfixingistoanswerthequestion“willtheusernoticeit?”.Iftheanswertothisquestionsis“no”,thenperformanceoptimizationwouldbeawastedeffort.Thereisanoldsayinginsoftwaredevelopment:

Prematureoptimizationistherootofallevil

Prematureoptimizationisthecardinalsinofreworkingandrefactoringcodetoenhanceperformancewithoutanyproofthatitisnecessary.Thiscouldmeaneithermakingchangeswithoutshowingthataperformanceproblemevenexists(answeringthequestionofwhetherornotitwouldbenoticeabletotheuser),ormakingchangesbecauseweonly

http://freepdf-books.com

Page 33: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

believeaperformanceissuemightstemfromaparticularareabeforeithasbeenproventobetrue.Makingthesemistakeshascostsoftwaredevelopers,asacollectivewhole,adepressingnumberofworkhoursfornothing.

Thisbookintendstogiveusthetools,knowledge,andskillsweneedtobothdetectandfixperformanceissuesinourapplication,nomatterwheretheystemfrom.ThiscouldbehardwarecomponentssuchastheCPU,GPU,orRAM,withinsoftwaresubsystemssuchasPhysics,Rendering,orwithintheUnityEngineitself.Inaddition,themoreresourceswesave,themorewecandowithintheUnityEnginewiththesamehardwaresystem,allowingustogeneratemoreinterestinganddynamicgameplay.

Thiswillgiveourgameabetterchanceofsucceedingandstandingoutfromthecrowdinamarketplacethatisinundatedwithnew,highqualitygameseverysingleday.

http://freepdf-books.com

Page 34: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

WhatthisbookcoversChapter1,DetectingPerformanceIssues,providesanexplorationoftheUnityProfilerandaseriesofmethodstoprofileourapplication,detectperformancebottlenecks,andperformrootcauseanalysis.

Chapter2,ScriptingStrategies,dealswiththebestpracticesforourUnityC#Scriptcode,minimizingComponentoverhead,improvinginter-objectcommunication,andmore.

Chapter3,TheBenefitsofBatching,exploresUnity’sDynamicandStaticBatchingsystemstoeasetheburdenontherenderingsystem.

Chapter4,KickstartYourArt,helpsyouunderstandtheunderlyingtechnologybehindourartassetsandlearnhowtoavoidcommonpitfallswithimporting,compression,andencoding.

Chapter5,FasterPhysics,isaboutinvestigatingthenuancesofUnity’sphysicssystemforboth3Dand2Dgames,andhowtoproperlyorganizeourphysicsobjectsforimprovedperformance.

Chapter6,DynamicGraphics,providesanin-depthexplorationoftherenderingsystem,andhowtoimproveapplicationsthatsufferrenderingbottlenecksintheGPU,orCPU,andspecializedtechniquesformobiledevices.

Chapter7,MasterfulMemoryManagement,examinestheinnerworkingsoftheUnityEngine,theMonoFramework,andhowmemoryismanagedwithinthesecomponentstoprotectourapplicationfromheapallocationsandruntimegarbagecollection.

Chapter8,TacticalTipsandTricks,dealswithamultitudeofusefultechniquesusedbyprofessionalstoimproveprojectworkflowandscenemanagement.

http://freepdf-books.com

Page 35: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 36: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

WhatyouneedforthisbookThemajorityofthisbookwillfocusonfeatureswithinthecontextofUnityversion5.x.MostofthetechniquescanbeappliedtoUnity4.xprojects,butmayrequireanupgradetoUnity4ProEditioninordertoaccesssomeofthem(suchasOcclusionCulling,StaticBatching,andeventheProfileritself).

http://freepdf-books.com

Page 37: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 38: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

WhothisbookisforThisbookisintendedforintermediateandadvancedUnitydeveloperswhohaveexperiencewithmostofUnity’sfeatureset,andthosewhowanttomaximizetheperformanceoftheirgameorsolveparticularbottlenecks.WhetherthebottleneckiscausedbyCPUoverload,runtimespiking,slowmemoryaccess,fragmentation,garbagecollection,poorGPUfillrate,ormemorybandwidth,thisbookwillteachyouthetechniquesyouneedtoidentifythesourceoftheproblemandhelpexploremultiplewaysofreducingtheirimpactonyourapplication.

FamiliaritywiththeC#languagewillbeneededforsectionsinvolvingscriptingandmemoryusage,andabasicunderstandingofcgwillbeneededforareasinvolvingShaderoptimization.

http://freepdf-books.com

Page 39: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 40: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ConventionsInthisbook,youwillfindanumberoftextstylesthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestylesandanexplanationoftheirmeaning.

Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:“ThemainUnitycallbackforapplicationupdatesistheUpdate()function.”

Ablockofcodeissetasfollows:

publicclassTestComponent:MonoBehaviour{

voidUpdate(){

if(Input.GetKeyDown(KeyCode.Space)){

PerformProfilingTest();

}

}

}

Whenwewishtodrawyourattentiontoaparticularpartofacodeblock,therelevantlinesoritemsaresetinbold:

publicclassTestComponent:MonoBehaviour{

voidUpdate(){

if(Input.GetKeyDown(KeyCode.Space)){

PerformProfilingTest();

}

}

}

Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,forexample,inmenusordialogboxes,appearinthetextlikethis:“ThethresholdvalueforthesleepingstatecanbemodifiedunderEdit|ProjectSettings|Physics|SleepThreshold.”

NoteWarningsorimportantnotesappearinaboxlikethis.

TipTipsandtricksappearlikethis.

http://freepdf-books.com

Page 41: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 42: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook—whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.

Tosendusgeneralfeedback,simplye-mail<[email protected]>,andmentionthebook’stitleinthesubjectofyourmessage.

Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.

http://freepdf-books.com

Page 43: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 44: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.

http://freepdf-books.com

Page 45: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

http://freepdf-books.com

Page 46: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks—maybeamistakeinthetextorthecode—wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.

Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.

http://freepdf-books.com

Page 47: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PiracyPiracyofcopyrightedmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.IfyoucomeacrossanyillegalcopiesofourworksinanyformontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.

Pleasecontactusat<[email protected]>withalinktothesuspectedpiratedmaterial.

Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.

http://freepdf-books.com

Page 48: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

QuestionsIfyouhaveaproblemwithanyaspectofthisbook,youcancontactusat<[email protected]>,andwewilldoourbesttoaddresstheproblem.

http://freepdf-books.com

Page 49: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 50: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter1.DetectingPerformanceIssuesPerformanceevaluationformostsoftwareproductsisaveryscientificprocess:determinethemaximumsupportedperformancemetrics(numberofconcurrentusers,maximumallowedmemoryusage,CPUusage,andsoon);performloadtestingagainsttheapplicationinscenariosthattrytosimulatereal-worldbehavior;gatherinstrumentationdatafromtestcases;analyzethedataforperformancebottlenecks;completearoot-causeanalysis;makechangesintheconfigurationorapplicationcodetofixtheissue;andrepeat.

Justbecausegamedevelopmentisaveryartisticprocessdoesnotmeanitshouldnotbetreatedinequallyobjectiveandscientificways.Ourgameshouldhaveatargetaudienceinmind,whocantellusthehardwarelimitationsourgamemightbeunder.Wecanperformruntimetestingofourapplication,gatherdatafrommultiplecomponents(CPU,GPU,memory,physics,rendering,andsoon),andcomparethemagainstthedesiredmetrics.Wecanusethisdatatoidentifybottlenecksinourapplication,performadditionalinstrumentationtodeterminetherootcauseoftheissue,andapproachtheproblemfromavarietyofangles.

Togiveusthetoolsandknowledgetocompletethisprocess,thischapterwillintroduceavarietyofmethodsthatwewillusethroughoutthebooktodeterminewhetherwehaveaperformanceproblem,andwheretherootcauseoftheperformanceissuecanbefound.Theseskillswillgiveusthetechniquesweneedtodetect,analyze,andprovethatperformanceissuesareplaguingourUnityapplication,andwhereweshouldbegintomakechanges.Indoingso,youwillprepareyourselvesfortheremainingchapterswhereyouwilllearnwhatcanbedoneabouttheproblemsyou’refacing.

WewillbeginwithanexplorationoftheUnityProfileranditsmyriadoffeatures.Wewillthenexploreahandfulofscriptingtechniquestonarrow-downoursearchfortheelusivebottleneckandconcludewithsometipsonmakingthemostofbothtechniques.

http://freepdf-books.com

Page 51: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheUnityProfilerTheUnityProfilerisbuiltintotheUnityEditoritself,andprovidesanexpedientwayofnarrowingoursearchforperformancebottlenecksbygeneratingusageandstatisticsreportsonamultitudeofUnity3Dcomponentsduringruntime:

CPUusagepercomponentoftheUnity3DEngineRenderingstatisticsGPUusageonseveralprogrammablepipelinestepsandstagesMemoryusageandstatisticsAudiousageandstatisticsPhysicsengineusageandstatistics

NoteWiththereleaseofUnity5.0,UnityTechnologieshasmadetheProfileravailabletoalldevelopersrunningthePersonalEdition(thenewnamefortheFreeEdition).

UsersrunningtheFreeEditionofUnity4musteitherupgradetoUnity5,orpurchasealicenseforUnity4ProEdition.

Thisadditionalreportingcomeswithaprice,however.Additionalinstrumentationflagswillbeenabledwithinthecompiler,generatingruntimeloggingeventsandadifferentlevelofautomatedcodeoptimizationwhiletheProfilerisinuse,whichcausessomeadditionalCPUandmemoryoverheadatruntime.Thisprofilingcostisnotcompletelynegligible,andislikelytocauseinconsistentbehaviorwhentheProfileristoggledonandoff.

Inaddition,weshouldalwaysavoidusingEditorModeforanykindofprofilingandbenchmarkingpurposesduetotheoverheadcostsoftheEditor;itsinterface,andadditionalmemoryconsumptionofvariousobjectsandcomponents.Itisalwaysbettertotestourapplicationinastandaloneformat,onthetargetdevice,inordertogetamoreaccurateandrealisticdatasample.

TipUserswhoarealreadyfamiliarwithconnectingtheUnityProfilertotheirapplicationsshouldskiptothesectiontitledTheProfilerwindow

http://freepdf-books.com

Page 52: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LaunchingtheProfilerWewillbeginwithabrieftutorialonhowtoconnectourgametotheUnityProfilerwithinavarietyofcontexts:

Localinstancesoftheapplication,eitherthroughtheEditororstandaloneProfilingtheEditoritselfLocalinstancesoftheapplicationinUnityWebplayerRemoteinstancesoftheapplicationonaniOSdevice(theiPadtabletortheiPhonedevice)RemoteinstancesoftheapplicationonanAndroiddevice(atabletorphonedevicerunningAndroidOS)WewillbrieflycovertherequirementsforsettinguptheProfilerineachofthesecontexts.

EditororstandaloneinstancesTheonlywaytoaccesstheProfileristolaunchitthroughtheUnityEditorandconnectittoarunninginstanceofourapplication.Thisisthecasewhetherwe’rerunningourgamewithintheEditor,runningastandaloneapplicationonthelocalorremotedevice,orwhenwewishtoprofiletheEditoritself.

ToopentheProfiler,navigatetoWindow|ProfilerwithintheEditor.IftheEditorisalreadyrunninginPlayMode,thenwemayseereportingdatagatheringintheProfilerWindow:

TipToprofilestandaloneprojects,ensurethattheUseDevelopmentModeandAutoconnectProfilerflagsareenabledwhentheapplicationisbuilt.

SelectingwhethertoprofileanEditor-basedinstance(throughtheEditor’sPlayMode)orastandaloneinstance(separatelybuiltandrunninginthebackground)canbeachievedthroughtheActiveProfileroptionintheProfilerwindow.

http://freepdf-books.com

Page 53: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheUnityProfiler

EditorprofilingProfilingtheEditoritself,suchasprofilingcustomEditorScripts,canbeenabledwiththeProfileEditoroptionintheProfilerwindowasshowninthefollowingscreenshot.NotethatthisrequirestheActiveProfileroptiontobeconfiguredtoEditor.

TheUnityWebplayerconnectionTheProfilercanalsoconnecttoaninstanceoftheUnityWebplayerthatiscurrentlyrunninginabrowser.Thisenablesustoprofileourweb-basedapplicationinamorereal-worldscenariothroughthetargetbrowser,andtestmultiplebrowsertypesforinconsistenciesinbehavior.

1. EnsurethattheUseDevelopmentModeflagisenabledwhentheWebplayerapplicationisbuilt.

2. LaunchthecompiledWebplayerapplicationinabrowserand,whileitisactiveinthebrowserwindow,holdtheAltkey(OptionkeyonaMac)andright-clickontheWebplayerobjectwithinthebrowsertoopentheReleaseChannelSelectionmenu.ThenselecttheDevelopmentchannel,asshowninthefollowingscreenshot:

NoteNotethatchangingtheReleaseChanneloptionwillrestarttheWebplayerapplication.

http://freepdf-books.com

Page 54: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

3. Asshowninthefollowingscreenshot,opentheProfilerintheUnityEditorwithintheProfilerwindow,andthennavigatetoActiveProfiler|WindowsWebPlayer(COMPUTERNAME)orActiveProfiler|OSXWebPlayer(COMPUTERNAME),dependingontheOperatingSystem:

YoushouldnowseereportingdatacollectingintheProfilerwindow.

RemoteconnectiontoaniOSdeviceTheProfilercanalsobeconnectedtoanactiveinstanceoftheapplicationrunningremotelyonaniOSdevice,suchasaniPadoriPhone.ThiscanbeachievedthroughasharedWiFiconnection.FollowthegivenstepstoconnecttheProfilertoanAppledevice:

NoteNotethatremoteconnectiontoanAppledeviceisonlypossiblewhentheProfilerisrunningonanAppleMacdevice.

1. EnsurethattheUseDevelopmentModeandAutoconnectProfilerflagsareenabledwhentheapplicationisbuilt.

2. ConnectboththeiOSdeviceandMactoalocalorADHOCWiFinetwork.3. AttachtheiOSdevicetotheMacviatheUSBortheLightningcable.4. BeginbuildingtheapplicationwiththeBuild&Runoptionasnormal.

http://freepdf-books.com

Page 55: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

5. OpentheProfilerwindowintheUnityEditorandselectthedeviceunderActiveProfiler.

YoushouldnowseetheiOSdevice’sprofilingdatagatheringintheProfilerwindow.

TipTheProfilerusesports54998to55511tobroadcastprofilingdata.Makesuretheseportsareavailableforoutboundtrafficifthereisafirewallonthenetwork.

RemoteconnectiontoanAndroiddeviceTherearetwodifferentmethodsforconnectinganAndroiddevicetotheUnityProfiler:eitherthroughaWiFiconnectionorusingtheAndroidDebugBridge(ADB)tool.ADBisasuiteofdebuggingtoolsthatcomesbundledwiththeAndroidSDK.

FollowthegivenstepsforprofilingoveraWiFiconnection:

1. EnsurethattheUseDevelopmentModeandAutoconnectProfilerflagsareenabledwhentheapplicationisbuilt.

2. ConnectboththeAndroidanddesktopdevicestoalocalWiFinetwork.3. AttachtheAndroiddevicetothedesktopdeviceviatheUSBcable.4. BeginbuildingtheapplicationwiththeBuild&Runoptionasnormal.5. OpentheProfilerwindowintheUnityEditorandselectthedeviceunderActive

Profiler.

YoushouldnowseetheAndroiddevice’sprofilingdatagatheringintheProfilerWindow.

ForADBprofiling,followthegivensteps:

1. FromtheWindowscommandprompt,runtheadbdevicescommand,whichchecksifthedeviceisrecognizedbyADB(ifnot,thenthespecificdevicedriversforthedevicemayneedtobeinstalledand/orUSBdebuggingneedstobeenabledonthetargetdevice).

NoteNotethat,iftheadbdevicescommandisn’tfoundwhenitisrunfromthecommandprompt,thentheAndroidSDKfoldermayneedtobeappendedontotheEnvironment’sPATHvariable.

2. EnsurethattheUseDevelopmentModeandAutoconnectProfilerflagsareenabledwhentheapplicationisbuilt.

3. AttachtheAndroiddevicetothedesktopdeviceviathecable(forexample,USB).4. BeginbuildingtheapplicationwiththeBuild&Runoptionasnormal.5. OpentheProfilerWindowintheUnityEditorandselectthedeviceunderActive

Profiler.

YoushouldnowseetheAndroiddevice’sprofilingdatagatheringintheProfilerwindow.

http://freepdf-books.com

Page 56: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheProfilerwindowWewillnowcovertheessentialfeaturesoftheProfilerastheycanbefoundwithintheinterface.

NoteNotethatthissectioncoversfeaturesastheyappearintheUnityProfilerwithinUnity5.AdditionalfeatureswereaddedtotheProfilerwiththereleaseofUnity5;thesemaybedifferent,ornotexist,inUnity4’sProfiler.

TheProfilerwindowissplitintothreemainareas:

ControlsTimelineViewBreakdownView

Theseareasareasshowninthefollowingscreenshot:

ControlsThetopbarcontainsmultiplecontrolswecanusetoaffectwhatisbeingprofiledandhowdeeplyinthesystemdataisgatheredfrom.Theyare:

AddProfiler:Bydefault,theProfilershowsseveralofUnity’senginecomponentsintheTimelineView,buttheAddProfileroptioncanbeusedtoaddadditionalitems.

http://freepdf-books.com

Page 57: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SeetheTimelineViewsectionforacompletelistofcomponentswecanprofile.Record:EnablingthisoptionwillmaketheProfilercontinuouslyrecordprofilingdata.NotethatdatacanonlyberecordedifPlayModeisenabled(andnotpaused)orifProfileEditorisenabled.DeepProfile:OrdinaryprofilingwillonlyrecordthetimeandmemoryallocationsmadebyanyUnitycallbackmethods,suchasAwake(),Start(),Update(),FixedUpdate(),andsoon.EnablingDeepProfilerecompilesourscriptstomeasureeachandeveryinvokedmethod.Thiscausesanevengreaterinstrumentationcostduringruntimeandusessignificantlymorememorysincedataisbeingcollectedfortheentirecallstackatruntime.Asaconsequence,DeepProfilingmaynotevenbepossibleinlargeprojectsrunningonweakhardware,asUnitymayrunoutofmemorybeforetestingcanevenbegin!

TipNotethatDeepProfilingrequirestheprojecttoberecompiledbeforeprofilingcanbegin,soitisbesttoavoidtogglingtheoptionduringruntime.

Becausethisoptionmeasuresallmethodsacrossourcodebaseinablindfashion,itshouldnotbeenabledduringmostofourprofilingtests.Thisoptionisbestreservedforwhendefaultprofilingisnotprovidingenoughdetail,orinsmalltestScenes,whichareusedtoprofileasmallsubsetofgamefeatures.

IfDeepProfilingisrequiredforlargerprojectsandScenes,buttheDeepProfileoptionistoomuchofahindranceduringruntime,thentherearealternativesthatcanbefoundintheupcomingsectiontitledTargetedProfilingofcodesegments.

ProfileEditor:ThisoptionenablesEditorprofiling—thatis,gatheringprofilingdatafortheUnityEditoritself.ThisisusefulinordertoprofileanycustomEditorScriptswehavedeveloped.

TipNotethatActiveProfilermustbesettotheEditoroptionforthisfeaturetowork.

ActiveProfiler:Thisdrop-downgloballyofferschoicestoselectthetargetinstanceofUnitywewishtoprofile;this,aswe’velearned,canbethecurrentEditorapplication,alocalstandaloneinstanceofourapplication,oraninstanceofourapplicationrunningonaremotedevice.Clear:ThisclearsallprofilingdatafromtheTimelineView.FrameSelection:TheFramecountershowshowmanyframeshavebeenprofiled,andwhichframeiscurrentlyselectedintheTimelineView.Therearetwobuttonstomovethecurrentlyselectedframeforwardorbackwardbyoneframe,andathirdbutton(theCurrentbutton)thatresetstheselectedframetothemostrecentframeandkeepsthatposition.ThiswillcausetheBreakdownViewtoalwaysshowtheprofilingdataforthecurrentframeduringruntimeprofiling.TimelineView:TheTimelineViewrevealsprofilingdatathathasbeencollectedduringruntime,organizedbyareasdependingonwhichcomponentoftheenginewasinvolved.

http://freepdf-books.com

Page 58: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

EachAreahasmultiplecoloredboxesforvarioussubsectionsofthosecomponents.Thesecoloredboxescanbetoggledtoreveal/hidethecorrespondingdatatypeswithintheTimelineView.

EachAreafocusesonprofilingdataforadifferentcomponentoftheUnityengine.WhenanAreaisselectedintheTimelineView,essentialinformationforthatcomponentwillberevealedintheBreakdownViewforthecurrentlyselectedframe.

TheBreakdownViewshowsverydifferentinformation,dependingonwhichAreaiscurrentlyselected.

TipAreascanberemovedfromtheTimelineViewbyclickingonthe‘X‘atthetoprightofanArea.AreascanberestoredtotheTimelineViewthroughtheAddProfileroptionintheControlsbar.

CPUArea

ThisAreashowsCPUUsageformultipleUnitysubsystemsduringruntime,suchasMonoBehaviourcomponents,cameras,somerenderingandphysicsprocesses,userinterfaces(includingtheEditor’sinterface,ifwe’rerunningthroughtheEditor),audioprocessing,theProfileritself,andmore.

TherearethreewaysofdisplayingCPUUsagedataintheBreakdownView:

HierarchyRawHierarchyTimeline

TheHierarchyModegroupssimilardataelementsandglobalUnityfunctioncallstogetherforconvenience—forinstance,renderingdelimiters,suchasBeginGUI()andEndGUI()callsarecombinedtogetherinthisMode.

TheRawHierarchyModewillseparateglobalUnityfunctioncallsintoindividuallines.ThiswilltendtomaketheBreakdownViewmoredifficulttoread,butmaybehelpfulifwe’retryingtocounthowmanytimesaparticularglobalmethodhasbeeninvoked,ordeterminingifoneofthesecallsiscostingmoreCPU/memorythanexpected.Forexample,eachBeginGUI()andEndGUI()callwillbeseparatedintodifferententries,possiblyclutteringtheBreakdownView,makingitdifficulttoread.

Perhaps,themostusefulmodefortheCPUAreaistheTimelineModeoption(nottobeconfusedwiththemainTimelineView).ThisModeorganizesCPUusageduringthecurrentframebyhowthecallstackexpandedandcontractedduringprocessing.BlocksatthetopofthisviewweredirectlycalledbytheUnityEngine(suchastheStart(),Awake(),orUpdate()methods),whileblocksunderneaththemaremethodsthatthosemethodshadcalled,whichcanincludemethodsonotherComponentsorobjects.

Meanwhile,thewidthofagivenCPUTimelineBlockgivesustherelativetimeittooktoprocessthatmethodcomparedtootherblocksaroundit.Inaddition,methodcallsthatconsumerelativelylittleprocessingtime,relativetothemoregreedymethods,areshown

http://freepdf-books.com

Page 59: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

asgrayboxestokeepthemoutofsight.

ThedesignoftheCPUTimelineModeoffersaverycleanandorganizedwayofdeterminingwhichparticularmethodinthecallstackisconsumingthemosttime,andhowthatprocessingtimemeasuresupagainstothermethodsbeingcalledduringthesameframe.Thisallowsustogaugewhichmethodisthebiggestculpritwithminimaleffort.

Forexample,let’sassumethatwearelookingataperformanceprobleminthefollowingscreenshot.Wecantell,withaquickglance,thattherearethreemethodsthatarecausingaproblem,andtheyeachconsumesimilaramountsofprocessingtime,duetohavingsimilarwidths.

Inthisexample,thegoodnewsisthatwehavethreepossiblemethodsthroughwhichtofindperformanceimprovements,whichmeanslotsofopportunitiestofindcodethatcanbeimproved.Thebadnewsisthatincreasingtheperformanceofonemethodwillonlyimproveaboutone-thirdofthetotalprocessingforthatframe.Hence,allthreemethodswillneedtobeexaminedandimprovedinordertominimizetheamountofprocessingtimeduringthisframe.

TheCPUAreawillbemostusefulduringChapter2,ScriptingStrategies.

TheGPUArea

TheGPUAreaissimilartotheCPUArea,exceptthatitshowsmethodcallsandprocessingtimeasitoccursontheGPU.RelevantUnitymethodcallsinthisAreawillrelatetocameras,drawing,opaqueandtransparentgeometry,lightingandshadows,andsoon.

TheGPUAreawillbebeneficialduringChapter6,DynamicGraphics.

TheRenderingArea

TheRenderingAreaprovidesrenderingstatistics,suchasthenumberofSetPasscalls,thetotalnumberofBatchesusedtorenderthescene,thenumberofBatchessavedfromDynamicandStaticBatching,memoryconsumedforTextures,andsoon.

TheRenderingAreawillbeusefulinChapter3,TheBenefitsofBatching.

http://freepdf-books.com

Page 60: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheMemoryArea

TheMemoryAreaallowsustoinspectmemoryusageoftheapplicationintheBreakdownViewintwodifferentways:

SimpleModeDetailedMode

TheSimpleModeprovidesonlyahigh-leveloverviewofmemoryconsumptionofcomponentssuchasUnity’slow-levelEngine,theMonoframework(totalheapsizethatwillbegarbage-collected),Graphics,Audio(FMOD),andevenmemoryusedtostoredatacollectedbytheProfiler.

TheDetailedModeshowsmemoryconsumptionofindividualgameobjectsandcomponents,forboththeirnativeandmanagedrepresentations.Italsohasacolumnexplainingthereasonforthatobjectconsumingmemoryandwhenitmightbede-allocated.

TheMemoryAreawillbethemainfocalpointofChapter7,MasterfulMemoryManagement.

TheAudioArea

TheAudioAreagrantsanoverviewofaudiostatisticsandcanbeusedbothtomeasureCPUusagefromtheaudiosystem,aswellastotalmemoryconsumedbyAudioSources(forbothplayingandpausedsources)andAudioClips.

TheAudioAreawillcomeinhandyasweexploreartassetsinChapter4,KickstartYourArt.

TipAudioisoftenoverlookedwhenitcomestoperformanceenhancements,butaudiocanbecomeofthebiggestsourcesofbottlenecksifitisnotmanagedproperly.It’sworthperformingoccasionalchecksontheAudiosystem’smemoryandCPUconsumptionduringdevelopment.

ThePhysics3D/2DArea

TherearetwodifferentPhysicsAreas,onefor3Dphysics(Nvidia’sPhysX)andanotherforthe2Dphysicssystem(Box2D)thatwasintegratedintotheUnityEngineinversion4.5.ThisAreaprovidesvariousphysicsstatisticssuchasRigidbody,Collider,andContactcounts.

WewillbemakinguseofthisAreainChapter5,FasterPhysics.

NoteAsofthepublicationofthistext,withUnityv5.2.2f1asthemostrecentversion,thePhysics3DAreaonlyprovidesahandfulofitems,whilethePhysics2DAreaprovidessignificantlymoreinformation.

http://freepdf-books.com

Page 61: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 62: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

BestapproachestoperformanceanalysisGoodcodingpracticesandprojectassetmanagementoftenmakefindingtherootcauseofaperformanceissuerelativelysimple,atwhichpointtheonlyrealproblemisfiguringouthowtoimprovethecode.Forinstance,ifthemethodonlyprocessesasinglegiganticforloop,thenitwillbeaprettysafeassumptionthattheproblemiseitherwiththeiterationofthelooporhowmuchworkisprocessedeachiteration.

Ofcourse,alotofourcode,whetherwe’reworkingindividuallyorinagroupsetting,isnotalwayswritteninthecleanestwaypossible,andweshouldexpecttohavetoprofilesomepoorcodingworkfromtimetotime.Sometimes,hack-ysolutionsareinevitable,andwedon’talwayshavethetimetogobackandrefactoreverythingtokeepupwithourbestcodingpractices.

It’seasytooverlooktheobviouswhenproblemsolvingandperformanceoptimizationisjustanotherformofproblemsolving.ThegoalistouseProfilersanddataanalysistosearchourcodebaseforcluesaboutwhereaproblemoriginates,andhowsignificantitis.It’softenveryeasytogetdistractedbyinvaliddataorjumptoconclusionsbecausewe’rebeingtooimpatientormissedasubtleclue.Manyofushaverunintooccasions,duringsoftwaredebugging,wherewecouldhavefoundtherootcauseoftheproblemmuchfasterifwehadsimplychallengedandverifiedourearlierassumptions.Alwaysapproachingdebuggingunderthebeliefthattheproblemishighlycomplexandtechnicalisagoodwaytowastevaluabletimeandeffort.Performanceanalysisisnodifferent.

Achecklistoftaskswouldbehelpfultokeepusfocusedontheissue,andnotwastetimechasing“ghosts”.Everyprojectisdifferentandhasadifferentsetofconcernsanddesignparadigms,butthefollowingchecklistisgeneralenoughthatitshouldbeabletoapplytoanyUnityproject:

VerifyingthetargetScriptispresentintheSceneVerifyingtheScriptappearsintheScenethecorrectnumberoftimesMinimizingongoingcodechangesMinimizinginternaldistractionsMinimizingexternaldistractions

http://freepdf-books.com

Page 63: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

VerifyingscriptpresenceSometimestherearethingsweexpecttosee,butdon’t.Theseareusuallyeasytonote,becausethehumanbrainisverygoodatpatternrecognition.Ifsomethingdoesn’tmatchtheexpectedpattern,thenittendstobeveryobvious.Meanwhile,therearetimeswhereweassumesomethinghasbeenhappening,butitdidn’t.Thesearegenerallymoredifficulttonotice,becausewe’reoftenscanningforthefirstkindofproblem.Verificationoftheintendedorderofeventsiscritical,orweriskjumpingtoconclusions,wastingvaluabletime.

InthecontextofUnity,thismeansitisessentialtoverifythatthescriptweexpecttoseetheeventcomingfromisactuallypresentintheScene,andthatthemethodcallshappenintheorderweintended.

ScriptpresencecanbequicklyverifiedbytypingthefollowingintotheHierarchywindowtextbox:

t:<monobehaviourname>

Forexample,typingt:mytestmonobehaviour(note:itisnotcase-sensitive)intotheHierarchytextboxwillshowashortlistofallGameObjectsthatcurrentlyhaveaMyTestMonobehaviourscriptattachedasaComponent.

TipNotethatthisshortlistfeaturealsoincludesanyGameObjectswithComponentsthatderivefromthegivenscriptname.

http://freepdf-books.com

Page 64: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Weshouldalsodouble-checkthattheGameObjectstheyareattachedtoarestillenabled,sincewemayhavedisabledthemduringearliertesting,orsomeone/somethinghasaccidentallydeactivatedtheobject.

http://freepdf-books.com

Page 65: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

VerifyingscriptcountIfweassumethataMonoBehaviour,whichiscausingperformanceproblems,onlyappearsonceinourScene,thenwemayignorethepossibilitythatconflictingmethodinvocationsarecausingabottleneck.Thisisdangerous;whatifsomeonecreatedtheobjecttwiceormoreintheScenefile,orweaccidentallyinstantiatedtheobjectmorethanoncefromcode?WhatweseeintheProfilercanbeaconsequenceofthesameexpensivemethodbeinginvokedmorethanonceatthesametime.Thisissomethingwewillwanttodouble-checkusingthesameshortlistmethodasbefore.

IfweexpectedonlyoneoftheComponentstoappearintheScene,buttheshortlistrevealedmorethanone,thenwemaywishtorethinkourearlierassumptionsaboutwhat’scausingthebottlenecks.Wemaywishtowritesomeinitializationcodethatpreventsthisfromeverhappeningagain,and/orwritesomecustomEditorhelperstodisplaywarningstoanyleveldesignerswhomightbemakingthismistake.

Preventingcasualmistakeslikethisisessentialforgoodproductivity,sinceexperiencetellsusthat,ifwedon’texplicitlydisallowsomething,thensomeone,somewhere,atsomepoint,forwhateverreason,willdoitanyway,andcostusagooddealofanalysiswork.

http://freepdf-books.com

Page 66: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MinimizingongoingcodechangesMakingcodechangestotheapplicationinordertohuntdownperformanceissuesisnotrecommended,asthechangesareeasytoforgetastimewearson.Addingdebugloggingstatementstoourcodecanbetempting,butrememberthatitcostsustimetointroducethesecalls,recompileourcode,andremovethesecallsonceouranalysisiscomplete.Inaddition,ifweforgettoremovethem,thentheycancostunnecessaryruntimeoverheadinthefinalbuildsinceUnity’sDebugloggingcanbeprohibitivelyexpensiveinbothCPUandmemory.

Onewaytocombatthisproblemistouseasource-controltooltodifferentiatethecontentsofanymodifiedfiles,and/orrevertthembacktotheiroriginalstate.Thisisanexcellentwaytoensurethatunnecessarychangesdon’tmakeitintothefinalversion.

Makinguseofbreakpointsduringruntimedebuggingisthepreferredapproach,aswecantracethefullcallstack,variabledata,andconditionalcodepaths(forexample,if-elseblocks),withoutriskinganycodechangesorwastingtimeonrecompilation.

http://freepdf-books.com

Page 67: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MinimizinginternaldistractionsTheUnityEditorhasitsownlittlequirksandnuancesthatcanleaveusconfusedbycertainissues.

Firstly,ifasingleframetakesalongtimetoprocess,suchthatourgamenoticeablyfreezes,thentheProfilermaynotbecapableofpickinguptheresultsandrecordingthemintheProfilerwindow.Thiscanbeespeciallyannoyingifwewishtocatchdataduringapplication/Sceneinitialization.Theupcomingsection,CustomCPUProfiling,willoffersomealternativestoexploretosolvethisproblem.

Onecommonmistake(thatIhaveadmittedlyfallenvictimtomultipletimesduringthewritingofthisbook)is:ifwearetryingtoinitiateatestwithakeystrokeandwehavetheProfileropen,weshouldnotforgettoclickbackintotheEditor’sGamewindowbeforetriggeringthekeystroke!IftheProfileristhemostrecentlyclickedwindow,thentheEditorwillsendkeystrokeeventstothat,insteadoftheruntimeapplication,andhencenoGameObjectwillcatchtheeventforthatkeystroke.

VerticalSync(otherwiseknownasVSync)isusedtomatchtheapplication’sframeratetotheframerateofthedeviceitisbeingdisplayedon(forexample,themonitor).ExecutingtheProfilerwiththisfeatureenabledwillgeneratealotofspikesintheCPUusageareaundertheheadingWaitForTargetFPS,astheapplicationintentionallyslowsitselfdowntomatchtheframerateofthedisplay.Thiswillgenerateunnecessaryclutter,makingithardertospottherealissue(s).WeshouldmakesuretodisabletheVSynccoloredboxundertheCPUAreawhenwe’reonthelookoutforCPUspikesduringperformancetests.WecandisabletheVSyncfeatureentirelybynavigatingtoEdit|ProjectSettings|Qualityandthenthesubpageforthecurrentlyselectedbuildplatform.

Weshouldalsoensurethatadropinperformanceisn’tadirectresultofamassivenumberofexceptionsanderrormessagesappearingintheEditorconsole.Unity’sDebug.Log(),andsimilarmethodssuchasDebug.LogError(),Debug.LogWarning(),andsoon,arenotoriouslyexpensiveintermsofCPUusageandheapmemoryconsumption,whichcanthencausegarbagecollectiontooccurandevenmorelostCPUcycles.

ThisoverheadisusuallyunnoticeabletoahumanbeinglookingattheprojectinEditorMode,wheremosterrorscomefromthecompilerormisconfiguredobjects.Buttheycanbeproblematicwhenusedduringanykindofruntimeprocess;especiallyduringprofiling,wherewewishtoobservehowthegamerunsintheabsenceofexternaldisruptions.Forexample,ifwearemissinganobjectreferencethatweweresupposedtoassignthroughtheEditoranditisbeingusedinanUpdate()method,thenasingleMonoBehaviourcouldbethrowingnewexceptionseverysingleupdate.Thisaddslotsofunnecessarynoisetoourprofilingdata.

NotethatwecandisabletheInfoorWarningcheckboxes(showninthefollowingscreenshot)fortheprojectduringPlayModeruntime,butitstillcostsCPUandmemorytoexecutedebugstatements,eventhoughtheyarenotbeingrendered.Itisoftenagoodpracticetokeepalloftheseoptionsenabled,toverifythatwe’renotmissinganythingimportant.

http://freepdf-books.com

Page 68: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 69: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MinimizingexternaldistractionsThisoneissimplebutabsolutelynecessary.Weshoulddouble-checkthattherearenobackgroundprocesseseatingawayCPUcyclesorconsumingvastswathesofmemory.Beinglowonavailablememorywillgenerallyinterferewithourtesting,asitcancausemorecachemisses,hard-driveaccessforvirtualmemorypage-fileswapping,andgenerallyslowresponsivenessoftheapplication.

http://freepdf-books.com

Page 70: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 71: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TargetedprofilingofcodesegmentsIfourperformanceproblemisn’tsolvedbytheabovechecklist,thenweprobablyhavearealissueonourhandsthatdemandsfurtheranalysis.Thetaskoffiguringoutexactlywheretheproblemislocatedstillremains.TheProfilerwindowiseffectiveatshowingusabroadoverviewofperformance;itcanhelpusfindspecificframestoinvestigateandcanquicklyinformuswhichMonoBehaviourand/ormethodmaybecausingissues.However,wemuststilldetermineexactlywheretheproblemexists.Weneedtofigureoutiftheproblemisreproducible,underwhatcircumstancesaperformancebottleneckarises,andwhereexactlywithintheproblematiccodeblocktheissueisoriginatingfrom.

Toaccomplishthese,wewillneedtoperformsomeprofilingoftargetedsectionsofourcode,andthereareahandfulofusefultechniqueswecanemployforthistask.ForUnityprojects,theyessentiallyfitintotwocategories:

ControllingtheProfilerfromscriptcodeCustomtimingandloggingmethods

NoteNotethatthefollowingsectionmostlyfocussesonhowtoinvestigateScriptingbottlenecksthroughC#code.Detectingthesourceofbottlenecksinotherenginecomponentswillbediscussedintheirrelatedchapters.

http://freepdf-books.com

Page 72: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ProfilerscriptcontrolTheProfilercanbecontrolledinscriptcodethroughthestaticProfilerclass.ThereareseveralusefulmethodsintheProfilerclassthatwecanexplorewithintheUnitydocumentation,butthemostimportantmethodsarethedelimitermethodsthatactivateanddeactivateprofilingatruntime:Profiler.BeginSample()andProfiler.EndSample().

TipNotethatthedelimitermethods,BeginSample()andEndSample(),areonlycompiledindevelopmentbuilds,andassuchtheycausenooverheadinthefinalbuild.Therefore,itissafetoleavetheminourcodebaseifwewishtousethemforprofilingtestsatalaterdate.

TheBeginSample()methodhasanoverloadthatallowsacustomnameforthesampletoappearintheCPUUsageArea’sHierarchyModeview.Forexample,thefollowingcodewillprofileinvocationsofthismethodandmakethedataappearintheBreakdownViewunderacustomheading:

voidDoSomethingCompletelyStupid(){

Profiler.BeginSample("MyProfilerSample");

List<int>listOfInts=newList<int>();

for(inti=0;i<1000000;++i){

listOfInts.Add(i);

}

Profiler.EndSample();

}

TipDownloadingtheexamplecode

Youcandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.

Weshouldexpectthatinvokingthispoorlydesignedmethod(itgeneratesalistcontainingamillionintegers,andthendoesabsolutelynothingwithit)willcauseahugespikeinCPUusage,chewupseveralMegabytesofmemory,andappearintheProfilerBreakdownViewundertheheadingMyProfilerSampleasthefollowingscreenshotshows:

http://freepdf-books.com

Page 73: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

NotethatthesecustomsamplenamesdonotappearattherootofthehierarchywhenweperformDeepProfiling.ThefollowingscreenshotshowstheBreakdownViewforthesamecodeunderDeepProfiling:

Notehowthecustomnameforthesampledoesnotappearatthetopofthesample,wherewemayexpectitto.It’sunclearwhatcausesthisphenomenon,butthiscancausesomeconfusionwhenexaminingtheDeepProfilingdatawithinHierarchyMode,soitisgoodtobeawareofit.

http://freepdf-books.com

Page 74: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CustomCPUProfilingTheProfilerisjustonetoolatourdisposal.Sometimes,wemaywanttoperformcustomizedprofilingandloggingofourcode.Maybewe’renotconfidenttheUnityProfilerisgivingustherightanswer,maybeweconsideritsoverheadcosttoogreat,ormaybewejustlikehavingcompletecontrolofeverysingleaspectofourapplication.Whateverourmotivations,knowingsometechniquestoperformanindependentanalysisofourcodeisausefulskilltohave.It’sunlikelywe’llonlybeworkingwithUnityfortheentiretyofourgamedevelopmentcareers,afterall.

Profilingtoolsareverycomplex,soit’sunlikelywewouldbeabletogenerateacomparablesolutiononourownwithinareasonabletimeframe.WhenitcomestotestingCPUusage,allweneedisanaccuratetimingsystem,afast,low-costwayofloggingthatinformation,andsomepieceofcodetotestagainst.Itjustsohappensthatthe.NETlibrary(or,technically,theMonoframework)comeswithaStopwatchclassundertheSystem.Diagnosticsnamespace.WecanstopandstartaStopwatchobjectatanytime,andwecaneasilyacquireameasureofhowmuchtimehaspassedsincetheStopwatchwasstarted.

Unfortunately,thisclassisnotveryaccurate—itisaccurateonlytomilliseconds,ortenthsofamillisecondatbest.Countinghigh-precisionrealtimewithaCPUclockcanbeasurprisinglydifficulttaskwhenwestarttogetintoit;so,inordertoavoidadetaileddiscussionofthetopic,weshouldtrytofindawayfortheStopwatchclasstosatisfyourneeds.

Beforewegetobsessedwiththetopicofhighprecision,weshouldfirstaskourselvesifweevenneedit.Mostgamesexpecttorunat30FPS(frames-per-second)or60FPS,whichmeanstheyonlyhavearound33msor16ms,respectively,tocomputeeverythingfortheentireframe.So,hypothetically,ifweonlyneedtobringtheperformanceofaparticularcodeblockunder10ms,thenrepeatingthetestthousandsoftimestogetmicrosecondprecisionwouldn’treallytellusanythinguseful.

However,ifprecisionisimportant,thenoneeffectivewaytoincreaseitisbyrunningthesametestmultipletimes.Assumingthatthetestcodeblockisbotheasilyrepeatableandnotexceptionallylong,thenweshouldbeabletorunthousands,orevenmillions,oftestswithinareasonabletimeframeandthendividethetotalelapsedtimebythenumberoftestswejustperformedtogetamoreaccuratetimeforasingletest.

ThefollowingisaclassdefinitionforacustomtimerthatusesaStopwatchtocounttimeforagivennumberoftests:

usingUnityEngine;

usingSystem;

usingSystem.Diagnostics;

usingSystem.Collections;

publicclassCustomTimer:IDisposable{

privatestringm_timerName;

privateintm_numTests;

http://freepdf-books.com

Page 75: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

privateStopwatchm_watch;

//givethetimeraname,andacountofthenumberoftestswe're

running

publicCustomTimer(stringtimerName,intnumTests){

m_timerName=timerName;

m_numTests=numTests;

if(m_numTests<=0)

m_numTests=1;

m_watch=Stopwatch.StartNew();

}

//calledwhenthe'using'blockends

publicvoidDispose(){

m_watch.Stop();

floatms=m_watch.ElapsedMilliseconds;

UnityEngine.Debug.Log(string.Format("{0}finished:{1:0.00}mstotal,

{2:0.000000}mspertestfor{3}tests",m_timerName,ms,ms/m_numTests,

m_numTests));

}

}

ThefollowingisanexampleoftheCustomTimerclassusage:

intnumTests=1000;

using(newCustomTimer("MyTest",numTests)){

for(inti=0;i<numTests;++i){

TestFunction();

}

}//thetimer'sDispose()methodisautomaticallycalledhere

Therearethreethingstonotewhenusingthisapproach.Firstly,weareonlymakinganaverageofmultiplemethodinvocations.Ifprocessingtimevariesenormouslybetweeninvocations,thenthatwillnotbewell-representedinthefinalaverage.Secondly,ifmemoryaccessiscommon,thenrepeatedlyrequestingthesameblocksofmemorywillresultinanartificiallyhighercachehitrate,whichwillbringtheaveragetimedownwhencomparedtoatypicalinvocation.Thirdly,theeffectsofJITcompilationwillbeeffectivelyhiddenforsimilarlyartificialreasonsasitonlyaffectsthefirstinvocationofthemethod.JITcompilationissomethingthatwillbecoveredinmoredetailinChapter7,MasterfulMemoryManagement.

Theusingblockistypicallyusedtosafelyensurethatunmanagedresourcesareproperlydestroyedwhentheygooutofscope.Whentheusingblockends,itwillautomaticallyinvoketheobject’sDispose()methodtohandleanycleanupoperations.Inordertoachievethis,theobjectmustimplementtheIDisposableinterface,whichforcesittodefinetheDispose()method.

However,thesamelanguagefeaturecanbeusedtocreateadistinctcodeblock,whichcreatesashort-termobject,whichthenautomaticallyprocessessomethingusefulwhenthecodeblockends.

Note

http://freepdf-books.com

Page 76: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Notethattheusingblockshouldnotbeconfusedwiththeusingstatement,whichisusedatthestartofascriptfiletopullinadditionalnamespaces.It’sextremelyironicthatthekeywordformanagingnamespacesinC#hasanamingconflictwithanotherkeyword.

Asaresult,theusingblockandtheCustomTimerclassgiveusacleanwayofwrappingourtargettestcodeinawaywhichmakesitobviouswhenandwhereitisbeingused.

Anotherconcerntoworryaboutisapplicationwarmup.UnityhasasignificantstartupcostwhenaScenebegins,giventhenumberofcallstovariousGameObjects’Awake()andStart()methods,aswellasinitializationofothercomponentssuchasthePhysicsandRenderingsystems.Thisearlyoverheadmightonlylastasecond,butthatcanhaveasignificanteffectontheresultsofourtesting.Thismakesitcrucialthatanyruntimetestingbeginsaftertheapplicationhasreachedasteadystate.

Ifpossible,itwouldbewisetowrapthetargetcodeblockinanInput.GetKeyDown()methodcheckinordertohavecontroloverwhenitisinvoked.Forexample,thefollowingcodewillonlyexecuteourtestmethodwhentheSpaceBarispressed:

if(Input.GetKeyDown(KeyCode.Space)){

intnumTests=1000;

using(newCustomTimer("ControlledTest",numTests)){

for(inti=0;i<numTests;++i){

TestFunction();

}

}

}

TherearethreeimportantdesignfeaturesoftheCustomTimerclass:itonlyprintsasinglelogmessagefortheentiretest,onlyreadsthevaluefromtheStopwatchafterithasbeenstopped,andusesstring.Format()forgeneratingacustomstring.

Asexplainedearlier,Unity’sconsoleloggingmechanismisprohibitivelyexpensive.Asaresult,weshouldneverusetheseloggingmethodsinthemiddleofaprofilingtest(orevengameplay,forthatmatter).Ifwefindourselvesabsolutelyneedingdetailedprofilingdatathatprintsoutlotsofindividualmessages(suchasperformingatimingtestoneachiterationofaloop,tofindwhichiterationiscostingmoretimethantherest),thenitwouldbewisertocachetheloggingdataandprintitallattheend,astheCustomTimerclassdoes.Thiswillreduceruntimeoverhead,atthecostofsomememoryconsumption.ThealternativeisthatmanymillisecondsarelosttoprintingeachDebug.Log()messageinthemiddleofthetest,whichpollutestheresults.

ThesecondfeatureisthattheStopwatchisstoppedbeforethevalueisread.Thisisfairlyobvious;readingthevaluewhileitisstillcountingmightgiveusaslightlydifferentvaluethanstoppingitfirst.UnlesswedivedeepintotheMonoprojectsourcecode(andthespecificversionUnityuses),wemightnotknowtheexactimplementationofhowStopwatchcountstime,atwhatpointsCPUticksarecounted,andatwhatmomentsanyapplicationcontextswitchingistriggeredbytheOS.So,itisoftenbettertoerronthesideofcautionandpreventanymorecountingbeforeweattempttoaccessthevalue.

http://freepdf-books.com

Page 77: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Finally,there’stheusageofstring.Format().ThiswillbecoveredinmoredetailinChapter7,MasterfulMemoryManagement,buttheshortexplanationisthatthismethodisusedbecausegeneratingcustomstringsusingthe+operatorresultsinasurprisinglylargeamountofmemoryconsumption,whichattractstheattentionofthegarbagecollector.Thiswouldconflictwithourgoalofachievingaccuratetimingandanalysis.

http://freepdf-books.com

Page 78: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 79: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SavingandloadingProfilerdataTheUnityProfilercurrentlyhasafewfairlysignificantpitfallswhenitcomestosavingandloadingProfilerdata:

Only300framesarevisibleintheProfilerwindowatonceThereisnowaytosaveProfilerdatathroughtheuserinterfaceProfilerbinarydatacanbesavedintoafiletheScriptcode,butthereisnobuilt-inwaytoviewthisdata

Theseissuesmakeitverytrickytoperformlarge-scaleorlong-termtestingwiththeUnityProfiler.TheyhavebeenraisedinUnity’sIssueTrackertoolforseveralyears,andtheredoesn’tappeartobeanysalvationinsight.So,wemustrelyonourowningenuitytosolvethisproblem.

Fortunately,theProfilerclassexposesafewmethodsthatwecanusetocontrolhowtheProfilerlogsinformation:

1. TheProfiler.enabledmethodcanbeusedtoenable/disabletheProfiler,whichistheequivalentofclickingontheRecordbuttonintheControlViewoftheProfiler.

NoteNotethatchangingProfiler.enableddoesnotchangethevisiblestateoftheRecordbuttonintheProfiler’sControlsbar.Thiswillcausesomeconfusingconflictsifwe’recontrollingtheProfilerthroughbothcodeandtheuserinterfaceatthesametime.

2. TheProfiler.logFilemethodsetsthecurrentpathofthelogfilethattheProfilerprintsdataoutto.Beawarethatthisfileonlycontainsaprintoutoftheapplication’sframerateovertime,andnoneoftheusefuldatawenormallyfindintheProfiler’sTimelineView.Tosavethatkindofdataasabinaryfile,wemustusetheoptionsthatfollow.

3. TheProfiler.enableBinaryLogmethodwillenable/disableloggingofanadditionalfilefilledwithbinarydata,whichincludesalloftheimportantvalueswewanttosavefromtheTimelineandBreakdownViews.ThefilelocationandnamewillbethesameasthevalueofProfiler.logFile,butwith.dataappendedtotheend.

Withthesemethods,wecangenerateasimpledata-savingtoolthatwillgeneratelargeamountsofProfilerdataseparatedintomultiplefiles.Withthesefiles,wewillbeabletoperusethematalaterdate.

http://freepdf-books.com

Page 80: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SavingProfilerdataInordertocreateatoolthatcansaveourProfilerdata,wecanmakeuseofaCoroutine.Atypicalmethodwillbeexecutedfrombeginningtoendinonesitting.However,Coroutinesareusefulconstructsthatallowuswritemethodsthatcanpauseexecutionuntilalatertime,oraneventtakesplace.Thisisknownasyielding,andisaccomplishedwiththeyieldstatement.Thetypeofyielddetermineswhenexecutionwillresume,whichcouldbeoneofthefollowingtypes(theobjectthatmustbepassedintotheyieldstatementisalsogiven):

Afteraspecificamountoftime(WaitForSeconds)AfterthenextUpdate(WaitForEndOfFrame)AfterthenextFixedUpdate(WaitForFixedUpdate)JustpriortothenextLateUpdate(null)AfteraWWWobjectcompletesitscurrenttask,suchasdownloadingafile(WWW)AfteranotherCoroutinehasfinished(areferencetoanotherCoroutine)

TheUnityDocumentationonCoroutinesandExecutionOrderprovidesmoreinformationonhowtheseusefultoolsfunctionwithintheUnityEngine:

http://docs.unity3d.com/Manual/Coroutines.htmlhttp://docs.unity3d.com/Manual/ExecutionOrder.html

TipCoroutinesshouldnotbeconfusedwiththreads,whichexecuteindependentlyofthemainUnitythread.Coroutinesalwaysrunonthemainthreadwiththerestofourcode,andsimplypauseandresumeatcertainmoments,dependingontheobjectpassedintotheyieldstatement.

Gettingbacktothetaskathand,thefollowingistheclassdefinitionforourProfilerDataSaverComponent,whichmakesuseofaCoroutinetorepeatanactionevery300frames:

usingUnityEngine;

usingSystem.Text;

usingSystem.Collections;

publicclassProfilerDataSaverComponent:MonoBehaviour{

int_count=0;

voidStart(){

Profiler.logFile="";

}

voidUpdate(){

if(Input.GetKey(KeyCode.LeftControl)&&Input.GetKeyDown(KeyCode.H))

{

StopAllCoroutines();

_count=0;

StartCoroutine(SaveProfilerData());

http://freepdf-books.com

Page 81: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

}

IEnumeratorSaveProfilerData(){

//keepcallingthismethoduntilPlayModestops

while(true){

//generatethefilepath

stringfilepath=Application.persistentDataPath+"/profilerLog"+

_count;

//setthelogfileandenabletheprofiler

Profiler.logFile=filepath;

Profiler.enableBinaryLog=true;

Profiler.enabled=true;

//count300frames

for(inti=0;i<300;++i){

yieldreturnnewWaitForEndOfFrame();

//workaroundtokeeptheProfilerworking

if(!Profiler.enabled)

Profiler.enabled=true;

}

//startagainusingthenextfilename

_count++;

}

}

}

TryattachingthisComponenttoanyGameObjectintheScene,andpressCtrl+H(OSXuserswillwanttoreplacetheKeyCode.LeftControlcodewithsomethingsuchasKeyCode.LeftCommand).TheProfilerwillstartgatheringinformation(whetherornottheProfilerWindowisopen!)and,usingasimpleCoroutine,willpumpthedataoutintoaseriesoffilesunderwhereverApplication.persistantDataPathispointingto.

TipNotethatthelocationofApplication.persistantDataPathvariesdependingontheOperatingSystem.ChecktheUnityDocumentationformoredetailsathttp://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html.

ItwouldbeunwisetosendthefilestoApplication.dataPath,asitwouldputthemwithintheProjectWorkspace.TheProfilerdoesnotreleasethemostrecentlogfilehandleifwestoptheProfilerorevenwhenPlayModeisstopped.Consequently,asfilesaregeneratedandplacedintotheProjectworkspace,therewouldbeaconflictinfileaccessibilitybetweentheUnityEditortryingtoreadandgeneratecomplementarymetadatafiles,andtheProfilerkeepingafilehandletothemostrecentlogfile.Thiswouldresultinsomenastyfileaccesserrors,whichtendtocrashtheUnityEditorandloseanyScenechangeswe’vemade.

http://freepdf-books.com

Page 82: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

WhenthisComponentisrecordingdata,therewillbeasmalloverheadinharddiskusageandtheoverheadcostofIEnumeratorcontextswitchingevery300frames,whichwilltendtoappearatthestartofeveryfileandconsumeafewmillisecondsofCPU(dependingonhardware).

Eachfilepairshouldcontain300framesworthofProfilerdata,whichskirtsaroundthe300framelimitintheProfilerwindow.AllweneednowisawayofpresentingthedataintheProfilerwindow.

HereisascreenshotofdatafilesthathavebeengeneratedbyProfilerDataSaverComponent:

NoteNotethatthefirstfilemaycontainlessthan300framesifsomeframeswerelostduringProfilerwarmup.

http://freepdf-books.com

Page 83: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LoadingProfilerdataTheProfiler.AddFramesFromFile()methodwillloadagivenprofilerlogfilepair(thetextandbinaryfiles)andappenditintotheProfilertimeline,pushingexistingdatafurtherbackintime.Sinceeachfilewillcontain300frames,thisisperfectforourneeds,andwejustneedtocreateasimpleEditorWindowclassthatcanprovidealistofbuttonstoloadthefilesintotheProfiler.

TipNotethatAddFramesFromFile()onlyrequiresthenameoftheoriginallogfile.Itwillautomaticallyfindthecomplimentarybinary.datafileonitsown.

ThefollowingistheclassdefinitionforourProfilerDataLoaderWindow:

usingUnityEngine;

usingUnityEditor;

usingSystem.IO;

usingSystem.Collections;

usingSystem.Collections.Generic;

usingSystem.Text.RegularExpressions;

publicclassProfilerDataLoaderWindow:EditorWindow{

staticList<string>s_cachedFilePaths;

staticints_chosenIndex=-1;

[MenuItem("Window/ProfilerDataLoader")]

staticvoidInit(){

ProfilerDataLoaderWindowwindow=

(ProfilerDataLoaderWindow)EditorWindow.GetWindow

(typeof(ProfilerDataLoaderWindow));

window.Show();

ReadProfilerDataFiles();

}

staticvoidReadProfilerDataFiles(){

//makesuretheprofilerreleasesthefilehandle

//toanyofthefileswe'reabouttoloadin

Profiler.logFile="";

string[]filePaths=Directory.GetFiles

(Application.persistentDataPath,"profilerLog*");

s_cachedFilePaths=newList<string>();

//wewanttoignoreallofthebinary

//filesthatendin.data.TheProfiler

//willfigurethatpartout

Regextest=newRegex(".data$");

for(inti=0;i<filePaths.Length;i++){

stringthisPath=filePaths[i];

http://freepdf-books.com

Page 84: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Matchmatch=test.Match(thisPath);

if(!match.Success){

//notabinaryfile,addittothelist

Debug.Log("Foundfile:"+thisPath);

s_cachedFilePaths.Add(thisPath);

}

}

s_chosenIndex=-1;

}

voidOnGUI(){

if(GUILayout.Button("FindFiles")){

ReadProfilerDataFiles();

}

if(s_cachedFilePaths==null)

return;

EditorGUILayout.Space();

EditorGUILayout.LabelField("Files");

EditorGUILayout.BeginHorizontal();

//createsomestylestoorganizethebuttons,andshow

//themostrecently-selectedbuttonwithredtext

GUIStyledefaultStyle=newGUIStyle(GUI.skin.button);

defaultStyle.fixedWidth=40f;

GUIStylehighlightedStyle=newGUIStyle(defaultStyle);

highlightedStyle.normal.textColor=Color.red;

for(inti=0;i<s_cachedFilePaths.Count;++i){

//list5itemsperrow

if(i%5==0){

EditorGUILayout.EndHorizontal();

EditorGUILayout.BeginHorizontal();

}

GUIStylethisStyle=null;

if(s_chosenIndex==i){

thisStyle=highlightedStyle;

}else{

thisStyle=defaultStyle;

}

if(GUILayout.Button(""+i,thisStyle)){

Profiler.AddFramesFromFile(s_cachedFilePaths[i]);

s_chosenIndex=i;

}

http://freepdf-books.com

Page 85: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

EditorGUILayout.EndHorizontal();

}

}

ThefirststepincreatinganycustomEditorWindowiscreatingamenuentrypointwitha[MenuItem]attributeandthencreatinganinstanceofaWindowobjecttocontrol.BothoftheseoccurwithintheInit()method.

We’realsocallingtheReadProfilerDataFiles()methodduringinitialization.ThismethodreadsallfilesfoundwithintheApplication.persistantDataPathfolder(thesamelocationourProfilerDataSaverComponentsavesdatafilesto)andaddsthemtoacacheoffilenamestouselater.

Finally,thereistheOnGUI()method.Thismethoddoesthebulkofthework.Itprovidesabuttontoreloadthefilesifneeded,verifiesthatthecachedfilenameshavebeenread,andprovidesaseriesofbuttonstoloadeachfileintotheProfiler.ItalsohighlightsthemostrecentlyclickedbuttonwithredtextusingacustomGUIStyle,makingiteasytoseewhichfile’scontentsarevisibleintheProfileratthecurrentmoment.

TheProfilerDataLoaderWindowcanbeaccessedbynavigatingtoWindow|ProfilerDataLoaderintheEditorinterface,asshowinthefollowingscreenshot:

Hereisascreenshotofthedisplaywithmultiplefilesavailabletobeloaded.ClickingonanyofthenumberedbuttonswillpushtheProfilerdatacontentsofthatfileintotheProfiler.

http://freepdf-books.com

Page 86: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheProfilerDataSaverComponentandProfilerDataLoaderWindowdonotpretendtobeexhaustiveorfeature-rich.Theysimplyserveasaspringboardtogetusstartedifwewishtotakethesubjectfurther.Formostteamsandprojects,300framesworthofshort-termdataisenoughfordeveloperstoacquirewhattheyneedtobeginmakingcodechangestofixtheproblem.

http://freepdf-books.com

Page 87: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 88: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

FinalthoughtsonProfilingandAnalysisOnewayofdescribingperformanceoptimizationis“theactofstrippingawayunnecessarytasksthatspendvaluableresources”.Wecandothesameandmaximizeourownproductivitythroughminimizingwastedeffort.Effectiveuseofthetoolswehaveatourdisposalisofparamountimportance.Itwouldserveuswelltooptimizeourownworkflowbykeepingawareofsomebestpracticesandtechniques.

Most,ifnotall,adviceforusinganykindofdata-gatheringtoolproperlycanbesummarizedintothreedifferentstrategies:

UnderstandingthetoolReducingnoiseFocusingontheissue

http://freepdf-books.com

Page 89: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UnderstandingtheProfilerTheProfilerisanarguablywell-designedandintuitivetool,sounderstandingthemajorityofitsfeaturesetcanbegainedbysimplyspendinganhourortwoexploringitsoptionswithatestprojectandreadingitsdocumentation.Themoreweknowaboutourtoolintermsofitsbenefits,pitfalls,features,andlimitations,themoresensewecanmakeoftheinformationitisgivingus,soitisworthspendingthetimetouseitinaplaygroundsetting.Wedon’twanttobetwoweeksawayfromrelease,withahundredperformancedefectstofix,withnoideahowtodoperformanceanalysisefficiently!

Forexample,alwaysremainawareoftherelativenatureoftheTimelineView’sgraphicaldisplay.JustbecauseaspikeorrestingstateintheTimelineseemslargeandthreatening,doesnotnecessarilymeanthereisaperformanceissue.BecausetheTimelineViewdoesnotprovidevaluesonitsverticalaxis,andautomaticallyreadjuststhisaxisbasedonthecontentofthelast300frames,itcanmakesmallspikesappeartobeabiggerproblemthantheyreallyare.SeveralareasintheTimelineprovidehelpfulbenchmarkbars,givingaglimpseofhowtheapplicationwasperformingatthatmoment.Theseshouldbeusedtodeterminethemagnitudeoftheproblem.Don’tlettheProfilertrickusintothinkingthatbigspikesarealwaysbad.Asalways,it’sonlyimportantiftheuserwillnoticeit!

Asanexample,ifalargeCPUusagespikedoesnotexceedthe60FPSor30FPSbenchmarkbars(dependingontheapplication’stargetframerate),thenitwouldbewisetoignoreitandsearchelsewhereforCPUperformanceissues,asnomatterhowmuchweimprovetheoffendingpieceofcodeitwillprobablyneverbenoticedbytheenduser,andisn’tacriticalissuethataffectsproductquality.

http://freepdf-books.com

Page 90: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ReducingnoiseTheclassicaldefinitionofnoiseincomputerscienceismeaninglessdata,andabatchofprofilingdatathatwasblindlycapturedwithnospecifictargetinmindisalwaysfullofdatawhichwon’tinterestus.Moredatatakesmoretimetomentallyprocessandfilter,whichcanbeverydistracting.Oneofthebestmethodstoavoidthisittosimplyreducetheamountofdataweneedtoprocess,bystrippingawayanydatadeemednonvitaltothecurrentsituation.

ReducingclutterintheProfiler’sgraphicalinterfacewillmakeiteasiertodeterminewhichcomponentiscausingaspikeinresourceusage.RemembertousethecoloredboxesineachTimelineareatonarrowthesearch.However,thesesettingsareautosavedintheEditor,sobesuretore-enablethemforthenextprofilingsessionasthismightcauseustomisssomethingimportantnexttime!

Also,GameObjectscanbedeactivatedtopreventthemfromgeneratingprofilingdata,whichwillalsohelpreduceclutterinourprofilingdata.Thiswillnaturallycauseaslightperformanceboostforeachobjectwedeactivate.But,ifwe’regraduallydeactivatingobjectsandperformancesuddenlybecomessignificantlymoreacceptablewhenaspecificobjectisdeactivated,thenclearlythatobjectisrelatedtotherootcauseoftheproblem.

http://freepdf-books.com

Page 91: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

FocusingontheissueThiscategorymayseemredundant,giventhatwe’vealreadycoveredreducingnoise.Allweshouldhaveleftistheissueathand,right?Notexactly.Focusistheskillofnotlettingourselvesbecomedistractedbyinconsequentialtasksandwildgoosechases.

RecallthatprofilingwiththeUnityProfilercomeswithaminorperformancecost.ThiscostisevenmoreseverewhenusingtheDeepProfilingoption.Wemightevenintroducemoreminorperformancecostsintoourapplicationwithadditionalloggingandsoon.It’seasytoforgetwhenandwhereweintroducedprofilingcodeifthehuntcontinuesforseveralhours.

Weareeffectivelychangingtheresultbymeasuringit.Anychangesweimplementduringdatasamplingcansometimesleadustochaseafternonexistentbugsintheapplication,whenwecouldhavesavedourselvesalotoftimebyattemptingtoreplicatethescenarioundernon-profilingconditions.Ifthebottleneckisreproducibleandnoticeablewithoutprofiling,thenit’sacandidatetobeginaninvestigation.Butifnewbottleneckskeepappearinginthemiddleofanexistinginvestigation,thenkeepinmindthattheycouldsimplybebottleneckswerecentlyintroducedwithtestcode,andnotsomethingthat’sbeennewlyexposed.

Finally,whenwehavefinishedprofiling,havecompletedourfixes,andarenowreadytomoveontothenextinvestigation,weshouldmakesuretoprofiletheapplicationonelasttimetoverifythatthechangeshavehadtheintendedeffect.

http://freepdf-books.com

Page 92: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 93: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryYoulearnedagreatdealthroughoutthischapteronhowtodetectperformanceissueswithinyourapplication.YoulearnedaboutmanyoftheProfiler’sfeaturesandsecrets,youexploredavarietyoftacticstoinvestigateperformanceissueswithamorehands-on-approach,andyou’vebeenintroducedtoavarietyofdifferenttipsandstrategiestofollow.Youcanusethesetoimproveyourproductivityimmensely,solongasyouappreciatethewisdombehindthemandremembertoexploitthemwhenthesituationmakesitpossible.

Thischapterhasintroducedustothetips,tactics,andstrategiesweneedfindaperformanceproblemthatneedsimprovement.Duringtheremainingchapters,wewillexploremethodsonhowtofixissues,andimproveperformancewheneverpossible.So,giveyourselfapatonthebackforgettingthroughtheboringpartfirst,andlet’smoveontolearningsomestrategiestoimproveourC#scriptingpractices.

http://freepdf-books.com

Page 94: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 95: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter2.ScriptingStrategiesSincescriptingwillconsumeagreatdealofourdevelopmenttime,itwillbeenormouslybeneficialtolearnsomebestpractices.Scriptingisaverybroadterm,sowewilltrytolimitourexposureinthischaptertosituationsthatareveryUnityspecific,focusingonproblemsarisingfromwithintheUnityAPIsandenginedesign.WewilldiscussthenuancesandadvancedtopicsoftheC#language,.NETlibrary,andMonoFramework,inChapter7,MasterfulMemoryManagement.

Whetheryouhavesomespecificproblemsinmindthatyouwishtosolveoryoujustwanttolearnsometechniquesforfuturereference,thischapterwillintroduceyoutoanarrayofmethodsthatyoucanusetoimproveyourscriptingeffortsnowandinthefuture.Ineachcase,wewillexplorehowandwhytheperformanceissuearises,anexamplesituationinwhichtheproblemisoccurring,andoneormoresolutionstocombattheissue.

http://freepdf-books.com

Page 96: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CacheComponentreferencesAcommonmistakewhenscriptinginUnityistooverusetheGetComponent()method.Forexample,thefollowingscriptcodeistryingtocheckacreature’shealthvalue,andifitshealthgoesbelow0,disableaseriesofComponentstoprepareitforadeathanimation:

voidTakeDamage(){

if(GetComponent<HealthComponent>().health<0){

GetComponent<Rigidbody>().enabled=false;

GetComponent<Collider>().enabled=false;

GetComponent<AIControllerComponent>().enabled=false;

GetComponent<Animator>().SetTrigger("death");

}

}

Eachtimethismethodexecutes,itwillreacquirefivedifferentComponentreferences.Thisisgoodintermsofheapmemoryconsumption(inthatitdoesn’tcostany),butitisnotveryfriendlyonCPUusage.ThisisparticularlyproblematicifthemainmethodwerecalledduringUpdate().Evenifitisnot,itstillmightcoincidewithotherimportantevents,suchascreatingparticleeffects,replacinganobjectwitharagdoll(thusinvokingvariousactivityinthephysicsengine),andsoon.Thiscodingstylecanseemharmless,butitcancausealotoflong-termproblemsandruntimeworkforverylittlebenefit.

Itcostsusverylittlememoryspace(only32or64bitseachtime;Unityversion,platform,andfragmentationpermitting)tocachethesereferencesforfutureuse.So,unlessyou’reextremelybottleneckedonmemory,abetterapproachwouldbetoacquirethereferencesduringinitializationandkeepthemuntiltheyareneeded:

privateHealthComponent_healthComponent;

privateRigidbody_rigidbody;

privateCollider_collider;

privateAIControllerComponent_aiController;

privateAnimator_animator;

voidAwake(){

_healthComponent=GetComponent<HealthComponent>();

_rigidbody=GetComponent<Rigidbody>();

_collider=GetComponent<Collider>();

_aiController=GetComponent<AIControllerComponent>();

_animator=GetComponent<Animator>();

}

voidTakeDamage(){

if(_healthComponent.health<0){

_rigidbody.detectCollisions=false;

_collider.enabled=false;

_aiController.enabled=false;

_animator.SetTrigger("death");

}

}

CachingtheComponentreferencesinthiswaysparesusfromreacquiringthemeachtime

http://freepdf-books.com

Page 97: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

they’reneeded,savingussomeCPUoverheadeachtime,attheexpenseofsomeadditionalmemoryconsumption.

http://freepdf-books.com

Page 98: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 99: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ObtainingComponentsusingthefastestmethodThereareseveralvariationsoftheGetComponent()method,anditbecomesprudenttocallthefastestpossibleversionofthismethod.ThethreeoverloadsavailableareGetComponent(string),GetComponent<T>(),andGetComponent(typeof(T)).ItturnsoutthatthefastestversiondependsonwhichversionofUnitywearerunning.

InUnity4,theGetComponent(typeof(T))methodisthefastestoftheavailableoptionsbyareasonablemargin.Let’sprovethiswithsomesimpletesting:

intnumTests=1000000;

TestComponenttest;

using(newCustomTimer("GetComponent(string)",numTests)){

for(vari=0;i<numTests;++i){

test=(TestComponent)GetComponent("TestComponent");

}

}

using(newCustomTimer("GetComponent<ComponentName>",numTests)){

for(vari=0;i<numTests;++i){

test=GetComponent<TestComponent>();

}

}

using(newCustomTimer("GetComponent(typeof(ComponentName))",numTests)){

for(vari=0;i<numTests;++i){

test=(TestComponent)GetComponent(typeof(TestComponent));

}

}

ThiscodetestseachoftheGetComponent()overloadsamilliontimes.Thisisfarmoreteststhanwouldbesensibleforatypicalproject,butitisenoughteststoprovethepoint.

Hereistheresultwegetwhenthetestscomplete:

Asyoucansee,GetComponent(typeof(T))issignificantlyfasterthanGetComponent<T>(),whichisaroundfivetimesfasterthanGetComponent(string).ThistestwasperformedagainstUnity4.5.5,butthebehaviorshouldbeequivalentallthewaybacktoUnity3.x.

Note

http://freepdf-books.com

Page 100: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

GetComponent(string)shouldnotbeused,sinceitisnotoriouslyslowandisonlyincludedforcompleteness.

TheseresultschangewhenweruntheexactsametestinUnity5.UnityTechnologiesmadesomeperformanceenhancementstohowSystem.TypereferencesarepassedaroundinUnity5.0,and,asaresult,GetComponent<T>()andGetComponent(typeof(T))becomeessentiallyequivalent:

Asyoucansee,theGetComponent<T>()methodisonlyatinyfractionfasterthanGetComponent(typeof(T)),whileGetComponent(string)isnowaround30timesslowerthanthealternatives(interestingly,itbecameevenslowerthanitwasinUnity4).Multipletestswillprobablyyieldsmallvariationsintheseresults,butultimatelywecanfavoreitherofthetype-basedversionsofGetComponent()whenwe’reworkinginUnity5,andtheoutcomewillbeaboutthesame.

Thereisonecaveat,however.Ifwe’rerunningUnity4,thenwestillhaveaccesstoavarietyofquickaccessorpropertiessuchascollider,rigidbody,camera,andsoon.ThesepropertiesbehavelikeprecachedComponentmembervariables,whicharesignificantlyfasterthanallofthetraditionalGetComponent()methods:

intnumTests=1000000;

Rigidbodytest;

using(newCustomTimer("Cachedreference",numTests))

{

for(vari=0;i<numTests;++i){

test=gameObject.rigidbody;

}

}

NoteNotethatthiscodeisintendedforUnity4,andwillnotcompileinUnity5duetotheremovaloftherigidbodyproperty.

RunningthistestinUnity4givesusthefollowingresult:

Inanefforttoreducedependenciesandimprovecodemodularizationintheengine’sbackend,UnityTechnologieshasdeprecatedallofthesequickaccessorvariablesinUnity5.Onlythetransformpropertyremains.

http://freepdf-books.com

Page 101: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TipUnity4usersconsideringanupgradetoUnity5shouldknowthatupgradingwillautomaticallymodifyanyofthesepropertiestousetheGetComponent<T>()method.However,thiswillresultinuncachedGetComponent<T>()callsscatteredthroughoutyourcode,possiblyrequiringyoutorevisitthetechniquesintroducedintheearliersection,entitledCacheComponentReferences.

ThemoralofthestoryisthatifwearerunningUnity4,andtherequiredComponentisoneofGameObject’sbuilt-inaccessorproperties,thenweshouldusethatversion.Ifnot,thenweshouldfavorGetComponent(typeof(T)).Meanwhile,ifwe’rerunningUnity5,thenwecanfavoreitherofthetype-basedversions:GetComponent<T>()orGetComponent(typeof(T)).

http://freepdf-books.com

Page 102: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 103: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

RemovingemptycallbackdeclarationsWhenwecreatenewMonoBehaviourscriptfilesinUnity,whetherwe’reusingUnity4orUnity5,itcreatestwoboilerplatemethodsforus:

//Usethisforinitialization

voidStart(){

}

//Updateiscalledonceperframe

voidUpdate(){

}

TheUnityenginehooksintothesemethodsduringinitializationandaddsthemtoalistofmethodstocallbackatkeymoments.However,ifweleavetheseasemptydeclarationsinourcodebase,thentheywillcostusasmalloverheadwhenevertheengineinvokesthem.

TheStart()methodisonlycalledwhentheGameObjectisinstantiatedforthefirsttime,whichcanbewheneverthesceneisloadedoranewGameObjectisinstantiatedfromaPrefab.Therefore,leavingtheemptyStart()declarationmaynotbeparticularlynoticeableunlessthere’salotofGameObjectsinthesceneinvokingthematstartuptime.However,italsoaddsunnecessaryoverheadtoanyGameObject.Instantiate()call,whichtypicallyhappensduringkeyevents,sotheycanpotentiallycontributeto,andexacerbate,alreadypoorperformancessituationwhenlotsofeventsarehappeningsimultaneously.

Meanwhile,theUpdate()methodiscalledeverytimethesceneisrendered.IfourscenecontainsthousandsofGameObjectsowningcomponentswiththeseemptyUpdate()declarations,thenwecanbewastingalotofCPUcyclesandcausinghavoconourframerate.

Let’sprovethiswithasimpletest.OurtestsceneshouldhaveGameObjectswithtwotypesofComponent,onetypewithanemptyUpdate()declaration,andanotherwithnomethodsdefined:

publicclassCallbackTestComponent:MonoBehaviour{

voidUpdate(){}

}

publicclassEmptyTestComponent:MonoBehaviour{

}

Herearethetestresultsfor32,768Componentsofeachtype.Ifweenableallobjectswithnostubmethodsduringruntime,thennothinginterestinghappenswithCPUusageintheProfiler.WemaynoticesomememoryconsumptionchangesandsomeslightlydifferentVSyncactivity,butnothingveryconcerning.However,assoonasweenablealltheobjectswithemptyUnitycallbackdeclarations,wewillobserveahugeincreaseinCPUusage:

http://freepdf-books.com

Page 104: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Thefixforthisissimple;deletetheemptydeclarations.Unitywillhavenothingtohookinto,andnothingwillbecalled.Sometimes,findingsuchemptydeclarationsinanexpansivecodebasecanbedifficult,butusingsomebasicregularexpressions(regex),weshouldbeabletofindwhatwe’relookingforrelativelyeasily.

TipAllcommoncode-editingtoolsforUnity,suchasMonoDevelop,VisualStudio,andevenNotepad++,provideawaytoperformaregex-basedsearchontheentirecodebase.Checkthetool’sdocumentationformoreinformation,sincethemethodcanvarygreatlydependingonthetoolanditsversion.

ThefollowingregexsearchshouldfindanyemptyUpdate()declarationsinourcode:

void\s*Update\s*?\(\s*?\)\s*?\n*?\{\n*?\s*?\}

ThisregexchecksforastandardmethoddefinitionoftheUpdate()method,whileincludinganysurpluswhitespaceandnewlinecharactersthatcanbedistributedthroughoutthemethoddeclaration.

Naturally,alloftheaboveisalsotrueforthenon-boilerplateUnitycallbacks,suchasOnGUI(),OnEnable(),OnDestroy(),FixedUpdate(),andsoon.ChecktheMonoBehaviourUnityDocumentationpageforacompletelistofthesecallbacksathttp://docs.unity3d.com/ScriptReference/MonoBehaviour.html.

Itmightseemunlikelythatsomeonegeneratedemptyversionsofthesecallbacksinourcodebase,butneversaynever.Forexample,ifweuseacommonbaseclassMonoBehaviourthroughoutallofourcustomcomponents,thenasingleemptycallbackdeclarationinthatbaseclasswillpermeatetheentiregame,whichcancostusdearly.BeparticularlycarefuloftheOnGUI()method,asitcanbeinvokedmultipletimeswithinthesameframeoruserinterface(UI)event.

http://freepdf-books.com

Page 105: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 106: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AvoidingtheFind()andSendMessage()methodsatruntimeTheSendMessage()methodandfamilyofGameObject.Find()methodsarenotoriouslyexpensive,andshouldbeavoidedatallcosts.TheSendMessage()methodisabout2,000timesslowerthanasimplefunctioncall,andthecostoftheFind()methodscalesverypoorlywithScenecomplexitysinceitmustiteratethrougheveryGameObjectintheScene.ItissometimesreasonabletocallFind()duringinitializationofaScene,suchasAwake()andStart(),onlyforobjectsthatalreadyexistsintheScene.However,usingeithermethodforinter-objectcommunicationatruntimeislikelytogenerateaverynoticeableoverhead.

RelyingonFind()andSendMessage()typemethodsistypicallysymptomaticofpoordesign,inexperienceinprogrammingwithC#andUnity,orjustplainlazinessduringprototyping.Theirusagehasbecomesomethingofanepidemicamongbeginner-andintermediate-levelprojects,suchthatUnityTechnologiesfeelstheneedtokeepremindinguserstoavoidusingtheminarealgame,overandoveragainintheirdocumentationandattheirconferences.Theyonlyexistasalessprogrammer-ywaytointroducenewuserstointer-objectcommunication,andforsomespecialcaseswheretheycanbeusedinalazy,butresponsible,way.

Tobefair,Unitytargetsawidedemographicofusers,fromindividualhobbyists,students,andthosewithdelusionsofgrandeur,tosmall,mid-sized,andlargedevelopmentteams.Thisresultsinanincrediblywiderangeofsoftwaredevelopmentability.Whenyou’restartingoutwithUnity,itcanbedifficulttofigureoutonyourownwhatyoushouldbedoingdifferently,especiallygivenhowtheUnityenginedoesnotadheretothedesignparadigmsofmanyothergameengines.Ithassomeforeignandquirkyconceptssurroundingscenesandprefabs,aswellasnogodclassentrypoints,noranyobviousraw-datastoragesystemstoworkwith.

Sincewe’retalkingaboutscriptingoptimizationinthissection,let’sexplorethesubjectinsomedetail,discussingsomealternativemethodsforinter-objectcommunication.

Let’sstartbyexaminingaworst-caseexample,whichusesbothFind()andSendMessage()methods,anddiscoversomewaystoimproveuponit.Thefollowingexamplemethodattemptstoinstantiateagivennumberofenemiesfromaprefab,andthennotifiesanEnemyManagerobjectoftheirexistence:

publicvoidSpawnEnemies(intnumEnemies){

for(inti=0;i<numEnemies;++i){

GameObjectenemy=(GameObject)GameObject.Instantiate(_enemyPrefab,

Vector3.zero,Quaternion.identity);

GameObjectenemyManagerObj=GameObject.Find("EnemyManager");

enemyManagerObj.SendMessage("AddEnemy",enemy,

SendMessageOptions.DontRequireReceiver);

}

}

http://freepdf-books.com

Page 107: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Puttingmethodcallsinsidealoop,whichalwaysoutputtothesameresult,isabigredflagforpoorperformance,andwhenwe’redealingwithexpensivemethodssuchasFind(),weshouldalwayslookforwaystocallthemasfewtimesaspossible.Ergo,oneimprovementwecanmakeistomovetheFind()calloutsideoftheforloopandcachetheresultinalocalvariabletobeusedwithintheloop.

WecanalsooptimizeourusageoftheSendMessage()methodbyreplacingitwithaGetComponent()call.Thisreplacesaverycostlymethodwithamuchgentlervariation,achievingeffectivelythesameresult.

Thisgivesusthefollowing:

publicvoidSpawnEnemies(intnumEnemies){

GameObjectenemyManagerObj=GameObject.Find("EnemyManager");

EnemyManagerComponentenemyMgr=

enemyManagerObj.GetComponent<EnemyManagerComponent>();

for(inti=0;i<numEnemies;++i){

GameObjectenemyIcon=(GameObject)GameObject.Instantiate(_enemyPrefab,

Vector3.zero,Quaternion.identity);

enemyMgr.AddEnemy(enemy);

}

}

IfthismethodiscalledduringtheinitializationoftheScene,andwe’renotoverlyconcernedwithloadingtime,thenwecanprobablyconsiderourselvesfinishedwithouroptimizationwork.

However,weoftenneednewobjectsthatareinstantiatedatruntimetofindanexistingobjecttocommunicatewith.Inthisexample,wewantnewenemyobjectstoregisterwithourEnemyManagerComponentsothatitcandowhateveritneedstodotocontroltheenemyobjectsinourScene.WewouldlikeareliableandfastwayfornewobjectstofindexistingobjectswithoutunnecessaryusageoftheFind()method,duetotheoverheadinvolved.

Therearemultipleapproacheswecantaketosolvingthisproblem,eachwiththeirownbenefitsandpitfalls:

StaticclassesSingletonComponentsAssignreferencestopre-existingobjectsAglobalmessagingsystem

http://freepdf-books.com

Page 108: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

StaticclassesThisapproachinvolvescreatingaclassthatisgloballyaccessibletotheentirecodebaseatanytime.Theobjectstaysalivefromthemomenttheapplicationstarts,tothemomentitisclosed.Globalmanagerclassesareoftenfrownedupon,sincethenamedoesn’tsaymuchaboutwhatit’smeanttodo,andtheycanbedifficulttodebugsincechangescanoccurfromanywhere,atanypointduringruntime.Inaddition,itisprobablytheleastrobustapproachwhenitcomestochangingorreplacingitatafuturedate.Despiteallofthesedrawbacks,itisbyfartheeasiestsolutiontoimplement,andsowewillcoveritfirst.

TheSingletondesignpatternisacommonwayofensuringthatwehaveaglobally-accessibleobject,andthatonlyoneinstanceeverexistsinmemory.However,thewaythatSingletonsareprimarilyused(notethequalifier)inUnityprojects,canbeeasilyreplacedwithasimpleC#Staticclasswithouttheneedtoimplementprivateconstructors,andtheunnecessarypropertyaccessofanInstancevariable.Essentially,implementingatypicalSingletondesignpatterninC#justtakesmorecode,andtime,toachievethesameresultasastaticclass.

AstaticclassthatfunctionsinmuchthesamewayasourEnemyManagerComponentisusedinthepreviousexamplecanbedefinedasfollows:

usingSystem.Collections.Generic;

publicstaticclassEnemyManager{

staticList<GameObject>_enemies;

publicstaticvoidAddEnemy(GameObjectenemy){

_enemies.Add(enemy);

}

publicstaticvoidRollCall(){

for(inti=0;i<_enemies.Count;++i){

Debug.Log(string.Format("Enemy\"{0}\"reportingin…",

_enemies[i].name));

}

}

}

Notethateverymemberandmethodhasthestatickeywordattached,whichimpliesthatonlyoneinstanceofthisobjectwilleverresideinmemory.Staticclasses,bydefinition,donotallowanynonstaticinstancememberstobedefined,asthatwouldimplythatwecouldsomehowduplicatetheobject.

Staticclassescanbegivenastaticconstructor,whichcanbeusedtoinitializememberdata.Astaticconstructorcanbedefinedlikeso,anditiscalledthemomenttheclassisfirstaccessed(eitherthroughamembervariableoramemberfunction):

staticEnemyManager(){

_enemies=newList<GameObject>();

}

Thistypeofglobalclassisgenerallyconsideredtobeacleanerandeasier-to-useversion

http://freepdf-books.com

Page 109: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ofthetypicalSingletondesignpatternintheworldofC#development.

http://freepdf-books.com

Page 110: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SingletonComponentsThedisadvantageofthestaticclassapproachisthattheymustinheritfromthelowestformofclass—Object.ThismeansthatstaticclassescannotinheritfromMonoBehaviourandthereforewecannotmakeuseofanyofitsUnity-relatedfunctionality,includingtheall-importanteventcallbacks,aswellasCoroutines.Also,sincethere’snoobjecttoselect,welosetheabilitytoinspecttheobject’sdataatruntimethroughtheInspector.ThesearefeaturesthatwemaywishtomakeuseofinourglobalSingletonclasses.

Acommonsolutiontothisproblemistoimplementa“SingletonasaComponent”classthatspawnsaGameObjectcontainingitself,andprovidingstaticmethodstograntglobalaccess.Notethat,inthiscase,wemustessentiallyimplementthetypicalSingletondesignpattern,withprivatestaticinstancevariables,andaglobalInstancemethodforglobalaccess.

HereisthedefinitionforaSingletonAsComponentclass:

publicclassSingletonAsComponent<T>:MonoBehaviourwhereT:

SingletonAsComponent<T>{

privatestaticT__Instance;

protectedstaticSingletonAsComponent<T>_Instance{

get{

if(!__Instance){

T[]managers=

GameObject.FindObjectsOfType(typeof(T))asT[];

if(managers!=null){

if(managers.Length==1){

__Instance=managers[0];

return__Instance;

}elseif(managers.Length>1){

Debug.LogError("Youhavemorethanone"+

typeof(T).Name+"inthescene.Youonly

need1,it'sasingleton!");

for(inti=0;i<managers.Length;++i){

Tmanager=managers[i];

Destroy(manager.gameObject);

}

}

}

GameObjectgo=newGameObject(typeof(T).Name,

typeof(T));

__Instance=go.GetComponent<T>();

DontDestroyOnLoad(__Instance.gameObject);

}

return__Instance;

}

set{

__Instance=valueasT;

}

}

http://freepdf-books.com

Page 111: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

Sincewewishthistobeaglobalandpersistentobject,weneedtocallDontDestroyOnLoad()shortlyaftertheGameObjectiscreated.ThisisaspecialfunctionthattellsUnitythatwewishtheobjecttopersistbetweenScenesforaslongastheapplicationisrunning.Fromthatpointonward,whenanewsceneisloaded,theobjectwillnotbedestroyedandwillretainallofitsdata.

Thisclassdefinitionassumestwothings.Firstly,becauseitisusinggenericstodefineitsbehavior,itmustbederivedfrominordertocreateaconcreteclass.Secondly,amethodwillbedefinedtoassignthe_Instancevariableandcastitto/fromthecorrectType.

Forexample,thefollowingisallthatisneededtosuccessfullygenerateanewSingletonAsComponentderivedclasscalledMySingletonComponent:

publicclassMySingletonComponent:

SingletonAsComponent<MySingletonComponent>{

publicstaticMySingletonComponentInstance{

get{return((MySingletonComponent)_Instance);}

set{_Instance=value;}

}

}

ThisclasscanbeusedatruntimebyhavinganyotherobjectaccesstheInstancepropertyatanytime.IftheComponentdoesnotalreadyexistinourScene,thentheSingletonAsComponentbaseclasswillinstantiateitsownGameObjectandattachaninstanceofthederivedclasstoitasaComponent.Fromthatpointforward,accessthroughtheInstancepropertywillreferencetheComponentthatwascreated.

TipWhileitispossible,weshouldnotplaceourSingletonAsComponentderivedclassinaSceneHierarchy.ThisisbecausetheDontDestroyOnLoad()methodwillneverbecalled!ThiswouldpreventtheSingletonComponent’sGameObjectfrompersistingwhenthenextSceneisloaded.

PropercleanupofaSingletonComponentcanbealittleconvolutedbecauseofhowUnitytearsdownScenes.Anobject’sOnDestroy()methodiscalledwheneveritisdestroyedduringruntime.Thesamemethodiscalledduringapplicationshutdown,wherebyeveryComponentoneveryGameObjecthasitsOnDestroy()methodcalledbyUnity.ApplicationshutdownalsotakesplacewhenweendPlayModeintheEditorandreturntoEditMode.However,destructionofobjectsoccursinarandomorder,andwecannotassumethattheSingletonComponentwillbethelastobjectdestroyed.

Consequently,ifanyobjectattemptstodoanythingwiththeSingletoninthemiddleoftheirOnDestroy()method,thentheywillbecallingtheInstanceproperty.IftheSingletonhasalreadybeendestroyedpriortothismoment,thencallingInstanceduringanotherobject’sdestructionwouldcreateanewinstanceoftheSingletonComponentinthemiddleofapplicationshutdown!ThiscancorruptourScenefiles,asinstancesofourSingletonComponentswillbeleftbehindintheScene.Ifthishappens,thenUnitywillthrowthefollowingerrormessageatus:

http://freepdf-books.com

Page 112: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThereasonsomeobjectsmaywishtocallintoourSingletonduringdestructionisthatSingletonsoftenmakeuseoftheObserverpattern.Thisdesignpatternallowsotherobjectstoregister/deregisterwiththemforcertaintasks,similartohowUnitylatchesontocallbackmethods,butinalessautomatedfashion.WewillseeanexampleofthisintheupcomingsectionAglobalmessagingsystem.Objectsthatareregisteredwiththesystemduringconstructionwillwanttoderegisterwiththesystemduringtheirownshutdown,andthemostconvenientplacetodothisiswithinitsOnDestroy()method.Consequently,suchobjectsarelikelytorunintotheaforementionedproblem,whereSingletonsareaccidentallycreatedduringapplicationshutdown.

Tosolvethisproblem,weneedtomakethreechanges.Firstly,weneedtoaddanadditionalflagtotheSingletonComponent,whichkeepstrackofitsactivestate,anddisableitattheappropriatetimes.ThisincludestheSingleton’sowndestruction,aswellasapplicationshutdown(OnApplicationQuit()isanotherusefulUnitycallbackforMonoBehaviours,whichiscalledduringthistime):

privatebool_alive=true;

voidOnDestroy(){_alive=false;}

voidOnApplicationQuit(){_alive=false;}

Secondly,weshouldimplementawayforexternalobjectstoverifytheSingleton’scurrentstate:

publicstaticboolIsAlive{

get{

if(__Instance==null)

returnfalse;

return__Instance._alive;

}

}

Finally,anyobjectthatattemptstocallintotheSingletonduringitsownOnDestroy()method,mustfirstverifythestateusingtheIsAlivepropertybeforecallingInstance.Forexample:

publicclassSomeComponent:MonoBehaviour{

voidOnDestroy(){

if(MySingletonComponent.IsAlive){

MySingletonComponent.Instance.SomeMethod();

}

}

}

ThiswillensurethatnobodyattemptstoaccessInstanceduringdestruction.Ifwedon’tfollowthisrule,thenwewillrunintoproblemswhereinstancesofourSingletonobjectwillbeleftbehindintheSceneafterreturningtoEditMode.

TheironyoftheSingletonComponentapproachisthatweareusingoneofUnity’s

http://freepdf-books.com

Page 113: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Find()methodstodeterminewhetherornotoneoftheseSingletonComponentsalreadyexistsintheScenebeforeweattempttoassignthe__Instancereferencevariable.Fortunately,thiswillonlyhappenwhentheSingletonComponentisfirstaccessed,butit’spossiblethattheinitializationoftheSingletonwouldnotnecessarilyoccurduringSceneinitializationandcanthereforecostusaperformancespikeatabadmomentduringgameplay,whenthisobjectisfirstinstantiatedandFind()getscalled.TheworkaroundforthisistohavesomegodclassconfirmthattheimportantSingletonsareinstantiatedduringSceneinitializationbysimplycallingInstanceoneachone.

Thedownsidetothisapproachisthatifwelaterdecidethatwewantmorethanoneofthesemanagerclassesexecutingatonce,orwewishtoseparateitsbehaviortobemoremodular,thentherewouldbealotofcodethatneedstochange.

Therearefurtheralternativesthatwecanexplore,suchasmakinguseofUnity’sbuilt-inbridgebetweenscriptcodeandtheInspectorinterface.

http://freepdf-books.com

Page 114: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Assigningreferencestopre-existingobjectsAnotherapproachtotheproblemofinter-objectcommunicationistouseUnity’sbuilt-inserializationsystems.Softwaredesignpuriststendtogetalittlecombativeaboutthisfeature,sinceitbreaksencapsulation;itmakesvariablesmarkedprivateactinawaythattreatsthemaspublic.EventhoughthevalueonlybecomespublicwithrespecttotheUnityInspectorandnothingelse,thisisstillenoughtowavesomeredflags.

However,itisaveryeffectivetoolforimprovingdevelopmentworkflow.Thisisparticularlytruewhenartists,designers,andprogrammersarealltinkeringwiththesameproduct,whereeachhaswildlyvaryinglevelsofcomputerscienceandsoftwareprogrammingknowledge.Sometimesit’sworthbendingafewrulesinthenameofproductivity.

Wheneverwecreateapublicvariable,UnityautomaticallyserializesandexposesthevalueintheInspectorinterfacewhentheComponentisselected.However,publicvariablesaredangerousfromasoftwaredesignperspective—thesevariablescanbechangedthroughcodeatanytime,whichcanmakeithardtokeeptrackofthevariable,andintroducealotofunexpectedbugs.

Asanalternative,wecantakeanyprivateorprotectedmembervariableofaclassandexposeittotheUnityEditorInspectorinterfacewiththe[SerializeField]attribute.Thisapproachispreferredoverpublicvariables,asitgivesusmorecontrolofthesituation.Thisway,atleastweknowthevariablescannotbechangedatruntimeviacodeoutsidetheclass(orderivedclass),andthereforemaintainencapsulationfromtheperspectiveofscriptcode.

Forexample,thefollowingclassexposesthreeprivatevariablestotheInspector:

publicclassEnemySpawnerComponent:MonoBehaviour{

[SerializeField]privateint_numEnemies;

[SerializeField]privateGameObject_enemyPrefab;

[SerializeField]privateEnemyManagerComponent_enemyManager;

voidStart(){

SpawnEnemies(_numEnemies);

}

voidSpawnEnemies(int_numEnemies){

for(inti=0;i<_numEnemies;++i){

GameObjectenemy=(GameObject)GameObject.Instantiate(_enemyPrefab,

Vector3.zero,Quaternion.identity);

_enemyManager.AddEnemy(enemy);

}

}

}

TipNotethattheprivateaccessspecifiersshownintheprecedingcodeareredundantkeywordsinC#,asmembervariablesarealwaysprivateunlessspecifiedotherwise,but

http://freepdf-books.com

Page 115: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

theseaccessspecifiersareincludedforcompleteness.

LookingatthisComponentintheInspectorviewrevealsthreevalues,initiallygivendefaultvaluesof0,ornull,whichcanbemodifiedthroughtheInspectorinterface:

WecandraganddropaPrefabreferencefromtheProjectswindowintotheEnemyPrefabfield,or,ifwefeltsoinclined,evenareferencetoanotherGameObjectthatispresentintheScene.Although,giventhatit’sbeingusedlikeaPrefabinthecode,itwouldbeunwisetodothis,sincewewouldbecloningaGameObjectthatmighthavealreadyundergonechangesintheScene.PrefabsservethepurposeofablueprintfromwhichtoinstantiatenewGameObjectsandshouldbeusedassuch.

TheEnemyManagerfieldisinterestingbecauseitisaComponentreferenceandnotaGameObjectreference.IfaGameObjectisdroppedintothisfield,thenitwillrefertotheComponentonthegivenobject,asopposedtotheGameObjectthatwedraggedanddroppedintothefield.IfthegivenobjectdoesnothavetheexpectedComponent,thennothingwillbeassigned.

TipAcommonusageoftheComponentreferencetechniqueistoobtainreferencestoComponentsattachedtothesameGameObjectitisattachedto.ThisisanalternativeapproachtothetopicdiscussedinthesectionentitledCacheComponentReferences,earlierinthischapter.

ThedangerhereisthatsincePrefabsareessentiallyGameObjects,PrefabswiththerequiredComponentcanbeassignedtothesefields,eventhoughwemightnotwishthemtobe.UnityloadsPrefabsintomemorymuchlikeGameObjects,andassumesthey’llbeusedinPrefab-likeways;thatis,treatedasnothingmorethanblueprintstobeinstantiatedfromonanas-neededbasis.However,theystillcountasdatastoredinmemoryandcanthereforebeeditedonawhim,makingthemsusceptibletochangesthatdirectlyaffectallfutureGameObjectsinstantiatedfromthem.

Tomakemattersworse,thesechangesbecomepermanenteveniftheyaremadeduringPlayMode,sincePrefabsoccupythesamememoryspacewhetherPlayModeisactiveornot.ThismeansthatwecanaccidentallycorruptourPrefabs,ifweassignthemtothewrongfields.Consequently,thisapproachisamoreteam-friendlywayofsolvingtheoriginalproblemofinter-objectcommunication,butitisnotidealduetoalloftherisksinvolvedwithteammembersaccidentallybreakingthingsorleavingnullreferencesinplace.

ItisalsoimportanttonotethatnotallobjectscanbeserializedbytheInspectorview.

http://freepdf-books.com

Page 116: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Unitycanserializeallprimitivedatatypes(ints,floats,strings,andbools),variousbuilt-intypessuchas(Vector3,Quaternion,andsoon)enums,classes,andstructs,aswellasarraysandlistsofotherserializabletypes.However,itisunabletoserializestaticfields,read-onlyvalues,properties,anddictionaries.

TipSomeUnitydevelopersliketoimplementpseudo-serializationofdictionariesviatwoseparatelistsforkeysandvalues,alongwithaCustomEditorscript,orviaasinglelistofobjects,whichcontainbothkeysandvalues.Bothofthesesolutionsarealittleclumsy,butperfectlyvalid.

Thelastsolutionwewilllookatwillprovideawaytohopefullygetthebestofbothworldsbycombiningeaseofimplementation,easeofextension,andstrictusagethatavoidstoomuchhumanerror.

http://freepdf-books.com

Page 117: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AglobalmessagingsystemThefinalsuggestedapproachtotheproblemofinter-objectcommunicationistoimplementaglobalmessagingsystemthatanyobjectcanaccessandsendmessagesthroughtoanyobjectthatmaybeinterestedinlisteningtothatspecifictypeofmessage.Objectseithersendmessagesorlistenforthem,andtheresponsibilityisonthelistenertodecidewhatmessagesitisinterestedin.Themessagesendercanbroadcastthemessagewithoutcaringatallwhoislistening.Thisapproachisexcellentforkeepingourcodemodularanddecoupled.

Thekindsofmessagewewishtosendcantakemanyforms,suchasincludingdatavalues,references,instructionsforlisteners,andmore,buttheyshouldallhaveacommon,basicdeclarationthatourmessagingsystemcanusetodeterminewhatthemessageis,andwhoitisintendedfor.

ThefollowingisasimpleclassdefinitionforaMessageobject:

publicclassBaseMessage{

publicstringname;

publicBaseMessage(){name=this.GetType().Name;}

}

TheBaseMessageclass’sconstructorcachestheTypeinalocalstringpropertytobeusedlaterforcataloguinganddistributionpurposes.CachingthisvalueisimportantaseachcalltoGetType().Namewillresultinanewstringbeingallocatedontheheap,andwewanttominimizethisasmuchaspossible.Ourcustommessagesmustderivefromthisclass,whichallowsthemtoaddwhateversuperfluousdatatheywish,whilestillmaintainingtheabilitytobesentthroughourmessagingsystem.Takenotethat,despiteacquiringtheTypenameduringthebaseclassconstructor,thenamepropertywillstillcontainthenameofthederivedclass,notthebaseclass.

MovingontoourMessagingSystemclass,weshoulddefineitsfeaturesbywhatkindofrequirementsweneedittofulfill:

ItshouldbegloballyaccessibleAnyobject(MonoBehaviourornot)shouldbeabletoregister/deregisteraslisteners,toreceivespecificmessagetypes(thatis,theObserverpattern)RegisteringobjectsshouldprovideamethodtocallwhenthegivenmessageisbroadcastThesystemshouldsendthemessagetoalllistenerswithinareasonabletimeframe,butnotchokeontoomanyrequestsatonce

AgloballyaccessibleobjectThefirstrequirementmakesthemessagingsystemanexcellentcandidateforaSingletonobject,sinceweshouldonlyeverneedoneinstanceofthesystem.Although,itiswisetothinklongandhardifthisistrulythecasebeforecommittingtoimplementingaSingleton.Ifwelaterdecidethatwewantmultipleinstancesofthisobjecttoexist,thenitcanbedifficulttorefactorduetoallofthedependencieswewillgraduallyintroduceto

http://freepdf-books.com

Page 118: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ourcodebaseasweusethesystemmoreandmore.

Forthisexample,wewillassumethatweareabsolutelypositivethatwewillonlyneedoneofthesesystems,anddesignitaccordingly.

RegistrationMeetingthesecondandthirdrequirementscanbeachievedbyofferingsomepublicmethodsthatallowregistrationwiththemessagingsystem.Ifweforcethelisteningobjecttoprovideusadelegatefunctiontocallwhenthemessageisbroadcast,thenthisallowslistenerstocustomizewhichmethodiscalledforwhichmessage.Thiscanmakeourcodebasemucheasiertounderstand,ifwenamethedelegateafterthemessageitisintendedtoprocess.

TipDelegatefunctionsareincrediblyusefulconstructsinC#thatallowsustopasslocalmethodsaroundasargumentstoothermethods,andaretypicallyusedforcallbacks.ChecktheMSDNC#ProgrammingGuideformoreinformationondelegatesathttps://msdn.microsoft.com/en-us/library/ms173171.aspx.

Insomecases,wemightwishtobroadcastageneralnotificationmessageandhavealllistenersdosomethinginresponse,suchasan“EnemySpawned”message.Othertimes,wemightbesendingamessagethatspecificallytargetsasinglelisteneramongstagroup.Forexample,wemightwishtosendan“EnemyHealthValueChanged”messagethatisintendedforaspecifichealthbarobjectthatisattachedtotheenemythatwasdamaged.Ifweimplementawayforlistenerstostopmessageprocessingearly,thenwecansaveasignificantnumberofCPUcycles,iftherearemanylistenerswaitingforthesamemessagetype.

Thedelegatewedefineshouldthereforeprovideawayofretrievingthemessageviaanargument,andreturnaresponsethatdetermineswhetherornotprocessingforthemessageshouldstopwhenthelistenerisdonewithit.ThedecisiononwhethertostopprocessingornotcanbeachievedbyreturningasimpleBoolean,wheretrueimpliesthatthislistenerhashandledthemessage,andprocessingforthemessagemuststop.

Hereisthedefinitionforthedelegate:

publicdelegateboolMessageHandlerDelegate(BaseMessagemessage);

ListenersmustdefineamethodofthisformandpassareferencetoitwhenitregisterswiththeMessagingSystem,thusprovidinganentrypointforthemessagingsystemtocallwhenthemessageisbroadcast.

MessageprocessingThefinalrequirementforourmessagingsystemisthatthisobjecthassomekindoftiming-basedmechanismbuiltintopreventitfromchokingontoomanymessagesatonce.Thismeansthat,somewhereintheprocess,wewillneedtomakeuseofMonoBehavioureventcallbacksinordertoworkduringUnity’sUpdate()andbeabletocounttime.

http://freepdf-books.com

Page 119: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Thiscanbeachievedwiththestaticclass-basedSingleton(whichwedefinedearlier),whichwouldrequiresomeotherMonoBehaviour-basedgodclasstocallintoit,informingitthattheScenehasupdated.Alternatively,wecanusetheSingletonAsComponenttoachievethesamething,butdosoindependentlyofanygodclass.Theonlydifferencebetweenthetwoiswhetherornotthesystemisdependentonthecontrolofotherobjects.

TheSingletonAsComponentapproachisprobablythebest,sincetherearen’ttoomanyoccasionswherewewouldn’twantthissystemactingindependently,evenifmuchofourgamelogicdependsuponit.Forexample,evenifthegamewaspaused,wewouldn’twantthegamelogictopauseourmessagingsystem.Westillwantthemessagingsystemtocontinuereceivingandprocessingmessagessothatwecan,forexample,keepUI-relatedComponentscommunicatingwithoneanotherwhilethegameplayisinapausedstate.

ImplementingthemessagingsystemLet’sdefineourmessagingsystembyderivingfromtheSingletonAsComponentclass,andprovideamethodforobjectstoregisterwithit:

usingSystem.Collections.Generic;

publicclassMessagingSystem:SingletonAsComponent<MessagingSystem>{

publicstaticMessagingSystemInstance{

get{return((MessagingSystem)_Instance);}

set{_Instance=value;}

}

privateDictionary<string,List<MessageHandlerDelegate>>_listenerDict=

newDictionary<string,List<MessageHandlerDelegate>>();

publicboolAttachListener(System.Typetype,MessageHandlerDelegate

handler){

if(type==null){

Debug.Log("MessagingSystem:AttachListenerfailedduetonomessage

typespecified");

returnfalse;

}

stringmsgName=type.Name;

if(!_listenerDict.ContainsKey(msgName)){

_listenerDict.Add(msgName,newList<MessageHandlerDelegate>());

}

List<MessageHandlerDelegate>listenerList=_listenerDict[msgName];

if(listenerList.Contains(handler)){

returnfalse;//listeneralreadyinlist

}

listenerList.Add(handler);

returntrue;

}

}

http://freepdf-books.com

Page 120: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

The_listenerDictvariableisadictionaryofstringsmappedtolistsofMessageHandlerDelegates.Thisdictionaryorganizesourlistenerdelegatesintolistsbywhichmessagetypetheywishtolistento.Thus,ifweknowwhatmessagetypeisbeingsent,thenwecanquicklyretrievealistofalldelegatesthathavebeenregisteredforthatmessagetype.Wecantheniteratethroughthelist,queryingeachlistenertoseeifoneofthemwantstohandleit.

TheAttachListener()methodrequirestwoparameters;amessagetypeintheformofaSystem.Type,andaMessageHandlerDelegatetosendthemessagetowhenitcomesthroughthesystem.

MessagequeuingandprocessingInordertoprocessmessages,ourMessagingSystemshouldmaintainaqueueofincomingmessageobjectssothatwecanprocessthemintheordertheyarebroadcasted:

privateQueue<BaseMessage>_messageQueue=newQueue<BaseMessage>();

publicboolQueueMessage(BaseMessagemsg){

if(!_listenerDict.ContainsKey(msg.name)){

returnfalse;

}

_messageQueue.Enqueue(msg);

returntrue;

}

Themethodsimplychecksifthegivenmessagetypeispresentinourdictionarybeforeaddingittothequeue.Thiseffectivelytestswhetherornotanobjectactuallycarestolistentothemessagebeforewequeueittobeprocessedlater.Wehaveintroducedanewprivatemembervariable,_messageQueue,forthispurpose.

Next,we’lladdadefinitionforUpdate().ThismethodwillbecalledregularlybytheUnityEngine.Itspurposeistoiteratethroughthecurrentcontentsofthemessagequeue,onemessageatime,verifywhetherornottoomuchtimehaspassedsincewebeganprocessing,andifnot,passthemalongtothenextstageintheprocess:

privatefloatmaxQueueProcessingTime=0.16667f;

voidUpdate(){

floattimer=0.0f;

while(_messageQueue.Count>0){

if(maxQueueProcessingTime>0.0f){

if(timer>maxQueueProcessingTime)

return;

}

BaseMessagemsg=_messageQueue.Dequeue();

if(!TriggerMessage(msg))

Debug.Log("Errorwhenprocessingmessage:"+msg.name);

if(maxQueueProcessingTime>0.0f)

timer+=Time.deltaTime;

}

http://freepdf-books.com

Page 121: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

Thetime-basedsafeguardisinplacetomakesurethatitdoesnotexceedaprocessingtimelimitthreshold.Thispreventsthemessagingsystemfromfreezingourgameiftoomanymessagesgetpushedthroughthesystemtooquickly.Ifthetotaltimelimitisexceeded,thenallmessageprocessingwillstop,leavinganyremainingmessagestobeprocessedduringthenextframe.

Lastly,weneedtodefinetheTriggerMessage()method,whichdistributesmessagestolisteners:

publicboolTriggerMessage(BaseMessagemsg){

stringmsgName=msg.name;

if(!_listenerDict.ContainsKey(msgName)){

Debug.Log("MessagingSystem:Message\""+msgName+"\"hasno

listeners!");

returnfalse;//nolistenersformessagesoignoreit

}

List<MessageHandlerDelegate>listenerList=_listenerDict[msgName];

for(inti=0;i<listenerList.Count;++i){

if(listenerList[i](msg))

returntrue;//messageconsumedbythedelegate

}

returntrue;

}

Thismethodisthemainworkhorseofthemessagingsystem.TheTriggerEvent()‘spurposeistoobtainthelistoflistenersforthegivenmessagetypeandgiveeachofthemanopportunitytoprocessit.Ifoneofthedelegatesreturnstrue,thenprocessingofthecurrentmessageceasesandthemethodexits,allowingtheUpdate()methodtoprocessthenextmessage.

Normally,wewouldwanttouseQueueEvent()tobroadcastmessages,butTriggerEvent()canbecalledinstead.ThismethodallowsmessagesenderstoforcetheirmessagestobeprocessedimmediatelywithoutwaitingforthenextUpdate()event.Thisbypassesthethrottlingmechanism,butthismightbenecessaryformessagesthatneedtobesentduringcriticalmomentsingameplay,wherewaitingoneadditionalframemightresultinstrange-lookingbehavior.

ImplementingacustommessageWe’vecreatedthemessagingsystem,butanexampleofhowtouseitwouldhelpuswrapourheadsaroundtheconcept.Let’sstartbydefiningasimplemessageclass,whichwecanusetotransmitsomedata:

publicclassMyCustomMessage:BaseMessage{

publicreadonlyint_intValue;

publicreadonlyfloat_floatValue;

publicMyCustomMessage(intintVal,floatfloatVal{

_intValue=intVal;

_floatValue=floatVal;

http://freepdf-books.com

Page 122: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

}

Goodpracticeformessageobjectsistomaketheirmembervariablesreadonly.Thisensuresthatthedatacannotbechangedaftertheobject’sconstruction.Thissafeguardsthecontentofourmessagesagainstbeingaltered,asthey’repassedbetweenonelistenerandanother.

MessageregistrationHere’sasimpleclassthatregisterswiththemessagingsystem,requestingtohaveitsHandleMyCustomMessage()methodcalledwheneveraMyCustomMessageobjectisbroadcastfromanywhereinourcodebase:

publicclassTestMessageListener:MonoBehaviour{

voidStart(){

MessagingSystem.Instance.AttachListener(typeof(MyCustomMessage),

this.HandleMyCustomMessage);

}

boolHandleMyCustomMessage(BaseMessagemsg){

MyCustomMessagecastMsg=msgasMyCustomMessage;

Debug.Log(string.Format("Gotthemessage!{0},{1}",

castMsg._intValue,castMsg._floatValue));

returntrue;

}

}

WheneveraMyCustomMessageobjectisbroadcast(fromanywhere!),thislistenerwillretrievethemessagethroughitsHandleMyCustomMessage()method.Itcanthentypecastitintotheappropriatederivedmessagetypeandhandlethemessageinitsownuniqueway.Otherclassescanregisterforthesamemessage,andhandleitdifferentlythroughitsowncustomdelegatemethod(assuminganearlierobjectdidn’treturntruefromitsowndelegate).

WeknowwhattypeofmessagewillbeprovidedbythemsgargumentoftheHandleMyCustomMessage()method,becausewedefineditduringregistrationthroughtheAttachListener()call.Duetothis,wecanbecertainthatourtypecastingissafe,andwecansavetimebynothavingtodoanullreferencecheck,although,technically,thereisnothingstoppingususingthesamedelegatetohandlemultiplemessagetypes!Inthesecases,thoughwewouldneedtoimplementawayofdeterminingwhichmessageobjectisbeingpassed,andtreatitaccordingly.Thebestapproachistodefineauniquemethodforeachmessagetypeinordertokeepthingsappropriatelydecoupled.

NotehowtheHandleMyCustomMessagemethoddefinitionmatchesthefunctionsignatureofMessageHandlerDelegate,andthatitisbeingreferencedintheAttachListener()call.Thisishowwetellthemessagingsystemwhatmethodtocallwhenthegivenmessagetypeisbroadcast,andhowdelegatesensuretypesafety.Ifthefunctionsignaturehadadifferentreturnvalueoradifferentlistofarguments,thenitwouldbeaninvaliddelegatefortheAttachListener()method,andwewouldgetcompilererrors.

http://freepdf-books.com

Page 123: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Thebeautifulpartisthatwe’refreetogivethedelegatemethodwhatevernamewewant.Themostsensibleapproachistonamethemethodafterthemessagewhichithandles.Thismakesitcleartoanyonereadingourcodewhatthemethodisusedforandwhatmessageobjecttypeisrequiredtocallit.

MessagesendingFinally,let’simplementanexampleofsendingamessagesothatwecantestthissystemout!Here’sacomponentthatwillbroadcastaninstanceofourMyCustomMessageclassthroughthemessagingsystemwhentheSpaceBarispressed:

publicclassTestMessageSender:MonoBehaviour{

publicvoidUpdate(){

if(Input.GetKeyDown(KeyCode.Space)){

MessagingSystem.Instance.QueueMessage(newMyCustomMessage(5,

13.355f));

}

}

}

IfweaddboththeTestMessageSenderandTestMessageListenerobjectstoourSceneandpresstheSpacebar,weshouldseealogmessageappearintheconsole,informingusofasuccessfultest:

OurMessagingSystemSingletonobjectwillbecreatedimmediatelyuponSceneinitialization,whentheTestMessageListener‘sStart()methodiscalledanditregisterstheHandleMyCustomMessagedelegate.NoadditionaleffortisrequiredonourparttocreatetheSingletonweneed.

MessagecleanupSincemessageobjectsareclasses,theywillbecreateddynamicallyinheapmemoryandwillbedisposedofshortlyafterwardswhenthemessagehasbeenprocessedanddistributedamongstalllisteners.However,asyouwilllearninChapter7,MasterfulMemoryManagement,thiswilleventuallyresultinagarbagecollectionasheapmemoryaccumulatesovertime.Ifourapplicationrunsforlongenough,itwilleventuallyresultintheoccasionalgarbagecollection.Therefore,itiswisetousethemessagingsystemsparinglyandavoidspammingmessagestoofrequentlyoneveryupdate.

Themoreimportantclean-upoperationtoconsiderisderegistrationofdelegatesifanobjectneedstobedestroyedorde-spawned.Ifwedon’thandlethisproperly,thenthemessagingsystemwillhangontodelegatereferencesthatpreventobjectsfrombeingfullydestroyedandfreedfrommemory.

Essentially,weneedtopaireveryAttachListener()callwithanappropriateDetachListener()methodwhentheobjectisdestroyed,disabled,orweotherwisedecide

http://freepdf-books.com

Page 124: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

thatwenolongerneedittobequeriedwhenmessagesarebeingsent.

ThefollowingmethoddefinitionintheMessagingSystemclasswilldetachalistenerforaspecificevent:

publicboolDetachListener(System.Typetype,MessageHandlerDelegate

handler)

{

if(type==null){

Debug.Log("MessagingSystem:DetachListenerfailedduetonomessage

typespecified");

returnfalse;

}

stringmsgName=type.Name;

if(!_listenerDict.ContainsKey(type.Name)){

returnfalse;

}

List<MessageHandlerDelegate>listenerList=_listenerDict[msgName];

if(!listenerList.Contains(handler)){

returnfalse;

}

listenerList.Remove(handler);

returntrue;

}

HereisanexampleusageoftheDetachListener()method,addedtoourTestMessageListenerclass:

voidOnDestroy(){

if(MessagingSystem.IsAlive){

MessagingSystem.Instance.DetachListener(typeof(MyCustomMessage),

this.HandleMyCustomMessage);

}

}

NotehowthisdefinitionmakesuseoftheIsAlivepropertydeclaredintheSingletonAsComponentclass.Thissafeguardsusagainsttheaforementionedproblemsduringapplicationshutdown,wherewecannotguaranteethattheSingletonwasdestroyedlast.

WrappingupthemessagingsystemCongratulationsareinorder,aswehavefinallybuiltafullyfunctionalglobalmessagingsystemthatanyandallobjectscaninterfacewith,tosendmessagesbetweenoneanother!AusefulfeatureofthisapproachisthatitisMonoBehaviour-agnostic,meaningthatthemessagesendersandlistenersdonotevenneedtoderivefromMonoBehaviourtointerfacewiththemessagingsystem;itjustneedstobeaclassthatprovidesamessagetypeandadelegatefunctionofthematchingfunctionsignature.

AsfarasbenchmarkingtheMessagingSystemclassgoes,weshouldfindthatifitis

http://freepdf-books.com

Page 125: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

capableofprocessinghundreds,ifnotthousandsofmessagesinasingleframewithminimalCPUoverhead(dependingontheCPU,ofcourse).TheCPUusageisessentiallythesamewhetheronemessageisbeingdistributedto100differentlisteners,100messagesaredistributedtojustonelistener.Itcostsaboutthesameeitherway.

Evenifwe’repredominantlysendingmessagesduringUIorgameplayevents,thisisprobablyfarmorepowerthanweneed.So,ifitdoesseemtobecausingperformanceproblems,thenit’sfarmorelikelytobecausedbywhatthelistenerdelegatesaredoingwiththemessagethanthemessagingsystem’sabilitytoprocessthosemessages.

Therearemanywaystoenhancethemessagingsystemtoprovidemoreusefulfeatureswemayneedinthefuture,suchas:

Allowmessagesenderstosuggestadelay(intimeorframecount)beforeamessageisprocessedanddistributedAllowmessagelistenerstodefineapriorityforhowurgentlyitshouldreceivemessagescomparedtootherlistenerswaitingforthesamemessagetype—awayofskippingtothefrontofthequeueifitregisteredlaterthanotherlistenersImplementsomesafetycheckstohandlesituationswherealistenergetsaddedtothelistofmessagelistenersforaparticularmessage,whileamessageofthattypeisstillbeingprocessed—C#willthrowanenumerationexceptionatussincethedelegatelistwillbechangedbyAttachListener(),whileitisstillbeingiteratedthroughinTriggerEvent()

Atthispoint,wehaveprobablyexploredmessagingsystemsenough,sothesetaskswillbeleftasanacademicexerciseforyoutoundertake,ifyoubecomecomfortableusingthissolutioninyourgames.

Let’sexploresomefurthertechniquesthatwecanusetoimproveperformancethroughscripting.

http://freepdf-books.com

Page 126: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 127: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DisablingunusedscriptsandobjectsScenescangetprettybusysometimes,especiallywhenwe’rebuildinglarge,openworlds.ThemoreobjectsinvokingcodeinanUpdate()method,theworsethingswillscaleandthesloweryourgamebecomes.However,muchofwhatisbeingprocessedmaybecompletelyunnecessaryifitisoutsideoftheplayer’svieworsimplytoofarawaytomatter.Thismaynotbeapossibilityinlargecity-buildingsimulationgameswheretheentiresimulationmustbeprocessedatalltimes,butitisoftenpossibleinfirstpersonandracinggames,wheretheplayeriswanderingaroundalargeexpansivearea,wherenon-visibleobjectscanbetemporarilydisabledwithouthavinganynoticeableeffectongameplay.

http://freepdf-books.com

Page 128: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DisablingobjectsbyvisibilitySometimes,wewantComponentsorGameObjectstobedisabledwhenthey’renotvisible.Unitycomeswithbuilt-inrenderingfeaturestoavoidrenderingobjectsthatarenotvisiblebyCameras(FrustumCulling,whichisautomaticinallversions),andtoavoidrenderingobjectsthatarehiddenbehindotherobjects(OcclusionCulling,tobediscussedinChapter6,DynamicGraphics),butthisdoesnotaffectComponentsthatarenon-renderable,suchasAIscripts.Wemustcontrolthatbehaviorourselves.

ThisproblemcanbesolvedeasilybyusingtheOnBecameVisible()andOnBecameInvisible()MonoBehaviourcallbacks.Asthenamesimply,thesecallbackmethodsareinvokedwhenarenderableobjecthasbecomevisibleorinvisiblewithrespecttothegameviewandanyCamerasinourScene.Inaddition,whentherearemultipleCamerasinaScene(forexample,alocalmultiplayergame),thecallbacksareonlyinvokediftheobjectbecomesvisibletoanyoneCamera,andbecomesinvisibletoallCameras.Thismeanstheaforementionedcallbackswillbecalledatexactlytherighttimestoimplementthisfeature.

Sincethevisibilitycallbacksrelatetoandcommunicatewiththerenderingsystem,theGameObjectmusthavearenderableobjectattached,suchasaMeshorSkinnedMesh.WemustensurethattheComponentswewanttoreceivethevisibilitycallbacksfromareattachedtothesameGameObjectastherenderableobjectandnotsomeparentorsub-object,otherwisetheywon’tbeinvoked.

TipNotethatUnityalsocountsthehiddencameraoftheSceneViewtowardstheOnBecameVisible()andOnBecameInvisible()callbacks.IfwefindthatthesemethodsarenotbeinginvokedproperlyduringPlayModetesting,makesuretoturntheSceneViewCameraawayfromeverything.

Toenable/disableindividualcomponentswiththevisibilitycallbacks,wecanaddthefollowingmethods:

voidOnBecameVisible(){enabled=true;}

voidOnBecameInvisible(){enabled=false;}

And,toenable/disabletheentireGameObjecttheComponentisattachedto,wecanimplementthemethodsthiswayinstead:

voidOnBecameVisible(){gameObject.SetActive(true);}

voidOnBecameInvisible(){gameObject.SetActive(false);}

http://freepdf-books.com

Page 129: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DisablingobjectsbydistanceInothersituations,wewantComponentsorGameObjectstobedisabledaftertheyarefarenoughawayfromtheplayer,suchthattheymaybebarelyvisible,buttoofarawaytomatter.AgoodcandidateforthistypeofactivityisroamingAIcreaturesthatwewanttoseeatadistance,butwherewedon’tneedittoprocessanything.

ThefollowingcodeisasimpleCoroutinethatperiodicallychecksthetotaldistancefromthetargetobjectanddisablesitselfifitstraystoofarawayfromit:

[SerializeField]GameObject_target;

[SerializeField]float_maxDistance;

[SerializeField]int_coroutineFrequency;

voidStart(){

StartCoroutine(DisableAtADistance());

}

IEnumeratorDisableAtADistance(){

while(true){

floatdistSqrd=(Transform.position-

_target.transform.position).sqrMagnitude;

if(distSqrd<_maxDistance*_maxDistance){

enabled=true;

}else{

enabled=false;

}

for(inti=0;i<_coroutineFrequency;++i){

yieldreturnnewWaitForEndOfFrame();

}

}

}

WeshouldassignthePlayerobject(orwhateverobjectwewantittocomparewith)tothe_targetfieldintheInspector,definethemaximumdistancein_maxDistance,andmodifythefrequencywithwhichtheCoroutineisinvokedbyusingthe_coroutineFrequencyproperty.Anytimetheobjectgoesfurtherthan_maxDistancedistanceawayfromtheobjectassignedto_target,itwillbedisabled.Itwillbere-enabledifitreturnswithinthatdistance.

Asubtleperformance-enhancingfeatureofthisimplementationiscomparingagainstdistance-squaredinsteadoftherawdistance.Thisleadsusconvenientlytoournexttip.

http://freepdf-books.com

Page 130: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 131: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Considerusingdistance-squaredoverdistanceItissafetosaythatCPUsarerelativelygoodatmultiplyingfloating-pointnumberstogether,butrelativelydreadfulatcalculatingsquarerootsfromthem.EverytimeweaskaVector3tocalculateadistancewiththemagnitudepropertyorwiththeDistance()method,we’reaskingittoperformasquarerootcalculation(asperthePythagoreantheorem),whichcancostalotofCPUoverheadcomparedtomanyothertypesofvectormathcalculations.

However,theVector3classalsooffersasqrMagnitudeproperty,whichisthesameasdistance,onlysquared.Thisletsusperformessentiallythesamecomparisoncheckwithouttheexpensivesquarerootincluded,solongaswealsosquarethevaluewe’retryingtocompareitagainst;or,todescribethismathematically,ifthemagnitudeofAislessthanthemagnitudeofB,thenA2willbelessthanB2.

Forexample,considercodelikethefollowing:

floatdistance=(transform.position–

other.transform.position).Distance();

if(distance<targetDistance){

//dostuff

}

Thiscanbereplacedwiththefollowingandachieveanearlyidenticalresult:

floatdistanceSqrd=(transform.position–

other.transform.position).sqrMagnitude;

if(distanceSqrd<targetDistance*targetDistance){

//dostuff

}

Thereasontheresultisnearlyidenticalisbecauseoffloating-pointprecision.We’relikelytolosesomeoftheprecisionthatwewouldhavehadfromusingthesquare-rootvalues,sincethevaluewillbeadjustedtoanareawithadifferentdensityofrepresentablenumbers;itcanlandexactlyon,orcloserto,amoreaccuraterepresentablenumber,or,morelikely,itwilllandonanumberwithlessaccuracy.Asaresult,thecomparisonisnotexactlythesame,butinmostcases,itiscloseenoughtobeunnoticeable,andtheperformancegaincanbequitesignificantforeachinstructionwereplaceinthismanner.

Ifthisminorprecisionlossisnotimportanttoyou,thenthisperformancetrickshouldbeconsidered.However,ifprecisionisveryimportanttoyou(suchasrunninganaccuratelarge-scalegalacticspacesimulation),thenyoumightwanttolookelsewhereforperformanceimprovements.

Notethatthistechniquecanbeusedforanysquare-rootcalculations;notjustfordistance.Thisissimplythemostcommonexampleyoumightrunacross,andbringtolighttheimportantsqrMagnitudepropertyoftheVector3class—apropertywhichUnityTechnologiesintentionallyexposedforustomakeuseofinthismanner.

http://freepdf-books.com

Page 132: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 133: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 134: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AvoidretrievingstringpropertiesfromGameObjectsOrdinarily,retrievingastringpropertyfromanobjectisthesameasretrievinganyotherreferencetypepropertyinC#;itisacquiredwithnoadditionalmemorycost.However,forwhateverarcanereasonhiddenwithintheUnitysourcecode,retrievingstringpropertiesfromGameObjectsduplicatesthestringinmemoryandresultsinaheapallocation.ThisdrawstheattentionoftheGarbageCollector,which,ifwearenotcareful,cancauseCPUspikesthatwillaffectperformanceduringruntime.

ThetwopropertiesofGameObjectaffectedbythisstrangebehavioraretagandname.Retrievingeitherofthesepropertiesforanyreasonwillcauseunnecessaryheapallocations.Therefore,itisunwisetouseeitherpropertyduringgameplay,andyoushouldonlyusetheminperformance-inconsequentialareassuchasEditorScripts.However,theTagsystemiscommonlyusedforruntimeidentificationpurposes,whichcanmakethisasignificantproblemforsometeams.

Forexample,thefollowingcodewouldcauseanadditionalheapmemoryallocationduringeveryiterationoftheloop:

for(inti=0;i<listOfObjects.Count;++i){

if(listOfObjects[i].tag=="Player"){

//dosomethingwiththisobject

}

}

ItisoftenbetterpracticetoidentifyobjectsbytheirComponents,classtypes,andidentifyingvaluesthatdonotinvolvestrings,butsometimeswe’reforcedintoacorner.Maybewedidn’tknowanybetterwhenwestarted,weinheritedsomeoneelse’scodebase,orwe’reusingitasaworkaroundforsomething.Let’sassumethat,forwhateverreason,we’restuckwiththeTagsystem,andwewanttoavoidtheseheapallocations.

Fortunately,thetagpropertyismostoftenusedincomparisonsituations,andGameObjectprovidesanalternativewaytocomparetagproperties,whichdoesnotcauseaheapallocation—theCompareTag()method.

Let’sperformasimpletesttoprovehowthissimplechangecanmakeallthedifferenceintheworld:

voidUpdate(){

intnumTests=10000000;

if(Input.GetKeyDown(KeyCode.Alpha1)){

for(inti=0;i<numTests;++i){

if(gameObject.tag=="Player"){

//dostuff

}

}

}

if(Input.GetKeyDown(KeyCode.Alpha2)){

http://freepdf-books.com

Page 135: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

for(inti=0;i<numTests;++i){

if(gameObject.CompareTag("Player")){

//dostuff

}

}

}

}

Wecanexecutethesetestsbypressingthe1and2keystotriggertherespectiveforloop.Herearetheresults:

LookingattheBreakdownviewforeachspike,wecanseetwocompletelydifferentsituations:

Retrievingthetagproperty10milliontimesresultsinabout363MBofmemorybeingallocatedjustforstringsalone.Thistakes2435millisecondstoprocess,where488millisecondsarespentongarbagecollection.Meanwhile,usingCompareTag()10milliontimescosts1788millisecondstoprocess,andcausesnoheapmemoryallocations,andhencenoGarbageCollection.Thisshouldmakeitabundantlyclearthatwemustavoidusingthenameandtagproperties.So,ifTagcomparisonbecomesnecessary,thenweshouldmakeuseofCompareTag().

Notethatpassinginastringliterallike"Player"doesnotresultinaruntimeheapallocation,sincetheapplicationtechnicallyallocatesthisvalueduringinitializationandmerelyreferencesitatruntime.However,ifwedynamicallygeneratethecomparisonstring,thenwewillrunintothesameheapmemoryallocationproblems,becausewe’reessentiallycreatinganewstringobjecteachtime.

http://freepdf-books.com

Page 136: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

YouwilllearnmorenuancesabouttheGarbageCollectorandstringusageinChapter7,MasterfulMemoryManagement.

http://freepdf-books.com

Page 137: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 138: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Update,Coroutines,andInvokeRepeatingUpdateiscalledeveryframe,butsometimeswehackinwaysfortheUpdatetobecalledlessfrequentlythannormal,andperhaps,withoutrealizingit,wecreateasituationwhereanemptymethodiscalledmoreoftenthannot:

voidUpdate(){

_timer+=Time.deltaTime;

if(_timer>_aiUpdateFrequency){

ProcessAI();

_timer-=_aiUpdateFrequency;

}

}

Withthisfunctiondefinition,weareessentiallycallinganemptyfunctionalmosteveryframe.Infact,itisworsethanthat;we’realsoperformingaBooleancheckthatalmostalwaysreturnsfalse.Thisisfineifwedon’tabusetheconcept,butasyou’velearned,havingtoomanyoftheseunnecessaryfunctioncallshidinginourScenecanbeasneakyhitonourperformance.

ThisfunctionisaperfectexampleofafunctionwecanconvertintoaCoroutinetomakeuseoftheirdelayed-invocationproperties:

voidStart(){

StartCoroutine(UpdateAI());

}

IEnumeratorUpdateAI(){

while(true){

yieldreturnnewWaitForSeconds(_aiUpdateFrequency);

ProcessAI();

}

}

However,thisapproachhasitsdrawbacks.Forone,aCoroutinecomeswithanadditionaloverheadcostrelativetoastandardfunctioncall(aroundtwiceasslow),aswellassomeheapmemoryallocationstostorethecurrentstateinmemoryuntilthenexttimeitisinvoked.Secondly,onceinitialized,Coroutinesrunindependent,oftheGameObject’sUpdate()processandwillbeinvokedregardlessofwhethertheGameObjecthasbeendisabledornot.Caremustbetakenbeforedecidingtoadoptthisapproach.

However,ifthesituationisappropriate,thebenefitsofcallingnothingduringmostframes,oftenoutweighstheadditionalcostduringtheframeswhereitisinvoked.Indeed,ifwearen’tperformingtoomanycomplexthingswithyieldstatements,thenwecanoftencreateanevensimplerversionofthemethodusingInvokeRepeating(),whichhasaslightlysmalleroverheadcost(about1.5timesslowerthanastandardfunctioncall):

voidStart(){

InvokeRepeating("ProcessAI",0f,_aiUpdateFrequency);

}

NotethatInvokeRepeatingisalsoindependentoftheGameObject’sUpdate()method,

http://freepdf-books.com

Page 139: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

andwillcontinuetobeinvokedeveniftheobjectisdisabled.

Regardlessofwhichapproachwepick,thereisanadditionalrisk—havingtoomanymethodstriggeringinthesameframesimultaneously.ImaginethousandsoftheseobjectsthatinitializedtogetherduringSceneinitialization.Everytime_aiUpdateFrequencysecondsgoby,theywillallinvoketheProcessAI()methodwithinthesameframe,andcauseahugespikeinCPUusage.

Possiblesolutionstothisprobleminclude:

GeneratinganewrandomtimetowaiteachtimethetimerexpiresorCoroutinetriggersSpreadoutCoroutineinitializationsothatonlyahandfulofthemarestartedeachframeDelegatetheresponsibilityofcallingupdatestosomemasterclassthatplacesalimitonthenumberofinvocationsthatoccureachframe

ReducingexcessiveUpdatedefinitionstoasimpleCoroutinecanpotentiallysaveusalotofunnecessaryoverhead,soweshouldconsiderconvertingthemwheneverwefeelitisappropriate.However,wemightalsoconsiderre-evaluatingoursolutiontotheoriginalprobleminordertopreventlotsoftimedeventsalltriggeringatthesamemoment.

AnotherapproachtooptimizingupdatesistonotuseUpdate()atall,ormoreaccurately,toonlyuseitonce.WhenUnitycallsUpdate(),itinvolvesbridgingthegapbetweenaGameObject’snativeandmanagedrepresentationoftheGameObject,whichcanbeacostlytask.Youwilllearnmoreaboutthisnative-managedbridgeinChapter7,MasterfulMemoryManagement,butfornow,justconsiderthateverycallbackwerelyonUnitytoinvokeforuscomeswithahiddenprocessingcostattachedrelativetoastandardfunctioncall.

Wecanthereforeminimizethisoverheadbylimitinghowoftenitneedstocrossthebridge.Wecandothisbyhavingagodclasstakecareofcallingourowncustomupdate-stylemethodacrossallofourcustomComponents,initsowndefinitionofUpdate().Infact,manyUnitydeveloperspreferthisapproachrightfromthestartoftheirprojects,asitgivesthemfinercontroloverwhenandhowupdatespropagatethroughoutthesystem,forthingssuchasmenupausingandcooltimemanipulationeffects.

Allobjectswantingtointegratewithsuchasystemmusthaveacommonentrypoint.Wecanachievethisthroughaninterfaceclass.Interfacesessentiallysetupacontractwherebyanyclassthatimplementstheinterfacemustprovideaspecificseriesofmethods.Inotherwords,ifweknowtheobjectimplementsaninterface,thenwecanbecertainaboutwhatmethodsareavailable.InC#,classescanonlyderivefromasinglebaseclass,buttheycanimplementanynumberofinterfaces(thisavoidsthe“deadlydiamondofdeath”problemthatC++programmersmaybefamiliarwith).

Thefollowinginterfacedefinitionwillsuffice,whichonlyrequirestheimplementingclasstodefineasinglemethod:

publicinterfaceIUpdateable{

voidOnUpdate(floatdt);

http://freepdf-books.com

Page 140: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

Next,we’lldefineaMonoBehaviourclass,whichimplementsthisinterface:

publicclassUpdateableMonoBehaviour:MonoBehaviour,IUpdateable

{

publicvirtualvoidOnUpdate(floatdt){}

}

Notethatwe’renamingthemethodOnUpdate()ratherthanUpdate().We’redefiningacustomversionofthesameconcept,butwewanttoavoidnamecollisionswiththestandardUpdate()callback.

TheOnUpdate()methodoftheUpdateableMonoBehaviourclassretrievesthecurrentdeltatime(dt),tospareusfromabunchofunnecessaryTime.deltaTimecalls.We’vealsomadethefunctionvirtual,toallowderivedclassestocustomizeit.However,asyouknow,UnityautomaticallygrabsandinvokesmethodsdefinedwiththenameUpdate(),butsincewe’redefiningourowncustomupdatewithadifferentname,thenweneedtoimplementsomethingthatwillcallthismethodwhenthetimeisappropriate;somekindof“GameLogic”godclass.

DuringtheinitializationofthisComponent,weshoulddosomethingtonotifyourGameLogicobjectofbothitsexistenceanditsdestruction,sothatitknowswhentostartandstopcallingitsOnUpdate()function.

Inthefollowingexample,wewillassumethatourGameLogicclassisaSingletonComponent,asdefinedearlierinthesectionentitledSingletonComponents,andhasappropriatestaticfunctionsdefinedforregistrationandderegistration(althoughbearinmindthatitcanjustaseasilyuseourmessagingsystem!).

ForMonoBehaviourstohookintothissystem,themostappropriateplaceiswithinStart()andOnDestroy():

voidStart(){

GameLogic.Instance.RegisterUpdateableObject(this);

}

voidOnDestroy(){

GameLogic.Instance.DeregisterUpdateableObject(this);

}

ItisbesttousetheStart()methodforthistask,sinceusingStart()meansthatwecanbecertainallotherpre-existingComponentswillhaveatleasthadtheirAwake()methodscalledpriortothismoment.Thisway,anycriticalinitializationworkwillhavealreadybeendoneontheobjectbeforewestartinvokingupdatesonit.

Notethat,becausewe’reusingStart()inaMonoBehaviourbaseclass,ifwedefineaStart()methodinaderivedclass,thenitwilleffectivelyoverridethebase-classdefinitionandUnitywillgrabthederivedStart()methodasacallbackinstead.Itwould,therefore,bewisetoimplementavirtualInitialize()methodsothatderivedclassescanoverrideittocustomizeinitializationbehaviorwithoutinterferingwiththebaseclass’staskofnotifyingtheGameLogicobjectofourcomponent’sexistence.

http://freepdf-books.com

Page 141: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Forexample:

voidStart(){

GameLogic.Instance.RegisterUpdateableObject(this);

Initialize();

}

protectedvirtualvoidInitialize(){

//derivedclassesshouldoverridethismethodforinitializationcode

}

Weshouldtrytomaketheprocessasautomaticaspossibletospareourselveshavingtore-implementthesetasksforeachnewComponentwedefine.AssoonasaclassinheritsfromourUpdateableMonoBehaviourclass,thenshouldbesecureintheknowledgethatitsOnUpdate()methodwillbecalledwheneveritisappropriate.

Finally,weneedtoimplementtheGameLogicclass.TheimplementationisprettymuchthesamewhetheritisaSingletonComponentorastandaloneComponent,andwhetherornotitusestheMessagingSystem.Eitherway,ourUpdateableMonoBehaviourclassmustregisterandderegisterasIUpdateableObjectobjects,andtheGameLogicclassmustuseitsownUpdate()callbacktoiteratethrougheveryregisteredobjectandcalltheirOnUpdate()function.

HereistheclassdefinitionfortheGameLogicsystem:

publicclassGameLogic:SingletonAsComponent<GameLogic>{

publicstaticGameLogicInstance{

get{return((GameLogic)_Instance);}

set{_Instance=value;}

}

List<IUpdateableObject>_updateableObjects=newList<IUpdateableObject>();

publicvoidRegisterUpdateableObject(IUpdateableObjectobj){

if(!_Instance._updateableObjects.Contains(obj)){

_Instance._updateableObjects.Add(obj);

}

}

publicvoidDeregisterUpdateableObject(IUpdateableObjectobj){

if(_Instance._updateableObjects.Contains(obj)){

_Instance._updateableObjects.Remove(obj);

}

}

voidUpdate(){

floatdt=Time.deltaTime;

for(inti=0;i<_Instance._updateableObjects.Count;++i){

_Instance._updateableObjects[i].OnUpdate(dt);

}

}

}

IfwemakesureallofourcustomMonoBehavioursinheritfromthe

http://freepdf-books.com

Page 142: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UpdateableMonoBehaviourclass,thenwe’veeffectivelyreplacedNinvocationsoftheUpdate()callbackwithjustoneUpdate()callback,plusNvirtualfunctioncalls.Thiscansaveusalargeamountofperformanceoverhead,becauseeventhoughwe’recallingvirtualfunctions,we’restillkeepingtheoverwhelmingmajorityofupdatebehaviorinsidemanagedcode,andavoidingthenative-managedbridgeasmuchaspossible.

Dependingonhowdeepyoualreadyareintoyourcurrentproject,suchchangescanbeincrediblydaunting,time-consuming,andlikelytointroducealotofbugsassubsystemsareupdatedtomakeuseofacompletelydifferentsetofdependencies.However,thebenefitscanoutweightherisksiftimeisonyourside.ItwouldbewisetodosometestingonagroupofobjectsinaScenethatissimilarlydesignedtoyourcurrentScenefilestoverifyifthebenefitsoutweighthecosts.

http://freepdf-books.com

Page 143: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 144: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ConsidercachingTransformchangesTheTransformComponentonlystoresdatarelativetoitsownparent.ThismeansthataccessingandmodifyingaTransformComponent’sposition,rotation,andscalepropertiescanresultinalotofunanticipatedmatrixmultiplicationcalculationstogeneratethecorrectTransformrepresentationfortheobjectthroughitsparents’Transforms.ThedeepertheobjectisintheHierarchy,themorecalculationsareneededtodeterminethefinalresult.Tomakemattersworse,changestoaTransformComponentalsosendinternalnotificationstocolliders,rigidbodies,lights,andcameras,whichmustbeprocessed.

However,thisalsomeansthatusinglocalPosition,localRotation,andlocalScalehavearelativelytrivialcostassociatedwiththem,becausethevaluescanberetrievedandwrittenastheyarepassedin.Therefore,theselocalpropertyvaluesshouldbeusedwheneverpossible.However,changingourmathematicalcalculationsfromworldspacetolocalspacecanovercomplicatewhatwereoriginallysimple(andsolved!)problems,somakingsuchchangesrisksbreakingourimplementationandintroducingalotofunexpectedbugs.Sometimesit’sworthabsorbingaminorperformancehitinordertosolveacomplex3Dmathematicalproblemmoreeasily!

Inaddition,itisnotuncommon,duringsomecomplexevent,wereplaceaTransform’spropertiesmultipletimesinthesameframe(althoughthisisprobablyawarningsignofover-engineereddesign).WecanconsiderminimizingthenumberoftimeswemodifytheTransformvaluesbycachingtheminamembervariableandcommittingthemonlyattheendoftheframe,asfollows:

privatebool_positionChanged;

privateVector3_newPosition;

publicvoidSetPosition(Vector3position){

_newPosition=position;

_positionChanged=true;

}

voidFixedUpdate(){

if(_positionChanged){

transform.position=_newPosition;

_positionChanged=false;

}

}

ThiscodewillonlycommitchangestothepositioninthenextFixedUpdate()method.

Notethatthiswillnotresultinsluggish-lookingbehaviorduringgameplay,sinceallphysicscalculationsareperformedimmediatelyafterFixedUpdate().TherewouldnotbeanyframesrenderedbeforethephysicsenginegetsachancetorespondtotheTransformchange.

http://freepdf-books.com

Page 145: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 146: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

FasterGameObjectnullreferencechecksItturnsoutthatperforminganullreferencecheckagainstaUnityobjectinvokesamethodontheothersideofthenative-managedbridge(mentionedearlierandexploredinmoredetailinChapter7,MasterfulMemoryManagement),which,asexpected,resultsinsomeunnecessaryperformanceoverhead:

if(gameObject!=null){

//dostuffwithgameObject

}

Thereisasimplealternativethatgeneratesafunctionallyequivalentoutput,butoperatesaroundtwiceasquickly(althoughitdoesobfuscatethepurposeofthecodealittle):

if(!System.Object.ReferenceEquals(gameObject,null)){

//dostuffwithgameObject

}

ThisappliestobothGameObjectsandComponents,aswellasotherUnityobjects,whichhavebothnativeandmanagedrepresentations.However,somerudimentarytestingrevealsthateitherapproachstillconsumesmerenanosecondsonanIntelCorei53570Kprocessor.So,unlessyouareperformingmassiveamountsofnullreferencechecks,thenthegainsmightbemarginalatbest.

However,itisnoteworthyinthesensethattherecanbemanyothersimplealternativesthathaveyettobediscovered,whichcanhelpimproveperformancebycircumventingthenative-managedbridge.

http://freepdf-books.com

Page 147: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 148: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryThischapterintroducedyoutomanymethodsofimprovingyourscriptingpracticesintheUnityEngine,withtheaimofimprovingperformanceif(andonlyif)youhavealreadyproventhemtobethecauseofaperformanceproblem.Someofthesetechniquesdemandsomeforethoughtandprofilinginvestigationbeforebeingimplemented,sincetheyoftencomewithintroducingadditionalrisksorobfuscatingourcodebasefornewdevelopers.Workflowisoftenjustasimportantasperformanceanddesign,sobeforeyoumakeanyperformancechangestothecode,youshouldconsiderwhetherornotyou’resacrificingtoomuchonthealtarofperformanceoptimization.

Wewillinvestigatemoreadvancedscriptingimprovementtechniqueslater,inChapter7,MasterfulMemoryManagement,butlet’stakeabreakfromstaringatcodeandexploresomewaystoimproveapplicationperformanceusingbuilt-inUnityfeaturessuchasStaticandDynamicBatching.

http://freepdf-books.com

Page 149: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 150: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter3.TheBenefitsofBatchingIn3Dgraphicsandgames,batchingisaverygeneraltermdescribingtheprocessofgroupingalargenumberofwaywardpiecesofdataandprocessingthemtogetherasasingle,largeblockofdata.Thegoalofthisprocessistoreducecomputationtime,oftenbyexploitingparallelprocessingorreducingoverheadcosts,iftheentirebatchistreatedasindividualelements.Insomecases,theactofbatchingcentersaroundmeshes,largesetsofvertices,edges,UVcoordinates,andsoon,whichareusedtorepresenta3Dobject.However,thetermcouldjustaseasilyrefertotheactofbatchingaudiofiles,sprites,andtexturefiles(alsoknownasAtlasing),andotherlargedatasets.

So,justtoclearupanyconfusion,whenthetopicofbatchingismentionedinUnity,itisusuallyreferringtothetwoprimarymechanismsitoffersforbatchingmeshfiles:StaticandDynamicBatching.Thesemethodsareessentiallyaformofgeometryinstancing,whereweusethesamemeshdatainmemorytorepeatedlyrenderthesameobjectmultipletimeswithoutneedingtopreparethedatamorethanonce.

Thesebatchingfeaturesofferusopportunitiestoimprovetheperformanceofourapplication,butonlyaslongastheyareusedwisely.Theyarefairlynuancedsystems,andtherehasbeenalotofconfusionsurroundingtheconditionsthattheyaretriggeredunder,andjustasimportantly,underwhatconditionswewouldevenseeaperformanceimprovement.Insomecases,batchingcanactuallydegradeperformanceifbatchesareaskedtoprocessdatasetsunderconditionsthatdon’tfitaveryparticularmold.

ThebatchingsystemsinUnityaremostlyablackbox,inwhichUnitytechnologieshavenotrevealedmuchdetailed,technicalinformationabouttheirinnerworkings.But,basedontheirbehavior,profilerdata,andthelistofrequirementsneededtomakethemwork,wecanstillinferagreatdeal.Thischapterintendstodispelmuchofthemisinformationfloatingaroundaboutbatchingsystems.Wewillobserve,viaexplanation,exploration,andexamples,justhowthesetwobatchingmethodsoperate.Thiswillenableustomakeinformeddecisions,makingthemostofthemtoimproveourapplication’sperformance.

http://freepdf-books.com

Page 151: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DrawCallsBeforewediscussStaticandDynamicBatchingindependently,let’sfirstunderstandtheproblemsthattheyarebothtryingtosolvewithinthegraphicspipeline.Wewilltrytokeepfairlylightonthetechnicalities.WewillexplorethistopicingreaterdetailinChapter6,DynamicGraphics.

TheprimarygoalofthesebatchingmethodsistoreducethenumberofDrawCallsrequiredtorenderallobjectsinthecurrentview.Atitsmostbasicform,aDrawCallisarequestsentfromtheCPUtotheGPU,askingittodrawanobject.But,beforeaDrawCallcanberequested,severalimportantcriterianeedtobemet.Firstly,meshandtexturedatamustbepushedfromtheCPUmemory(RAM)intoGPUmemory(VRAM),whichtypicallytakesplaceduringinitializationoftheScene.Next,theCPUmustpreparetheGPUbyconfiguringtheoptionsandrenderingfeaturesthatareneededtoprocesstheobjectthatisthetargetoftheDrawCall.

ThesecommunicationtasksbetweentheCPUandGPUtakeplacethroughtheunderlyinggraphicsAPI,whichcouldbeeitherDirectXorOpenGLdependingontheplatformwe’retargetingandcertaingraphicssettings.TheseAPIsfeaturemanycomplexandinterrelatedsettings,statevariables,anddatasetsthatcanbeconfigured,andtheavailablefeatureschangeenormouslybasedonthehardwaredevicewe’reoperatingon.ThemassivearrayofsettingsthatcanbeconfiguredbeforerenderingasingleobjectisoftencondensedintoasingletermknownastheRenderState.UntiltheseRenderStateoptionsarechanged,theGPUwillmaintainthesameRenderStateforallincomingobjectsandrendertheminasimilarfashion.

ChangingtheRenderStatecanbeatime-consumingprocess.Wewon’tgotoodeeplyintotheparticularsofthis,butessentiallytheRenderStateisacollectionofglobalvariablesthataffecttheentiregraphicspipeline.Changingaglobalvariablewithinaparallelsystemismucheasiersaidthandone.AlotofworkmusthappenontheGPUtosynchronizetheoutcomeofthesestatechanges,whichofteninvolveswaitingforthecurrentbatchtofinish.InamassivelyparallelsystemsuchasaGPU,alotofvaluabletimecanbelostwaitingforonebatchtofinishbeforebeginningthenext.ThingsthatcantriggerthissynchronizationmayincludepushinganewtextureintotheGPU,changingaShader,changinglightinginformation,shadows,transparency,andchangingalmostanysettingwecanthinkof.

OncetheRenderStatehasbeenconfigured,theCPUmustdecidewhatmeshtodraw,whatMaterialitshoulduse,andwheretodrawtheobjectbasedonitsposition,rotation,andscale(allrepresentedwithinasingletransformmatrix).InordertokeepthecommunicationbetweenCPUandGPUverydynamic,newrequestsarepushedintoaCommandBuffer.Thisisabufferedlist,whichtheCPUsendsinstructionsto,andwhichtheGPUpullsfromwheneveritfinishesthepreviouscommand.TheCommandBufferbehaveslikeaFirstInFirstOut(FIFO)queue,andeachtimetheGPUfinishesonecommand,itpopstheoldestcommandfromthefrontofthequeue,processesit,andrepeatsuntiltheCommandBufferisempty.

http://freepdf-books.com

Page 152: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

NotethatanewDrawCalldoesnotnecessarilymeanthatanewRenderStatemustbeconfigured.IftwoobjectssharetheexactsameRenderStateinformation,thentheGPUcanimmediatelybeginrenderingthenewobjectsincethesameRenderStateismaintainedafterthelastobjectwasfinished.

Becausetherenderingprocessrequirestwohardwarecomponentstoworkintandem,itisverysensitivetobottlenecks,whichcouldoriginateinoneorbothcomponents.GPUscanrenderindividualobjectsincrediblyquickly,soiftheCPUisspendingtoomuchtimegeneratingDrawCallcommands(orsimplygeneratingtoomanyofthem),thentheGPUwillwaitforinstructionsmoreoftenthanitisworking.Inthiscase,ourapplication’sgraphicswouldbeCPU-bound.We’respendingmoretimewaitingontheCPUtodecidewhattodraw,thantheGPUspendsdrawingit.Conversely,beingGPU-boundmeanstheCommandBufferfillsupwithrequestsastheGPUcannotprocessrequestsfromtheCPUquicklyenough.

NoteYouwilllearnmoreaboutwhatitmeanstohaverenderingbottlenecksineithertheCPUorGPU,andhowtosolvebothcases,inChapter6,DynamicGraphics.

Anothercomponentwhichcanimpedethespeedofgraphicsactivityinthischainofeventsiswithinthehardwaredriver.ThiscomponentmediatescommandscomingthroughthegraphicsAPI,whichcancomefrommultiplesourcessuchasourapplication,otherapplications,andeventheOperatingSystemitself(suchasrenderingthedesktop).Becauseofthis,usingupdateddriverscansometimesresultinafairlysignificantincreaseinperformance!

Next-generationgraphicsAPIs,suchasMicrosoft’sDirectX12,Apple’sMetal,andtheKronosGroup’sVulcan,allaimtoreducetheoverheadonthedriverbysimplifyingandparallelizingcertaintasks;particularly,howinstructionsarepassedintotheCommandBuffer.OncetheseAPIsbecomecommonplace,wemaybeabletogetawaywithusingsignificantlymoreDrawCallscomfortablywithinourapplication.ButuntiltheseAPIsmature,wemusttreatourDrawCallconsumptionwithagooddealofconcern,inordertoavoidbecomingCPU-bound.

http://freepdf-books.com

Page 153: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 154: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MaterialsandShadersShadersareshortprogramswhichdefinehowtheGPUshouldrenderincomingvertexandpixeldata.AShaderonitsowndoesnothavethenecessaryknowledgeofstatetoaccomplishanythingofvalue.Itrequiresinputssuchasdiffusetextures,normalmaps,colors,andsoon,andmustdecidewhatRenderStatevariablesarerequiredinordertocompleteitsintendedtask.

Unity’sMaterialsystemisessentialtoprovidingthisinformationtoourShaders.Ultimately,thisjustmeansaShaderisdependentuponaMaterialinordertobeusedtorenderanobject.EveryShaderneedsaMaterial,andeveryMaterialmusthaveaShader.EvennewlyimportedmeshesthatareintroducedintotheScenewithoutanyassignedMaterialsareautomaticallyassignedadefault(hidden)Material,whichgivesthemabasicdiffuseShaderandawhitecoloration.So,thereisnowayofgettingaroundthisrelationship.

NoteAsingleMaterialcanonlysupportasingleShader.TheuseofmultipleShadersonthesamemeshrequiresseparateMaterialstobeassignedtodifferentpartsofthesamemesh.

ThesetwosystemscapturethemajorityoftheRenderStatevariableswediscussedintheprevioussection.Asaresult,ifwecanminimizethenumberofMaterialsbeingusedtorendertheScene,thenweminimizetheamountofRenderStatechangesrequired,andhencereducetheamountoftimetheCPUspendspreparingtheGPUeachframe.

Let’sbeginwithasimpleSceneinordertovisualizethebehaviorofMaterialsandbatching.But,beforewestart,weshoulddisableseveralglobaloptionsforrenderingfeaturestoavoiddistractingourselveswithadvancedrenderingfeatures:

NavigatetoEdit|ProjectSettings|QualityandsetShadowstoDisableShadows(orselectthedefaultFastestqualitylevel)NavigatetoEdit|ProjectSettings|Player,opentheOtherSettingstab,anddisableStaticBatching,DynamicBatching,andGPUSkinningiftheyareenabled

TipTheStaticBatchingandGPUSkinningoptionsarenotavailableinUnity4FreeEdition,andrequireanupgradetoUnity4ProEdition.

Next,we’llcreateaScenethatcontainsasingleDirectionalLightandeightmeshes;fourcubes,andfourspheres,whereeachobjecthasitsownuniqueMaterial,position,rotation,andscale:

http://freepdf-books.com

Page 155: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

IfweobservetheBatchingvalueintheGameView’sStatspopup,weseeninetotalbatches(notethatthisvaluewillbelabeledDrawCallsintheUnity4Statspopup).UnlesstheCamera’sClearFlagssettingissettoDon’tClear,thenonebatchwillbeconsumeddrawingtheCamerabackground.ThiscouldbetheScene’sSkyboxorasinglequadthatfillsthescreenwithallpixelscoloredaspertheCamera’sBackgroundcolorproperty.

Thenexteightbatchesareusedtodrawoureightobjects.Ineachcase,theDrawCallinvolvespreparingtherenderingsystemusingtheMaterial’spropertiesandaskingtheGPUtorenderthegivenmeshatitscurrentposition,rotation,andscale.TheMaterialalsodefineswhichShaderisused,whichcontrolstheprogrammablepartsofthegraphicspipeline(vertexandfragmentsteps).

NotethatiftheRenderingPathsettingunderthePlayerSettingsissettoForward,thenwecanenableanddisabletheDirectionalLightinourSceneandthenumberofbatchesremainsatnine.ThefirstDirectionalLightinForwardrenderingiseffectivelyfreeatleastintermsofDrawCalls.AssoonasweaddmoreLightstoourScene,whethertheyareDirectional,Point,Spot,orAreaLights,wecauseallobjectstoberenderedwithanadditional“pass”throughtheShaderforeachLight,uptothevalueofthePixelLightCountvalueundertheQualitySettings(lightswithhighbrightnessvaluesareprioritizedfirst).

NoteLightingoptionscanbecomeasignificantsourceofDrawCalls,andyouwilllearnmoreaboutthissysteminChapter6,DynamicGraphics.

Aspreviouslymentioned,wecantheoreticallyminimizethenumberofDrawCallsby

http://freepdf-books.com

Page 156: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

reducinghowoftenwecausethesystemtochangeRenderStateinformation.So,partofthegoalthereforeistoreducetheamountofMaterialsweuse.But,ifwesetallobjectstousethesameMaterial,wedon’tseeanybenefitandthenumberofbatchesremainsatnine:

Thisisbecausewe’renotactuallyreducingthenumberofRenderStatechangesnorefficientlygroupingmeshinformation.Withoutanyformofbatching,therenderingsystemisnotsmartenoughtorealizewe’reoverwritingtheexactsameRenderStatevalues,andthenaskingittorenderthesamemeshes,overandoveragain.Thispresentsanopportunitytohavetherenderingprocessrecognizethesesituations,renderallofthesemeshestogetherasoneobject,andavoidunnecessaryDrawCalls.ThisisbasicallyhowDynamicBatchingworkstoreduceourDrawCalls.

http://freepdf-books.com

Page 157: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 158: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DynamicBatchingThepurposeofDynamicBatchingistobundletogetherlargegroupsofsimplemeshesandpushthemthroughtherenderingsystemasifitwasasinglemesh.OnlymeshesthatarecurrentlyvisibleintheCameraviewarecandidatesforDynamicBatching,whichmeansthatmostofthebatchingworkisaccomplishedatruntime,ratherthanpre-calculated.Thismeansthattheobjectsthatarebatchedtogetherwillvaryfromframetoframe.Hence,thename“Dynamic”Batching.

IfwereturntothePlayerSettingspageandenableDynamicBatching,weshouldseethatthenumberofbatchesdropsfromninedowntosix.DynamicBatchingisautomaticallyrecognizingthatourobjectsshareMaterialandmeshinformationandcancombinethemintoasinglebatchforprocessing.ThisisadecentCPUcost-savingstechniqueandreducesthelikelihoodthatourgamewithbeCPU-bound,sinceitfreesupmoretimeforothertasks,suchasAIandPhysicsprocessing.

Attheriskofsoundingungrateful,weshouldaskourselveswhyweonlysavethreeDrawCalls,andnotsix.Wewouldhopethatthesystemissmartenoughtogroupallofthecubestogetherinonebatchandallofthespheresinanother,takingonlytwoDrawCallstorenderthemall(plusoneDrawCallforthebackground).

ThecompletelistoftherequirementsneededtosuccessfullydynamicallybatchameshcanbefoundintheUnitydocumentationathttp://docs.unity3d.com/Manual/DrawCallBatching.html.

AllmeshinstancesmustusethesameMaterialreferenceOnlyparticlesystemsandmeshrenderersaredynamicallybatched.Skinnedmeshrenderers(foranimatedcharacters)andallotherrenderablecomponenttypescannotbebatchedThetotalnumberofvertexattributesusedbytheShadermustbenogreaterthan900Eitherallmeshinstancesshoulduseauniformscaleorallmeshesshoulduseanonuniformscale,butnotamixtureofthetwoMeshinstancesshouldrefertothesameLightmapfileTheMaterial’sShadershouldnotdependonmultiplepassesMeshinstancesmustnotreceivereal-timeShadows

TherearealsoacoupleofundocumentedrequirementsthathavebeenrevealedduringsomeUniteConferencepanels:

Thereisalimitof300meshesperbatchTheremustbenomorethan32,000meshindicesintheentirebatch

However,acoupleoftheserequirementsarenotcompletelyintuitiveorclearfromthedescription,whichmeritssomeadditionalexplanation.

http://freepdf-books.com

Page 159: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

VertexattributesAvertexattributeisapropertycontainedwithinameshfileonapervertexbasis.Thisincludes,butisnotlimitedto,avertex’sposition,anormalvector(mostoftenusedinlightingcalculations),andUVcoordinates(usedtodefinehowatexturewrapsaroundthemesh).Onlymesheswithlessthan900totalvertexattributesusedbytheShadercanbeincludedinDynamicBatching.

TipNotethatlookingintoamesh’srawdatafilemaycontainlessvertexattributeinformationthanUnityloadsintomemorybecauseofhowtheengineconvertsmeshdatafromoneofseveralrawdataformatsintoaninternalformat.

UsingmoreattributedatapervertexwithintheaccompanyingShaderwillconsumemorefromour900-attributebudgetandhencereducethenumberofverticesthemeshisallowedtohavebeforeitcannolongerbeusedinDynamicBatching.Forexample,asimpleShaderwhichonlyusesthreeattributespervertex,suchassomeofthelegacydiffuseShaders,cansupportDynamicBatchingusingmesheswithupto300vertices.ButamorecomplexShader,requiringfiveattributespervertex,canonlysupportDynamicBatchingwithmeshesupto180vertices.

ThisrestrictioniswhyourSceneonlysavesthreeDrawCallswithDynamicBatchingenabled,despitehavingallobjectssharethesameMaterialreference.ThecubethatisautogeneratedbyUnitycontains8verticeseachwithposition,normal,andUVdata,for24attributesintotal.Thisisfarlessthanthe900-vertexattributelimitwhenallofthisdataisusedbytheShader.However,anautogeneratedspherecontains515vertices,whichclearlycannotbedynamicallybatchedifwecountaposition,normal,andUVcoordinateforeachvertex.ThisexplainsoursixDrawCalls:oneforthebackground,oneforabatchedgroupofcubes,andfourforthespheresthatarenotbeingdynamicallybatched,whichmustberenderedwithseparateDrawCalls.

http://freepdf-books.com

Page 160: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UniformscalingThedocumentationsuggeststhat,generally,objectsshouldeithershareauniformscaleoreachhaveauniquenonuniformscaleinordertobeincludedindynamicbatching.But,inreality,thebehaviorofthisrestrictionchangesslightlydependingonwhichversionofUnitywearerunningduetosomechangestotheDynamicBatchingsysteminUnity5.

TipAuniformscalemeansthatallthreecomponentsofthescalevector(x,y,andz)areidentical.

InbothversionsofUnity,ifallinstancesofameshhaveauniformscale,thentheycanbegroupedtogetherinthesamedynamicbatch.InUnity5,itwilldynamicallybatchallnonuniformlyscaledinstancesofthemeshwiththeoriginalbatch,nomattertheirscale.However,inUnity4,nonuniformlyscaledobjects,usingthesamemeshandMaterial,willbegroupedtogetherintoseparatebatches.

Thisassumeswe’reworkingwithpositivescales.Thescalerestrictiongetsalittleunintuitivewhenwe’redealingwithnegativescales.InUnity4,negativescalesdonotaffectDynamicBatchingandallofthesamerulesapplyasbefore.But,inUnity5,ifthemeshhasoneorthreenegativevaluesinitsscalevector,thenitwillnotbeincludedinthebatch.Ifitcontainstwonegativevalues,thenitcanbebatchedalongwithalloftheotherinstances.Itdoesnotevenmatterwhichofthethreevaluesarenegative,onlythattherearezeroortwoofthem.

Presumably,thisisabi-productofthealgorithmusedtodetectvalidbatchablegroups,sincemirroringameshintwodimensionsismathematicallyequivalenttorotatingthemeshaboutbothofthesameaxes180degrees.Thus,thebehaviorweobserveisjusttheDynamicBatchingsystemautomaticallytransformingtheobjectforus.

So,itisworthkeepinginmindthatDynamicBatchingisalittlemoreefficientinUnity5,butithassometrade-offs.Ifwewishtousenegativescalesasashortcuttomirroramesh,thenitwillbeincapableofbeingDynamicallyBatched.

http://freepdf-books.com

Page 161: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DynamicBatchingsummaryTherewereclearlysomesignificantimprovementsmadetotheDynamicBatchingsysteminUnity5,allowingittobemoreversatiletoavarietyofsituations.However,nomatterwhichversionofUnityweareusing,DynamicBatchingisveryusefulwhenwewishtorenderverylargegroupsofsimplemeshes.

Thedesignofthesystemmakesitidealtousewhenallofthemesheswe’reDynamicallyBatchingaresimpleandnearlyidenticalinappearance.PossiblesituationstoapplyDynamicBatchingcouldbeasfollows:

Alargeforestfilledwithrocks,trees,andbushesAbuilding,factory,orspacestationwithmanycommonelements(computers,pipes,andsoon)throughouttheSceneAgamefeaturingmanydynamic,nonanimatedobjectswithsimplegeometryandparticleeffects(agamesuchasGeometryWarsspringstomind)

ThepotentialbenefitsofDynamicBatchingaresignificantenoughtosetasidesometimetoinvestigateifandwherewecanmakeuseofitinourScene.TherearenottoomanyoccasionswhereDynamicBatchingwouldactuallydegradeperformance.

ThemostcommonmistakewithDynamicBatchingistosetupaScenethatgenerateslotsofbatches,whicheachcontainonlyahandfulofmeshes.Inthesecases,theoverheadcostofdetectingandgeneratingthebatchesmightcostmorethanthetimeitsavesjustmakingaseparateDrawCallforeachmesh.

Inaddition,we’refarmorelikelytoinflictperformancelossesonourapplicationbysimplyassumingDynamicBatchingistakingplace,whenwe’veactuallyforgottenoneoftheessentialrequirements.Everysituationisunique,soitisworthexperimentingwithourMaterials,meshes,andShaderstodeterminewhatcanandcannotbedynamicallybatched.

http://freepdf-books.com

Page 162: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 163: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

StaticBatchingUnityoffersasecondbatchingmechanismthroughStaticBatching.ThepurposeofthisfeatureistograntusawaytobatchnonidenticalmeshesofanysizeintoasinglebatchwithasimilargoalandmethodologytoDynamicBatching,butsolvingtheproblemforadifferentsetofconditions.TheessentialdifferencebetweenthetwobatchingmethodsisthatStaticBatchingoccursduringapplicationinitialization,whereasDynamicBatchingtakesplaceatruntime.WethereforehavealotmorecontroloverwhenandwhereStaticBatchingtakesplace.

NoteStaticBatchingisavailableinalleditionsofUnity5,butonlyintheProEditionofUnity4.Unity4FreeuserswillneedtoupgradetotheProEditiontomakeuseofthisfeature.

TheStaticBatchingsystemhasitsownsetofrequirements:

Asthenameimplies,themeshesmustbeflaggedasStaticAdditionalmemorymustbesetasideforeachmeshbeingstaticallybatchedThemeshinstancescancomefromanysourcemesh,buttheymustsharethesameMaterial

Let’scovereachoftheserequirementsinmoredetail.

http://freepdf-books.com

Page 164: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheStaticflagStaticBatchingcanonlybeappliedtoobjectswiththeStaticflagenabledor,morespecifically,theBatchingStaticsubflag(alsoknownasStaticEditorFlags).ClickingonthedownarrownexttotheStaticoptionforaGameObjectwillrevealadropdownoftheseStaticEditorFlags,whichcanaltertheobject’sbehaviorforvariousStaticprocesses.

http://freepdf-books.com

Page 165: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MemoryrequirementsTheadditionalmemoryrequirementforStaticBatchingwillvarydependingontheamountofreplicationoccurringwithinthebatchedmeshes.StaticBatchingworksbycombiningallflaggedmeshesintoasingle,largemesh,andpassingitintotherenderingsystemthroughasingleDrawCall.Ifallofthemeshesbeingstaticallybatchedareunique,thenthiswouldcostusnoadditionalmemoryusagecomparedtorenderingtheobjectsnormally,asthesameamountofmemoryspaceisrequiredtostorethemeshes.

However,staticallybatchedduplicatescostusadditionalmemoryequaltothenumberofmeshesmultipliedbythesizeoftheoriginalmesh.Ordinarily,renderingone,ten,oramillionclonesofthesameobjectcostsusthesameamountofmemory,becausethey’reallreferencingthesamemeshdata.Theonlydifferenceisthetransformofeachobject.But,becauseStaticBatchingneedstocopythedataintoalargebuffer,completewithitstransformdata,thisreferencingislost,andanewduplicateoftheoriginalmeshiscopiedintothebufferwithahard-codedtransformposition,regardlessofwhetherthesamemeshhasalreadybeencopiedin.

Therefore,usingStaticBatchingtorender1,000identicaltreeobjectswillcostus1,000timesmorememorythanrenderingthesameobjectsnormally,becauseeachtreemustbecopiedintotheStaticBatchingbufferasauniquesetofvertexdata.ThiscausessomesignificantmemoryconsumptionandperformanceissuesifStaticBatchingisnotusedwisely.

http://freepdf-books.com

Page 166: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MaterialreferencesFinally,wealreadyknowaboutsharingmaterialreferencesasameansofreducingRenderStatechanges,sothisrequirementisfairlyobvious.However,sometimeswe’restaticallybatchingmeshesthatrequiremultiplematerials.Inwhichcase,allmeshesusingadifferentmaterialwillbegroupedtogetherintheirownstaticbatch,andagainforeachuniquematerialbeingused.

Thedownsidetothisdesignfeatureisthat,atbest,StaticBatchingcanonlyrenderallofthestaticmeshesusinganumberofDrawCallsequaltothenumberofmaterialstheyneed.But,thebenefitisthatwecancontrolwhichmeshesgetbatchedtogetherusingdifferentmaterials,effectivelyforcingittostartanewstaticbatchthroughsomecunningmaterialduplication.ThiswillbecomeclearafterwecoversomeoftheStaticBatchingsystem’scaveats.

http://freepdf-books.com

Page 167: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

StaticBatchingcaveatsTheStaticBatchingsystemisnotwithoutitsdrawbacks.Becauseofhowitapproachesthebatchingsolution,bycombiningmeshesintoasinglegreatermesh,theStaticBatchingsystemhasafewcaveatsthatweneedtobeawareof.TheseconcernsrangefromminorinconveniencestomajordrawbacksdependingontheScene:

DrawCallsavingsarenotimmediatelyvisiblefromtheStatswindowuntilruntimeStaticobjectsshouldnotbeintroducedtotheSceneatruntimeStaticallybatchedmeshescannotbemovedfromtheiroriginalstartingtransformIfanyoneofthestaticallybatchedmeshesisvisible,thentheentiregroupwillberendered

EditModedebuggingofStaticBatchingTryingtodeterminetheoveralleffectthatStaticBatchingishavingonourScenecanbealittletrickysincenothingisbeingStaticallyBatchedwhileinEditMode.AllofthemagichappensduringSceneinitialization,whichcanmakeitdifficulttodeterminewhatbenefitsStaticBatchingisactuallyproviding.Thisisespeciallytrueifweleaveimplementingthisfeatureuntillateintheprojectlifecycle,wherewecanspendalotoftimelaunching,tweaking,andrelaunchingourScenetoensurewe’regettingtheDrawCallsavingswe’reexpecting.Consequently,itisbesttostartworkingonStaticBatchingoptimizationearlyintheprocessofbuildinganewScene.

AvoidinginstantiatingstaticmeshesatruntimeNewstaticobjectsintroducedintotheScenewillnotbeautomaticallycombinedintoanyexistingbatchbytheStaticBatchingsystem.Todosowouldcauseanenormousruntimeoverheadbetweenrecalculatingthemeshandsynchronizingwiththerenderingsystem,soUnitydoesnotevenattempttodoit.Thisrestrictionmeansweshouldnotattempttodynamicallyinstantiatethestaticallybatchedcontent.AllmesheswewishtostaticallybatchshouldbepresentintheoriginalScenefile.

NoteDynamicinstantiationofobjectscanbeacostlyactioninitsownright.WewillcoversolutionstothatprobleminChapter7,MasterfulMemoryManagement.

Aswiththepreviouscaveat,staticallybatchedmeshesshouldnotbemovedaftertheyhavebeenbatched,sincedoingsowouldgenerateatremendousCPUoverhead.TheStaticBatchingsystemhasalreadytakentheoriginaldataandcombineditintoanewmeshobject.MovingtheoriginalmeshesisbothimpossiblewhiletheStaticflagisenabled,andnotevenrecognizedbytheUnitysystemiftheflagisdisabledandtheobject’stransformischanged.

VisibilityandrenderingThefinalcaveatisperhapsthemostimportant.IfevenasinglevertexofaStaticallyBatchedmeshisvisibletotheCamera,thenthewholemeshwillbepushedintothe

http://freepdf-books.com

Page 168: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

renderingsystemandprocessedinitsentirely.WeneedtobesmartabouthowweuseStaticBatchingandoptimizeitsusagetopreventusrenderingagiganticmesheachandeveryframe!

Forexample,ifwehaveaScenewithmanyroomsconnectedtogetherwhichallsharethesameMaterial,thenenablingStaticBatchingforeveryroomobjectwillcauseeverysingleroomtoberenderedevenifonlyasingleroomisvisible,andeveniftheplayerisstaringstraightintoawall.SuchSceneswouldfarebetterusingOcclusionCulling(exploredinChapter6,DynamicGraphics)topreventnonvisibleroomsfrombeingrendered.

Meanwhile,largeoutdoorsceneswillfinditusefultoduplicateMaterials.Thisisausefultricktoforcesimilarobjectstobestaticallybatchedintodifferentgroups.Assigningidentical,butduplicateMaterialstodifferentsectionsoftheworldwillrenderthemthesame;however,theywillbegroupedseparately.ThiswouldincreasethenumberofDrawCalls,butallowustoreusethesameTexture,Material,andShaderfilesfortheentireScene.

DuplicatingMaterialscanbecomeabitofachorefromthemaintenanceperspective,sinceanychangesmadetooneMaterialmustalsobemadetotheothers.Hypothetically,wemightthinkwecanaccomplishthisthroughScriptbyattachingaComponentthatautomaticallyduplicatesaMaterialandassignsittothemeshduringSceneinitialization.Unfortunately,StaticBatchinghappenstooearlyintheinitializationprocessforustointerceptthroughacustomComponentsuchasthis,sothetaskmustbedonethroughtheEditor(agoodopportunitytomakeuseofEditorscripts).

http://freepdf-books.com

Page 169: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

StaticBatchingsummaryStaticBatchingisapowerful,butdangeroustool.Ifwedon’tuseitwisely,wecanveryeasilyinflictperformancelossesviamemoryconsumptionandrenderingcostsonourapplication.Italsotakesagoodamountofmanualtweakingandconfiguration.However,itdoeshaveasignificantadvantage:itcanbeusedonobjectsetsofanysize.ThereisessentiallynolimitasfarasStaticBatchingisconcerned.

http://freepdf-books.com

Page 170: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 171: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryItisclearthattheStaticandDynamicBatchingfeaturesarenosilverbullet.WecannotblindlyapplythemtoanygivenSceneandexpectimprovements.IfourapplicationandScenehappentofitaparticularsetofparameters,thenthesemethodsareveryeffectiveatreducingCPUloadandrenderingbottlenecks.But,ifnot,thensomeadditionalworkisrequiredtoprepareourScenetomatchitsfeaturerequirements.Ultimately,onlyagoodunderstandingofthebatchingsystemsandhowtheyfunctioncanhelpusdeterminewhereandwhenthisfeaturecanbeapplied.

WewillcovermoregraphicsimprovementtechniquesinChapter6,DynamicGraphics.Untilthen,let’smoveontoadifferenttopic,andlookintosomeofthemoresubtleperformanceimprovementsthatwecanachievethroughmanagingourartassetsinintelligentways.

http://freepdf-books.com

Page 172: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 173: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter4.KickstartYourArtArtisaverysubjectivearea,dominatedbypersonalopinionandpreference.Itcanbedifficulttosaywhetheronepieceofartis“better”thantheother,andit’slikelythatwewon’tbeabletofindcompleteconsensusonouropinions.Thetechnicalaspectsbehindartassetsthatsupportagame’sartistrycanalsobeverysubjective.Therearemultipleworkaroundsthatcanbeimplementedtoimproveperformance,butthesetendtoresultinalossofqualityforthesakeofspeed.Ifwe’retryingtoreachpeakperformance,thenit’simportantthatweconsultwithourteammemberswheneverwedecidetomakeanychangestoourartassetsasitisprimarilyabalancingact,whichcanbeanartforminitself.

Whetherwe’retryingtominimizeourruntimememoryfootprint,keepingthesmallestpossibleexecutablesize,maximizingloadingspeed,ormaintainingconsistencyinframerate,thereareplentyofoptionstoexplore.Therearesomemethodsthatareclearlyalwaysideal,andotherswhichmayrequirealittlemorecareandforethoughtbeforebeingadopted,astheymightresultinreducedqualityorincreasethechancesofdevelopingbottlenecksinothercomponents.

Wewillbeginexaminingaudiofiles,followedbyTexturefiles,andfinishupwithmeshesandanimations.Ineachcase,wewillinvestigatehowUnityloads,stores,andmanipulatestheseassetsduringruntime,whatouroptionsare,andwhatwecandotoavoidbehaviorthatmightgenerateperformancebottlenecks.

http://freepdf-books.com

Page 174: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AudioDependingonthescopeoftheproject,audiofilescanrangeanywherefromthelargestdiskspaceconsumer,tothesmallest.Unity,asaframework,canbeusedtobuildsmallapplicationsthatrequireonlyahandfulofsoundeffectsandasinglebackgroundtrack,ortobuildlargeexpansiveroleplayinggamesthatneedmillionsoflinesofspokendialog,musictracks,andambientsounds.ItwillbeusefultomakesenseofhowaudiofilesaremanagedinUnitytobetterunderstandwhatweshoulddoforthesakeofoptimizationinbothcases.

ManydevelopersaresurprisedtofindthatruntimeaudioprocessingcanturnintoasignificantsourceofCPUandmemoryconsumption.Audioisoftenneglectedonbothsidesofthegamingindustry;developerstendnottocommitmanyresourcestoituntilthelastminute,whileuserswillrarelydrawattentiontoit.Nobodynoticeswhentheaudioisgoodorpassable,butweallknowwhatbadaudiosoundslike;it’sinstantlyrecognizable,jarring,andguaranteedtocatchunwantedattention.Thismakesitcrucialnottosacrificetoomuchaudioclarityinthenameofperformance.

Audiobottleneckscancomefromavarietyofsources.Excessivecompression,toomuchaudiomanipulation,toomanyactiveaudioclips,inefficientmemorystoragemethods,andaccessspeedsareallwaystoinvitepoormemoryandCPUperformance.But,withalittleeffortandunderstanding,allittakesisafewtweakshereandtheretosaveusfromauser-experiencedisaster.

NoteSeveralaudiooptionsarenamedslightlydifferentlybetweenUnity4andUnity5,butthefeaturesareidenticalforallintentsandpurposes.WewillproceedusingtheUnity5nameforeachfeature.

http://freepdf-books.com

Page 175: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LoadingaudiofilesWhenweselectanimportedAudioClipintheUnityEditor,weseethatthefirstoptionisthefile’sLoadType.Therearethreepossiblesettingsavailable:

DecompressOnLoadCompressedInMemoryStreaming

TheactualmomentwhenthefileisfirstloadedwilldependonotherAudioClipsettingsandhowtheyareusedduringruntime,whichwewillexplorelater.Thisoptionmerelydefinesthemethodofloadingwhenitoccurs.

DecompressOnLoadcompressesthefileondisktosavespace,anddecompressesitintomemorywhenitisfirstloaded.Thisisthestandardmethodofloadinganaudiofile,andshouldbeusedinmostcases.

CompressedInMemoryloadsthecompressedfilestraightintomemorywhenitisloaded,anddecompressesitduringruntimewhenitisbeingplayed.ThiswillsacrificeruntimeCPUwhentheclipisplayed,butimprovesloadingspeedandreducesruntimememoryconsumption.Hence,thisoptionisbestusedforverylargeaudiofilesthatareusedfairlyfrequently,orifwe’reincrediblybottleneckedonmemoryconsumptionandarewillingtosacrificesomeCPUcyclestoplaytheAudioClip.

Finally,theStreamingoptionwillload,decode,andplayfileson-the-flyatruntimebygraduallypushingthefilethroughasmallbuffer.ThismethodusestheleastamountofmemoryforaparticularAudioClipandthelargestamountofruntimeCPU.Thiscomeswiththeunfortunatedrawbackthattheycannotbereferencedmorethanonce.AttemptingtostreammultiplecopiesofthesameAudioClipwillgenerateanewbufferforeachinstance,resultinginasignificantamountofRAMandruntimeCPUcostifusedrecklessly.Consequently,thisoptionisbestreservedforsingle-instanceAudioClipsthatplayregularlyandneverneedtooverlapwithotherinstances.Ergo,thissettingisbestusedwithbackgroundmusicandambientsoundeffectsthatneedtoplayduringthemajorityofaScene’slifetime.

ProfilingaudioWecanconfirmmuchofthisbehaviorbyplayingmultipleinstancesofanygivenAudioClipviamultipleAudioSourcesinaScene,andbenchmarkingusingtheAudioViewoftheProfilertoseehowmuchmemoryandCPUisconsumedusingthevariousLoadTypeoptions.However,beawarethattheProfileroutputforaudiomemoryandCPUconsumptioninEditorModecanbeverymisleading,sinceitperformsaudioloadingdifferentlytohowitwouldoccurinaruntimeapplication.

ThefirsttimeweloadtheEditorandenterPlayMode,theEditorwilldecompressaudiofiles,costingacertainamountofmemoryandCPUcyclesduringinitializationinordertoaccomplishthis.WecanobservethememorycostsofthisprocessintheProfilerundertheAudioArea.However,ifwerestarttheScene,thenwemaynoticethatthememoryspentondecompressingaudiofilessuddenlydropstonearly0KB,sincefileshavealreadybeen

http://freepdf-books.com

Page 176: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

decompressedandtheEditorhasflushedawaydataitnolongerneeds.Thisisnotrepresentativeofarealsituation,asapplicationswouldneedtoperformthisdecompression.

So,ifwewantaccurateaudioprofilinginUnity,weshouldruntheProfileragainstastandalone,orremote,versionofourapplicationontheintendedplatform/device.

AdditionalloadingoptionsThereisanadditionalpairofoptionsthataffectaudiofileloadingbehavior:

LoadInBackgroundPreloadAudioData

Inthetypicalusecase,whereanAudioClipisassignedtoanAudioSourceComponentinaScene,theaudiofilewillbeloadedintomemoryduringSceneinitialization.But,iftheLoadInBackgroundoptionisenabled,thenloadingtheAudioClipwillbedeferredtoabackgroundtaskthatbeginsoncetheScenehasfinishedinitializingandgameplayhasessentiallybegun.So,itstandstoreasonthatwecanimprovetheSceneloadingspeedbyenablingthisoptionforAudioClipsthatwewon’tneeduntillaterintheScene’slifetime,suchassoundeffectsusedinmid-levelcutScenes.

WecanuseanAudioClipobject’sloadStatepropertytoverifyiftheassetisloadedbeforeattemptingtouseit.But,usingtheLoadInBackgroundoptionrisksintroducingjarringbehaviorifwetrytoaccessasoundfilebeforeitisfullyloaded.Inthesecases,thesoundfilewon’tplayuntilthebackgroundloadingtaskhascompleted,inwhichcasethesoundwillprobablyplayataninappropriatemoment.

Thesecondoption,PreloadAudioData,isenabledbydefault,whichtellstheUnityEnginetoautomaticallybeginloadingthefileduringSceneinitialization.DisablingthisoptiondefersloadingtothefirstinstantthattheAudioSourceobject’sPlay()orPlayOneShot()methodsareinvokedatruntime.ThiswillcauseaspikeintheCPU,astheaudiodataisloadedfromthedisk,decompressed(ornot,dependingontheLoadTypesetting),pushedintomemory,andeventuallyplayedonceloaded.

Duetotheamountofplaybackdelay,andtheperformancecost,itisnotrecommendedtorelyonloadingoccurringatthemomentthataudioplaybackisneeded.WeshouldinsteadcontrolloadingourselvesbycallingtheAudioClipobject’sLoadAudioData()atsomeconvenientmomentbeforethefileisneeded.Moderngamestypicallyimplementconvenientstoppingpointsinlevelstoperformtaskssuchasthis,suchasanelevatorbetweenfloorsorlongcorridors,whereverylittleactionistakingplace.NotethatwecanalsomanuallycontrolthefreeingofaudiofilememoryusingtheAudioClipobject’sUnloadAudioData()method.

Solutionsinvolvingcustomloadingandunloadingofaudiodataviathesemethodswouldneedtobetailor-madetotheparticulargame,dependingonwhenAudioClipsareneeded,howlongthey’reneededfor,howScenesareputtogether,andhowplayer(s)traversethem.Thiscanrequireasignificantnumberofspecial-casechanges,testing,andassetmanagementtweakstoachieve.So,itisrecommendedtosavethisapproachasa“Nuclear

http://freepdf-books.com

Page 177: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Option”tobeusedlateinproduction,intheeventthatallothertechniqueshavenotsucceededaswellaswehoped.

http://freepdf-books.com

Page 178: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

EncodingformatsandqualitylevelsUnitysupportsthreegeneral-caseencodingformatsforaudiofiles,withafewspecificcasesthatareplatform-dependent(suchasHEVAGforthePSVitaandXMAforXBoxOne).Wewillfocusonthethreeoptionalencodingformats:

CompressedPCMADPCM

ThecompressionalgorithmusedwiththeCompressedformatwilldependontheplatformbeingtargeted.Standaloneapplications,WebGL,andothernon-mobileplatformsuseOgg-Vorbisforcompression,whilemobileplatformsuseMPEG-3(MP3).

TheaudiofilesweimportintotheUnityEnginecanbeoneofmanypopularaudiofileformats,buttheactualencodingthatisbundledintotheexecutablewillendupinoneofthepreviouslymentionedformats.StatisticsareprovidedforthecurrentlyselectedformatintheareafollowingtheCompressionFormatoption,providinganideaofhowmuchdiskspaceisbeingsavedbythecompression,andhowmuchmemorytheAudioClipwillconsumeatruntime(notethatthisalsodependsonthecurrentlyselectedLoadType).

Theencoding/compressionformatusedcanhaveadramaticeffectonthequality,filesize,andmemoryconsumptionoftheaudiofileduringruntime,andonlytheCompressedoptiongivesustheabilitytoalterthequalitywithoutaffectingthesamplingrateofthefile.ThePCMandADPCMformatsdonotprovidethisluxury,andwe’restuckwithwhateverfilesizethosecompressionformatsdecidetogiveus,unlesswe’rewillingtoreduceaudioqualityforthesakeoffilesizebyreducingthesamplingrate.

Eachencodingandcompressionformatprovidesdifferentbenefitsandpitfalls,andeachaudiofilemaybeabletosacrificeonemetricforanotherbasedonitspurposeandcontents.Ifwewishtoproperlyoptimizeourapplication’saudiofiles,thenweneedtobewillingtousealloftheavailableformatsinasingleapplicationtomakethemostofouraudiofiles.

ThePCMformatisalosslessanduncompressedaudioformat,providingacloseapproximationofanalogaudio.Ittradeslargefilesizesforhigheraudioquality,andisbestusedforveryshortsoundeffectsthatrequirealotofclaritywhereanycompressionwouldotherwisedistorttheexperience.

Meanwhile,theADPCMformatisfarmoreefficientinbothsizeandCPUconsumptionthanPCM,butcompressionresultsinafairamountofnoise.Thisnoisecanbehiddenifitisreservedforshortsoundeffectswithalotofchaos,suchasexplosions,collisions,andimpactsoundswherewemightnotbeawareofanygeneratedartefacts.

Finally,theCompressedformatwillresultinsmallfilesthathavelowerqualitythanPCM,butsignificantlybetterqualitythanADPCM,attheexpenseofadditionalruntimeCPUusage.Thisformatshouldbeusedinmostcases.Thisoptionallowsuscustomizetheresultantqualitylevelofthecompressionalgorithm,totweakqualityagainstfilesize.BestpracticeswiththeQualityslideraretosearchforaqualitylevelthatisassmallas

http://freepdf-books.com

Page 179: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

possible,butunnoticeabletousers.Someusertestingmayberequiredtofindthe“sweetspot”foreachfile.

TipDonotforgetthatanyadditionalaudioeffectsappliedtothefileatruntimewillnotplaythroughtheEditorinEditMode,soanychangesshouldbefullytestedthroughtheapplicationinPlayMode.

http://freepdf-books.com

Page 180: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AudioperformanceenhancementsNowthatwehaveabetterunderstandingofaudiofileformats,loadingmethods,andcompressionmodes,let’sexploresomeapproachesthatwecanmaketoimproveperformancethroughtweakingaudiobehavior.

MinimizeactiveAudioSourcecountSinceeachactivelyplayingAudioSourceconsumesaparticularamountofCPU,thenitstandstoreasonthatwecansaveCPUcyclesforeachredundantAudioSourcethatisplayinginourScene.OneapproachistocontrolourAudioSourcesinsuchawaythatweputahardcaponhowmanyinstancesofanAudioClipcanplaysimultaneouslysothatwedon’tattempttoplaytoomanyofthesamesoundeffectssimultaneously.WecandothisbyhavingamanagementobjecttakecontrolofourAudioSources.ItshouldacceptsoundplaybackrequestsandplaysthefilethroughanyAudioSourcesthataren’talreadybusyplayinganexistingsound.

Themanagementobjectcouldalsothrottletherequestssuchthatthereisalimittohowmanyversionsofthesamesoundeffectcanplay,andhowmanytotalsoundeffectsareplayingatanygiventime.Thiswouldbebestusedon2Dsoundeffectsorsingleinstancesof3Dsoundeffects(whichwouldrequiremovingtheAudioSourcetothecorrectlocationatthemomentofplayback).

AlmosteveryAudioManagementAssetavailableintheUnityAssetStoreimplementsanaudio-throttlingfeatureofsomekind(oftenknownas“audiopooling”),andforgoodreason;it’sthebesttrade-offinminimizingexcessiveaudioplaybackwiththesmallestamountofeffortinpreparingaudioassetstomakeuseofit.Forthisreason,andbecausetheseassetsoftenprovidemanymoresubtleperformance-enhancingfeatures,itisrecommendedtouseapre-existingsolution,ratherthanrollingoutourown,asthescriptingprocesscanbeveryinvolved.

Notethatambient3DsoundsstillneedtobeplacedatspecificlocationsintheScenetomakeuseofthelogarithmicvolumeeffect,whichgivesitthepseudo-3Deffect,sotheaudiomanagementsystemwouldprobablynotbeanidealsolution.Limitingplaybackonambientsoundeffectsisbestachievedbyreducingthetotalnumberofsources.Thebestapproachistoeitherremovesomeofthemorreducethemdowntoonelarger,louderAudioSource.Naturally,thisapproachaffectsthequalityoftheuserexperience,sinceitwouldappearthatthesoundiscomingfromasinglesourceandnotmultiplesources,andsoitshouldbeusedwithcare.

MinimizeAudioClipreferencesEachAudioSourceintheScenewithareferencetoanAudioClipwithPreloadAudioDataenabledwillconsumeacertainamountofmemoryfortheAudioClip(compressed,decompressed,orbuffered,dependingonLoadType)throughouttheentirelengthofthegivenScene.TheexceptiontothisruleisiftwoormoreAudioSourcesreferencethesameAudioClip,inwhichcasenoadditionalmemoryisconsumedasalloftheAudioSourcesarereferencingthesamelocationinmemoryandreadingfromitonanas-needed

http://freepdf-books.com

Page 181: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

basis.

AudioClipsareunmanagedresourceswithinUnity,whichmeanstheywillnotbereleasedfrommemorymerelybysettingallreferencestonull.Unityexpectsustoloadandreleasetheseresourcesourselves,creatingandreleasingthemfrommemoryas-needed.Keepingfilesinmemoryforlongperiodsisreasonableforfrequentlyusedsoundeffects,sinceloadingafileintomemoryeverytimeitisrequestedwouldcostussomemeasureofCPUuse.

However,ifwefindthatweareusingtoomuchmemoryfromthesefrequentlyusedsoundeffects,thenwemustmakethedifficultchoiceofeitherreducingtheirqualityorremovingthementirely,tofindmemorysavings.Removingsoundeffectscompletelyisnotnecessarilyabadoption.Wemightbeabletoachieveauniquesoundeffectbyreusingexistingsoundeffectscombinedwithspecialeffectsandfilters.

Ontheotherhand,keepinginfrequentlyusedsoundeffectsinmemoryforthelengthofaScenecanposeasignificantproblem.Wemighthavemanyone-time-onlysoundeffects,suchasdialogclips,wherethereislittlereasontokeeptheminmemoryjustfortheoneuniquemomenttheyareneeded.CreatingAudioSourceswithassignedAudioClips(intheirAudioClipproperty)willgeneratesuchreferences,andcauseexcessmemoryconsumptionevenifweonlyusethemforasinglemomentduringgameplay.

ThesolutionistomakeuseofResources.Load()andResources.UnloadAsset()tokeeptheaudiodatainmemoryonlyforaslongasitisbeingplayed,andthenimmediatelyreleaseitonceitisnolongerneeded.Thefollowingcodesamplewillachievethiseffectinthesimplestmannerpossible(trackingonlyasingleAudioSourceandAudioClip)usingourSingletonAsComponentclass,justtogiveusanideaofwhatsuchasystemmightlooklike:

usingUnityEngine;

usingSystem.Collections;

usingSystem.Collections.Generic;

publicclassAudioSystem:SingletonAsComponent<AudioSystem>{

[SerializeField]AudioSource_source;

AudioClip_loadedResource;

publicstaticAudioSystemInstance{

get{return((AudioSystem)_Instance);}

set{_Instance=value;}

}

publicvoidPlaySound(stringresourceName){

_loadedResource=Resources.Load(resourceName)asAudioClip;

_source.PlayOneShot(_loadedResource);

}

voidUpdate(){

if(!_source.isPlaying&&_loadedResource!=null){

Resources.UnloadAsset(_loadedResource);

http://freepdf-books.com

Page 182: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

_loadedResource=null;

}

}

}

ThisclasscanbetestedwiththefollowingComponent,whichloadsasoundfilewhentheAkeyispressed:

publicclassAudioSystemTest:MonoBehaviour{

voidUpdate(){

if(Input.GetKeyDown(KeyCode.A)){

AudioSystem.Instance.PlaySound("TestSound");

}

}

}

TipNotethat,totestthiscode,anaudiofilenamedTestSoundmustbeplacedwithinafoldernamedResourcesinorderforUnitytofinditatruntime.

Usingthisapproachtoplaysoundeffects,weshouldnotethatmemoryforthesoundisonlyallocatedwhenitisplayed,andthenimmediatelyfreedwhenthesoundeffectends.Onceagain,multipleaudiotoolsintheUnityAssetStoreprovidethisfeature,buttheAudioSystemclasscanbeexpandedtohandlemultipleAudioSourcesandAudioClipsfairlyeasilyifwewishtocustomizethesolution.

EnableForcetoMonofor3DsoundsEnablingtheForcetoMonosettingonastereoAudioFilewillmixittogetherwiththechannelsintoasinglechannel,saving50percentofthefile’stotaldiskandmemoryspaceusage.Enablingthisoptionisgenerallynotagoodideaforsome2Dsoundeffectswherethestereoeffectisoftenusedtocreateacertainaudioexperience.Butwecanenablethisoptionforsomegoodspacesavingson3Dsoundeffects,wherebeingastereosourceisgenerallymeaningless,and2Dsoundswherethestereoeffectisn’timportant.

ResampletolowerfrequenciesResamplingimportedaudiofilestolowerfrequencieswillreducethefilesizeandruntimememoryfootprint.ThiscanbeachievedthroughanAudioClip’sSampleRateSettingandSampleRateproperties.Somefilesrequirehighsampleratestosoundreasonable,suchasfileswithhighpitchesandmodernmusicfiles.However,lowersettingscanreducethefile’ssizewithoutmuchnoticeablequalitydegradationinmostcases.22050Hzisacommonvalueforsourcesthatinvolvehumanspeechandclassicalmusic.Somesoundeffectsmaybeabletogetawaywithevenlowerfrequencyvalues.But,eachsoundeffectwillbeaffectedbythissettinginauniqueway,soitwouldbewisetospendsometimedoingsometestingbeforewefinalizeourdecisiononsamplingrate.

ConsiderallencodingformatsIfmemoryandharddiskconsumptionarenotaburdenonourapplication,thentheWAVformatcanbeusedtoreduceCPUcostsatruntime,duetohavingasmalleroverhead

http://freepdf-books.com

Page 183: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

requiredtodecodethedataduringeachplayback.Meanwhile,ifwehaveCPUcyclestospare,wecansavespacewithcompressedencoding.

BewareofstreamingStreamingfilesfromdiskshouldberestrictedtolarge,single-instancefilesonly,asitrequiresruntimeharddiskaccess;oneoftheslowestformsofdataaccessavailabletous.Layeredortransitioningmusicclipsmayrunintomajorhiccupsusingthismethod,atwhichpointitwouldbewisetoconsidertheResources.Load()approach.Weshouldalsoavoidstreamingmorethanonefileatatimeasitlikelytoinflictalotofcachemissesonthediskthatinterruptgameplay.

ApplyFiltereffectsthroughMixergroupstoreduceduplicationFiltereffectsareadditionalComponentsthatwecanattachtoanAudioSourcetomodifysoundplayback.EachindividualFiltereffectwillcostsomeamountofbothmemoryandCPU,andattachingduplicatestomanyAudioSourcesinourScenecanresultindireconsequencesifthey’reusedtoofrequently.AbetterapproachistomakeuseofUnity’sAudioMixerutilitytogeneratecommontemplatesthatmultipleAudioSourcescanreferencetominimizetheamountofmemoryoverhead.

TheofficialtutorialonAudioMixerscoversthetopicinexcellentdetail:

https://unity3d.com/learn/tutorials/modules/beginner/5-pre-order-beta/audiomixer-and-audiomixer-groups

Use“WWW.audioClip”responsiblyUnity’sWWWclasscanbeusedtostreamgamecontentinviatheWeb.But,accessingaWWWobject’saudioClippropertywillallocateawholenewAudioClipresourceeachtimeitisinvoked,andsimilarlywithotherWWWresource-acquiringmethods.ThisresourcemustbefreedwiththeResources.UnloadAsset()methodonceitisnolongerrequired.

Discardingthereference(settingittonull)willnotautomaticallyfreetheresource,soitwillcontinuetoconsumememory.Ergo,weshouldonlyobtaintheAudioClipthroughtheaudioClippropertyoncetoobtaintheresourcereference,useonlythatreferencefromthatpointforward,andreleaseitwhenitisnolongerrequired.

ConsiderAudioModulefilesforbackgroundmusicAudioModulefiles,alsoknownasTrackerModules,areanexcellentmeansofsavingasignificantamountofspacewithoutanynoticeablequalityloss.SupportedfileextensionsinUnityare.it,.s3m,.xm,and.mod.UnlikethecommonPCMaudioformats,whicharereadasbitstreamsofdatathatmustbedecodedatruntimetogenerateaspecificsound,TrackerModulescontainlotsofsmall,high-qualityPCMsamplesandorganizetheentiretracksimilartoamusicsheet;definingwhen,where,howloud,withwhatpitch,andwithwhatspecialeffectseachsampleshouldbeplayedwith.Thiscanprovidesignificantsizesavings,whilemaintaininghigh-qualitysampling.So,iftheopportunityisavailabletoustomakeuseofTrackerModuleversionsofourmusicfiles,thenitisworthexploring.

http://freepdf-books.com

Page 184: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 185: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TexturefilesTheterms“Texture”and“Sprite”oftengetconfusedingamedevelopment,soit’sworthmakingthedistinctionthatinUnity3DaTextureissimplyanimagefile;abiglistofcolordatatellingtheinterpretingprogramwhatcoloreachpixeloftheimageshouldbe.WhereasaSpriteisthe2Dequivalentofamesh,whichjusthappenstobeasinglequadthatrendersflatagainstthecurrentcamera.TherearealsothingscalledSpriteSheets,whicharelargecollectionsofindividualimagescontainedwithinalargerTexturefile,commonlyusedtocontaintheanimationsofa2Dcharacter.ThesefilescanbesplitapartbyUnity’sSpriteBatchtool,toformindividualTexturesfortheanimationframes.

Let’strytoignorealloftheseconfusingnamingconventionoverlaps,andsimplytalkaboutTextures:theimagefileswe’reimportingintoourapplicationthatweregeneratedintoolssuchasAdobePhotoshoporGimp.Atruntime,thesefilesareloadedintomemory,pushedtotheGPU,andrenderedbytheShaderoverthetargetobjectduringagivenDrawCall.

http://freepdf-books.com

Page 186: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CompressionformatsMuchlikeAudiofiles,UnityprovidesuswithavarietyofcompressiontechniquestostoreourTexturefilesmoreefficiently.WhenaTexturefileisimported,thereareseveralsettingsthatwecanmanipulate.ThefirstisTextureType.Thissettingdoesnotaffectthefileitself,butratherhowUnitywillinterpret,manipulate,andcompressitwithinthefinalexecutablewebuild.

WithmostoftheTextureTypeoptions,theonlythreecompressionoptionsUnityexposestousareCompressed,16-bit,andTrueColor.Alternatively,ifwesettheTextureTypetoAdvanced,thenweexposealargernumberofsettings.ThisgivesusfarmorecontrolovertheinterpretationoftheTexturefile.

http://freepdf-books.com

Page 187: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Thiswillbeusefulinformationgoingforwardasthereareseveralperformance-enhancingopportunitiestofindthroughthisparticularviewofaTexturefile,whichwouldnotbevisibleordinarily.

ThenumberofcompressionformatsinAdvancedmodearesignificantlymorebroadandvaried,buttheoptionsremainidenticalbetweenUnity4andUnity5.Someformatsallowalphavalues,whereassomedonot,whichrestrictsourchoicesifwewishtomaintainalphatransparencyinourTexture(orafourthfloatdatavaluefromaTexturebeingusedasaHeightmap!).

SomeformatsalsocostdifferentlevelsofperformanceduringSceneinitializationtodecompressandpushintotheGPU,whichcanvaryenormouslydependingontheplatformwe’retargetingandthechosenformat.AdvancedmodeprovidestheAutomaticCompressedoption,whichtriestopickthebestoptionforthegivenplatformanddevice.Wecanusethisoptionifwe’renotcompletelysureaboutthebestformatforourgame,orwecanspendthetimetodosomeperformance-testingwithdifferentformatstoconfirmthebestchoice(s)forthetargetdevice.

http://freepdf-books.com

Page 188: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

NotethatthePreviewWindowatthebottomoftheInspectorViewprovidessomeusefulstatisticstohelpusdeterminehoweffectivelythecurrentlyselectedcompressionmethodisbehaving.

http://freepdf-books.com

Page 189: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TextureperformanceenhancementsLet’sexploresomechangeswecanmaketoourTexturefiles,whichmighthelpimproveperformance,dependingonthesituationandthecontentofthefileswe’reimporting.Ineachcase,we’llexplorethechangesthatneedtobemade,andtheoveralleffecttheyhave,whetherthisresultsinapositiveornegativeimpactonmemoryorCPU,anincreaseordecreaseintheTexturequality,andunderwhatconditionswecanexpecttomakeuseofthesetechniques.

Also,becausetheUnity5PersonalEditionhasmademultiplefeaturesavailabletousthatwerepreviouslyonlyavailableintheProEdition,someusersmaynotbeawareofsomeadditionaltechniquesthatwecanapplytoourTexturestoimproveapplicationperformance.So,wewillalsocoversomeofthesetechniquestowardtheendofthissection.

ReduceTexturefilesizeThelargeragivenTexturefile,themoreGPUmemorybandwidthwillbeconsumedpushingtheTexturewhenitisneeded.Ifthetotalmemorypushedpersecondexceedsthegraphicscard’stotalmemorybandwidth,thenwewillhaveabottleneckastheGPUwaitsforallTexturestobeloadedbeforethenextrenderingpasscanbegin.SmallerTexturesarenaturallyeasiertopushthroughthepipelinethanlargerTextures,soweneedtofindagoodmiddlegroundbetweenhighqualityandperformance.

Acommontesttofindoutifwe’rebottleneckedinmemorybandwidthistosimplyreducetheresolutionofourgame’smostabundantandlargestTexturefilesandrelaunchtheScene.Iftheframeratesuddenlyimproves,thentheapplicationwasmostlikelyboundbytheTexturethroughput.Iftheframeratedoesnotimproveorimprovesverylittle,theneitherwestillhavesomememorybandwidthtomakeuseof,ortherearebottleneckselsewhereintherenderingpipelinepreventingusfromseeinganyfurtherimprovement.

UseMipMapswiselyTherewouldbenopointrenderingsmall,distantobjectssuchasrocksandtreeswithahigh-detailTextureifthere’snowaytheplayerwouldeverbeabletoseethatdetail,oriftheperformancelossistoogreattowarrantaminordetailincrease.MipMapswereinventedasawaytosolvethisproblem(aswellashelpingeliminatealiasingproblemsthatwereplaguingvideogamesataroundthesametime),bypregeneratinglower-resolutionalternativesofthesameTextureandkeepingthemtogetherinthesamememoryspace.Atruntime,theGPUpickstheappropriateMipMapoptionbasedonhowlargethesurfaceappearswithintheperspectiveview(essentiallybasedonthetexel-to-pixelratiowhentheobjectisrendered),andthenpicksanappropriatelyscaledMipMapoftheTexture.

ByenablingtheGenerateMipMapsoption,Unityautomaticallyhandlesthegenerationoftheselower-resolutioncopiesoftheTexture.Thesealternativesaregeneratedusinghigh-qualityresamplingandfilteringmethodswithintheEditor,ratherthanatruntime.

Thefollowingimageshowshowa1024x1024imagewillbeMipMappedintomultiple

http://freepdf-books.com

Page 190: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

lower-resolutionduplicates:

ThedownsidetoMipMappingisthatithasanegativeimpactonfilesizeandloadingtimeduetothelargercombinedTexturefilesthatarebeingautomaticallygenerated.ThefinalTexturefilewillbearound33percentlargerwhenMipMappingisenabled.TherearealsosomesituationswheretheMipMappingprocessisawasteofeffort,soweshouldexaminesomeofourTexturefilestoseeifMipMapsarebeingappliedwisely.

MipMappingisonlyusefulifwehaveTexturesthatneedtoberenderedatvaryingdistancesfromthecamera.IfwehaveTexturesthatalwaysrenderedatasimilardistancefromthemaincamera,suchthattheMipMappedalternativesareneverused,thenenablingMipMapsisjustwastingspace.Inthesecases,weshoulddisabletheMipMappingfeaturebydisablingtheGenerateMipMapsoptionfortheTexture.

IfonlyasingleMipMapalternativeisused,thenweshouldconsiderdisablingMipMappinganddownscalingtheresolutionoftheoriginalTexturefile.

AdditionalcandidatesfordisablingtheMipMappingfeatureare:

AlmostanyTexturefileusedina2DgameUserInterface(GUI)TexturesTexturesformeshes,Sprites,andParticleEffects,whichalwaysrendernearthecamera—examplesincludetheplayercharactersthemselves,anyobjectstheyholdorcarry,andanyParticleEffectswhichalwayscenteraroundtheplayer

ManageresolutiondownscalingexternallyUnityputsalotofeffortintomakingthingsaseasytouseaspossibleandprovidesuswiththeabilitytoplacetheprojectfilesfromexternaltoolstoourProjectworkspace,suchasPSDandTIFFfiles,whichareoftenlargeandsplitintomultiplelayeredimages.UnityautomaticallygeneratesaTexturefilefromthefile’scontentsfortherestoftheEngineto

http://freepdf-books.com

Page 191: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

makeuseof,whichcanbeveryconvenient,asweonlyneedtomaintainasinglecopyofthefilethroughSourceControlandtheUnitycopyisautomaticallyupdatedwhenanartistmakeschanges.

TheproblemisthatthealiasingintroducedbyUnity’sauto-Texturegenerationandcompressiontechniquesfromthesefilesmaynotbeasrobustandefficientasthetoolsweusetogeneratesuchfiles,suchasAdobePhotoshoporGimp.Unitymaybeintroducingartefactsthroughaliasing,andwemightfindourselvesgettingintothehabitofimportingimagefileswithahigherresolutionthannecessary,justtokeeptheintendedqualitylevel.But,hadwedownscaledtheimagethroughtheexternalapplicationfirst,wemightsuffermuchlessaliasing.Inthesecases,wemayhavebeenabletoachieveanacceptablelevelofqualitywithalowerresolution,whileconsuminglessoveralldiskandmemoryspace.

WecaneitheravoidusingPSDandTIFFfileswithinourUnityprojectasamatterofhabit(storingthemelsewhereandimportingthedownscaledversionintoUnity),orjustperformsomeoccasionaltestingtoensurewe’renotwastingfilesize,memory,andGPUmemorybandwidthusinglargerresolutionfilesthannecessary.Thiscostsussomeconvenienceinprojectfilemanagement,butcanprovidesomesignificantsavingsforsomeTextures,ifwe’rewillingtospendthetimecomparingthedifferentdownscaledversions.

AdjustAnisotropicFilteringlevelsAnisotropicFilteringisafeaturewhichimprovestheimagequalityofTextureswhentheyareviewedatveryshallow(oblique)angles.ThefollowingscreenshotshowstheclassicexampleofpaintedlinesonaroadwithandwithoutAnisotropicFilteringapplied.WithoutAnisotropicFiltering,thepaintedlinesappearblurryanddistortedthefurthertheyareawayfromthecamera,whereastheviewwithAnisotropicFilteringappliedmakestheselinesmorecrispandclear.

ThestrengthofAnisotropicFilteringappliedtotheTexturecanbehand-modifiedonaper-TexturebasiswiththeAnisoLevelsettingaswellasgloballyenabled/disabledusingtheAnisotropicTexturesoptionwithintheQualitySettingsscreen.

MuchlikeMipMapping,thiseffectcanbecostlyandsometimesunnecessary.IfthereareTexturesinourScenewherewearecertainwillneverbeviewedatanobliqueangle(such

http://freepdf-books.com

Page 192: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

asdistantbackgroundspritesandparticle-effectTextures),thenwecansafelydisableAnisotropicFilteringforthemtosavesomeruntimeoverhead.WecanalsoconsideradjustingthestrengthoftheAnisotropicFilteringeffectonaper-Texturebasistofindthemagicspotbetweenqualityandperformance.

ConsiderAtlasingAtlasingisthetechniqueofcombininglotsofsmaller,isolatedTexturestogetherintoasingle-largeTexturefileinordertominimizethenumberofMaterials,andhenceDrawCalls,weneedtoapplybyexploitingDynamicBatching.Conceptually,thistechniqueisverysimilartotheapproachesofminimizingMaterialusageyoulearnedinChapter3,TheBenefitsofBatching.

EachuniqueMaterialwouldrequireanadditionalDrawCall,buteachMaterialonlysupportsasingleprimaryTexture(thisexcludesNormalMaps,EmissionMaps,andothersecondaryTextures).BycombiningallTexturesintoasinglecolossalTexture,wecanminimizethenumberofDrawCallsusedtorenderobjectsthatsharethisTexture:

Thebenefitsareclear;reducingDrawCallsresultsinreducingtheCPUworkloadandimprovingtheframerateifourapplicationisCPU-bound(orsimplyfreesupcyclesforothertasks).Therewillbenolossofquality,andmemoryconsumptionwillbeessentially

http://freepdf-books.com

Page 193: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

identical.Allwe’redoingisexploitingUnity’sDynamicBatchingsystemtoreduceDrawCalls.NotethatAtlasingdoesnotresultinreducedmemorybandwidthconsumption,sincetheamountofdatabeingpushedisidentical.ItjusthappenstobebundledtogetherinonebiggerTexturefile.

TipAtlasingisonlyanoptionwhenallofthegivenTexturesrequirethesameShader.IfsomeoftheTexturesneeduniquegraphicaleffectsappliedthroughShaders,thentheymusteitherbeisolatedintotheirownMaterialsorAtlasedwithotherTextures,whichusethesameShader.

AtlasingisacommontacticappliedtoUserInterfaceelements,andingamesthatfeaturealotof2Dgraphics.AtlasingbecomespracticallyessentialwhendevelopingmobilegameswithUnity,sinceDrawCallstendtobethemostcommonbottleneckonthoseplatforms.But,wewouldnotwanttogeneratetheseatlasfilesmanually.LifewouldbemuchsimplerifwecouldcontinuetoeditourTexturesindividually,andautomatethetaskofcombiningthemintoalargerfile.

ManyGUI-relatedtoolsintheUnityAssetStoreprovideanautomatedTexture-atlasingfeature,therearesomestandaloneprogramsscatteredacrosstheInternet,whichcanhandlethiswork,andUnityitselfprovidedabuilt-inSpritePackertoolwiththenewUIsysteminversion4.6,whichcanbeeasilycustomizedtopackTexturesindifferentways.

ChecktheUnitydocumentationtodiscovermoreaboutthisusefulfeature,ifinterested:

http://docs.unity3d.com/Manual/SpritePacker.html

Eitherway,itisrecommendedtomakeuseofanexistingsolutionforatlasgenerationinordertoavoidreinventingthewheel.

TipNotethatTexturesmustbedefinedastheSpritetypeinordertoberecognizedandpackedbytheSpritePackertool.

Atlasingdoesnotneedtoapplyto2DgraphicsandUIelementseither.Wecanapplythistechniqueto3Dmeshesifwehappentobecreatingalotoflow-resolutionTextures.3DgamesthatfeaturesimpleTextureresolutions,oraflat-shadedlow-polyartstyle,areidealcandidatesforAtlasinginthisway.

However,becauseDynamicBatchingonlyaffectsnon-animatedmeshes(thatis,MeshRenderers,andnotSkinnedMeshRenderers),thereisnoreasontocombineTexturefilesforanimatedcharactersintoanatlas.Sincetheyareanimated,theGPUneedstomultiplyeachobject’sbonesbythetransformofthecurrentanimationstate.Thismeansauniquecalculationisneededforeachcharacter,andtheywillresultinanextraDrawCallregardlessofanyattemptswemaketohavethemshareMaterials.

Asaresult,combiningTexturesforanimatedcharactersshouldonlybedoneasamatterofconvenienceandspace-saving;forexample,inaflat-shadedlow-polyartstylegame,whereeverythinghappenstouseacommoncolorpalette,wecanmakesomesignificant

http://freepdf-books.com

Page 194: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

spacesavingsbyusingasingleTexturefortheentiregameworld,objects,andcharacters.

ThedisadvantagesofAtlasingaremostlyintermsofdevelopmenttimeandworkflowcosts.ItrequiresalotofefforttooverhaulanexistingprojecttomakeuseofAtlasing,whichcanbealotofworkjusttofigureoutifitisworththeeffortornot.Inaddition,weneedtobewareofgeneratingatlasfiles,whicharetoolargeforthetargetplatform.

Somedevices(specificallymobiledevices)havearelativelylowlimitonthesizeofTexturesthatcanbepulledintothelowestmemorycacheoftheGPU.Iftheatlasistoolarge,thenitmustbebrokenupintosmallerTextures,tofitthetargetmemoryspace.IftherendererhappenstoneedTexturesfromdifferentpiecesoftheatlaseveryotherDrawCall,thennotonlywillweinflictalotofcachemisses,butalsowemightfindthatwechokethememorybandwidthasTexturesareconstantlypulledfromVRAMandthelower-levelcache.

WewouldprobablynothavethisproblemiftheatlaswasleftasindividualTextures.ThesameTextureswappingwouldoccur,butwillresultinmuchsmallerfilesbeingswappedatthecostofadditionalDrawCalls.OurbestoptionsatthisstagewouldbetolowertheatlasresolutionorgeneratemultiplesmalleratlasestohavebettercontroloverhowtheywillbeDynamicallyBatched.

So,Atlasingisclearlynotaperfectsolution.Ifitisnotclearwhetheritwouldresultinaperformancebenefit,thenweshouldbecarefulnottowastetoomuchtimeonimplementation.

Ingeneral,weshouldattempttoapplyAtlasingtomid-range/high-qualityMobilegamesrightfromthestartoftheproject,keepingwithintheTexturelimitforthetargetplatform,makingper-platformandper-deviceadjustmentsasnecessary.Ontheotherhand,thesimplestMobilegameswillmostlikelyfunctionwithoutneedinganyAtlasing.

Meanwhile,weshouldconsiderapplyingAtlasingtohigh-qualityDesktopgames,onlyifourDrawCallcountexceedsreasonablehardwareexpectations,sincewewillwantmanyofourTexturestomaintainhighresolutionsformaximumquality.Low-qualityDesktopgamescanprobablyaffordtoavoidAtlasing,sinceDrawCallsareunlikelytobethebiggestbottleneck.

Ofcourse,nomatterwhattheproductis,ifwe’reeverCPU-boundbyDrawCallsandwe’vealreadyexhaustedmanyofthealternativetechniques,thenAtlasingwouldbethenextbesttechniquetoimplement,asitcanresultinsomeimpressiveDrawCallsavingswhenusedproperly.

Adjustcompressionratesfornon-squareTexturesItisnotrecommendtoimportnon-squareand/ornon-power-of-2Texturesintoourapplication,becauseGPUsoftenrequirethepushedTexturetobesquare,andapower-of-2sizeresultsinunnecessaryworkloaddealingwithmalformedTexturesizes.UnitywillautomaticallyadjusttheTextureandaddadditionalemptyspaceinordertofittheformfactorthattheGPUexpects,whichwillresultinadditionalmemorybandwidthcosts,pushingwhatisessentiallyuselessdatatotheGPU.

http://freepdf-books.com

Page 195: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

So,thefirstrecommendationistoavoidnon-squareand/ornon-power-of-2Texturesaltogether.Iftheimagecanbeplacedwithinasquare,power-of-2Texture,anddoesnotresultintoomuchqualitydegradationduetosqueezing/stretching,thenweshouldapplythosechangesjusttokeeptheCPUandGPUhappy.

However,ifwestillwanttousenon-squareTextures,thereisatrickwecanapplytoachievehigherqualitywithoutcostinganyadditionalspace.Sincethewaynon-squareTexturesarepackedbycompressionalgorithms,wecanoftenincreasethebit-rate(andhencequality)ofthechosencompressionformatforanon-squareTextureandstillachieveanidenticalimportedfilesizeandruntimeoverheadcost.ThisonlycostsusthetimeittakestofindtheseTexturesandtestavarietyofcompressionalgorithmstofindthehighestqualityversion.

SparseTexturesSparseTextures,alsoknownasMega-TexturesorTiled-Textures,provideawayofeffectivelystreamingTexturedatafromdiskatruntime.Relativelyspeaking,iftheCPUperformsoperationsintheorderofseconds,thenthediskwilloperateintheorderofdays.Socommonadviceisthatharddiskaccessduringgameplayshouldbeavoidedatallcosts,sinceanysuchtechniquerisksinflictingmorediskaccessthanavailable,causingourapplicationtogrindtoahalt.

But,SparseTexturingbreaksthisruleandofferssomeinterestingperformancesavingtechniques.TheaimofSparseTexturingistocombinemanyTexturesintoanenormousTexturefile,whichwouldbefartoolargetoloadintographicsmemoryasasingleTexturefile.ThisissimilartotheconceptofAtlasing,exceptthefilecontainingtheTexturesisincrediblylarge(forexample,32,768x32,768resolution)andcontainsconsiderabledetail(32bitsperpixel).Theideaistosavelargeamountsofruntimememoryandmemorybandwidthbyhand-pickingsmallsubsectionsoftheTexturedynamically,andpullthemfromthediskjustbeforetheyareneededinthegame.Themaincostofthistechniqueisthefilesizerequirement(theexampleresolutionfilewouldconsume4GBofdiskspace!).OthercostsforthistechniquecanbeovercomewithagreatdealofScenepreparationwork.

ThegameworldneedstobecreatedinsuchawaythatitminimizestheamountofTextureswappingtakingplace.Inordertoavoidjarring,“texturepopping”problems,Texturesubsectionsmustbepulledfromadiskwithjustenoughtimetosparethattheplayerdoesnotnotice.ThistakesplaceinthedesignoftheTexturefileitself,bykeepingcommonelementsforagivenSceneinthesamegeneralareaoftheTexture,andthedesignoftheScene,bytriggeringnewTexturesubsectionloadingatkeymomentsduringgameplay.Ifitishandledwithgreatcareandattentiontodetail,thenSparseTexturingcanresultinsomeimpressiveScenequalityandequallyimpressivememorysavings.

SparseTexturingwaspreviouslyaProEdition-onlyfeatureinUnity4,butwasmadeavailablewiththePersonalEditionofUnity5.SparseTexturingrequiresspecializedhardwareandplatformsupport,however,sothisoptionisnotavailabletoallgames.Itisahighlyspecializedanduncommontechniquewithinthegamingindustry,whichisreflectedinthelackofdocumentation.TheUnitydocumentationdoesnotprovidemuch

http://freepdf-books.com

Page 196: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

informationonSparseTexturing,butitdoesprovideanexampleSceneshowingtheeffectatwork.ItcanbefoundatthefollowingURL:http://docs.unity3d.com/Manual/SparseTextures.html.

ForUnitydeveloperswhoconsiderthemselvesadvancedenoughtofigureitoutontheirown,itmightbeworthtakingthetimetoperformsomeresearchtoseeifSparseTexturingisrightfortheirprojectandwhethertheyarewillingtomaketheappropriateScenechangesnecessarytogaintheperformancebenefitsthatthisfeaturepresents.

ProceduralMaterialsAlsoknownasSubstances,ProceduralMaterialsareameansofprocedurallygeneratingTexturesatruntimebycombiningsmall,high-qualityTexturesampleswithcustommathematicalformulas.ThegoalofProceduralMaterialsistogreatlyminimizetheapplicationfootprintatthecostofadditionalruntimememoryandCPUprocessingduringinitialization.LikeSparseTexturing,thisfeaturewaspreviouslyonlyavailableintheProEditionofUnity4andisnowavailableinUnity5.

ThisgivesmanyusersanopportunitytoviewtheirMaterialsfromadifferentperspective,asProceduralMaterialsareamoremodernapproachtotheirgames.Texturefilesareoftenthebiggestdiskspaceconsumerofagameproject,andit’sfairlycommonknowledgethatdownloadtimeshaveatremendousnegativeimpactonthecompleteddownloadrateandjustgettingpeopletotryourgame(evenifit’sfree!).ProceduralMaterialsofferustheabilitytosacrificesomeinitializationandruntimeprocessingpowerformuchfasterdownloads.ThisisveryimportantforanupcominggenerationofMobilegamesthataretryingtocompeteviagraphicalfidelity.

TheUnitydocumentationonProceduralMaterialsisfarmoreextensivethanforSparseTexturing,soitisrecommendedtoworkthroughthedocumentationforaclearerpictureofhowSubstancesworkandhowtheycanprovideuswithperformancebenefits:

http://docs.unity3d.com/Manual/ProceduralMaterials.html

http://freepdf-books.com

Page 197: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 198: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MeshandanimationfilesFinally,let’scovermeshandanimationfiles.Thesefiletypesareessentiallylargearraysofvertexandskinnedbonedata,andthereareavarietyoftechniqueswecanapplytominimizefilesize,whilekeepingasimilar,ifnotidentical,appearance.Therearealsosometimeswaystolowerthecostofrenderinglargegroupsoftheseobjectsthroughbatchingtechniques.Let’slookintoaseriesofperformance-enhancingtechniqueswecanapplytosuchfiles.

http://freepdf-books.com

Page 199: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ReducingpolygoncountThisisthemostobviouswaytogainperformance,butweshouldneverdisregardit.Infact,sincewecannotbatchobjectsusingSkinnedMeshRenderers,it’soneoftheonlygoodwaysofreducingCPUandGPUruntimeoverheadforanimatedobjects.

Reducingthepolygoncountissimple,straightforward,andprovidesbothCPUandmemorycostsavingsforthetimerequiredforartiststocleanupthemesh.Muchofanobject’sdetailisprovidedalmostentirelybydetailedTexturingandcomplexShadinginthisdayandage,sowecanoftengetawaywithstrippingawayalotofverticesonmodernmeshesandmostuserswouldbeunabletotellthedifference.

TweakingMeshCompressionUnityoffersfourdifferentMeshCompressionsettingsforimportedmeshfiles:Off,Low,Medium,andHigh.IncreasingthissettingwillstripawaymoreandmorepartsofthemeshthatUnitythinksaren’tneededinordertomakeagoodestimateofthesamemeshwiththeaimofreducingoverallfilesize.Thisisessentiallyanautomatedversionofhavinganartistmanuallyreducingthepolygoncount.

However,automatedmeshoptimizationisaverydifficultproblemtosolvemathematicallyandeventhebestalgorithmstendtogeneratealotofartefactsandirregularities.DifferentlevelsofMeshCompressioncanbeattemptedasaquicksolutiontoreducingpolygoncount,butitwillprobablynevercomparetohavinganartistmakeappropriatepolycountreductionsbyhand.

TipThese3Dtoolsoftenprovidetheirownbuilt-inwaysofautomatedmeshoptimization,andshouldbetestedasameansofoptimizingthemeshbeforeimportingthemintoUnity.

UseRead-WriteEnabledappropriatelyTheRead-WriteEnabledflagallowschangestobemadetothemeshatruntimeeitherviaScriptingorautomaticallybyUnityduringruntime.Internally,thismeansitwillkeeptheoriginalmeshdatainmemoryuntilwewanttoduplicateitandmakechangesdynamically.DisablingthisoptionwillallowUnitytodiscardtheoriginalmeshdatafrommemoryonceithasdeterminedthefinalmeshtouse.

Ifweonlyeveruseauniformlyscaledversionofameshthroughouttheentiregame,thendisablingthisoptionwillsaveruntimememorysincewewillnolongerneedtheoriginalmeshdatatomakefurtherrescaledduplicatesofthemesh(incidentally,thisishowUnityorganizesobjectsbyscalefactorwhenitcomestoDynamicBatching).Unitycan,therefore,discardthisunwanteddataearlysincewewillneverneeditagainuntilthenexttimetheapplicationislaunched.

However,ifthemeshoftenreappearsatruntimewithdifferentscales,thenUnityneedstokeepthisdatainmemorysothatitcanrecalculateanewmeshmorequickly,andsotheRead-WriteEnabledflagshouldbeenabled.DisablingitwillrequireUnitytonotonlyreloadthemeshdata,butalsomaketherescaledduplicateatthesametime,causinga

http://freepdf-books.com

Page 200: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

potentialperformancehiccup.

Unitytriestodetectthecorrectbehaviorforthissettingatinitializationtime,butwhenmeshesareinstantiatedandscaledinadynamicfashionatruntime,thenwemustforcetheissuebyenablingthissetting.Thiswillimproveinstantiationspeedoftheobjects,butcostsomememoryoverheadsincetheoriginalmeshdataiskeptarounduntilit’sneeded.

TipNotethatthisalsoapplieswhenusingtheGenerateCollidersoption.

http://freepdf-books.com

Page 201: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Import/calculateonlywhat’sneededThisappearstobeanotherobvioussuggestion,butmeshesdonotonlycontainvertexpositionaldata.TherecouldbeunnecessaryNormalsandTangentsinourmeshthattheShaderswon’tneed,orwecouldbeautogeneratingNormalandTangentcoordinatesthatwewon’tuse,particularlywhentheSmoothingAngleisverylow.Inthesecases,eachvertexrequiresmultiplenormalvectorstocreatethefaceted,flat-shadingstylethatresultsfromit.

Double-checkyourmeshimportsettingsandexaminetheresultantfilesizeandin-gameappearance,bytinkeringwiththeimportsettingstoseeifyoucanmakeanysavingsbystrippingawayunwantedandunnecessarydata.

http://freepdf-books.com

Page 202: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ConsiderbakedanimationsThiswilldependonthe3Driggingandanimationtoolthatweareusing,andtheoverallvertexcountofourmesh;insomecasesbakinganimationscanresultinmuchsmallerfilesizesandmemoryoverheadthanblended/skinnedanimations.Bakedanimationsworkbystoringakeyframedpositionforeachvertexforeachframethatwassampled,andifthemesh’spolygoncountislowenough,thenwemayseesomesignificantsavingsthroughthissimplechange.

Inaddition,howoftenthebakedsampleistakencanusuallybecustomizedbytheexportingapplication.Differentsampleratesshouldbetestedtofindagoodvaluewherethekeymomentsoftheanimationstillshine-throughwhatisessentiallyasimplifiedestimate.

http://freepdf-books.com

Page 203: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LetUnityoptimizemeshesTheOptimizeMeshesoptioninamesh’simportsettingswillreorganizethevertexdataforquickerreadability,andsometimesregeneratethelow-levelrenderingstyle(downtothelevelofpointsversustrisversusstrips)tooptimizetherenderingspeedofthemesh.Simplyput,thisoptionshouldbeenabledinalmostallcases,asthereisverylittlereasontonotletUnitymaketheseadjustmentsforus,unlesswe’vedonesomeprofilingandwe’repositivethatit’ssomehowgeneratingbottlenecks.

Ifwe’regeneratingmeshesprocedurally,thenwecantellUnitytoinvokethisprocessusingtheOptimize()methodonaMeshFilterComponent.Thisprocesscantakesometime,soitshouldbeusedduringinitializationorotherconvenientstoppingpoint.

http://freepdf-books.com

Page 204: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CombinemeshesCombiningmeshesintoalarge,singlemeshcanbeconvenienttoreduceDrawCallsifthemeshesaretoolargeforDynamicBatchinganddon’tplaywellwithotherStaticallyBatchedgroups.ThisisessentiallytheequivalentofStaticBatching,butperformedmanually,sosometimesit’swastedeffortifStaticBatchingcouldtakecareoftheprocessforus.

However,ifwe’reusingtheUnity4FreeEditionwhereStaticBatchingisnotavailabletousorwewishthemeshtomovearoundtheScene,thenthisisagoodoptiontominimizeourDrawCalls.BewarethatitcomeswiththesameriskasStaticBatching.IfanysinglevertexofthemeshisvisibleintheScene,thentheentireobjectwillberenderedtogetherasonewhole.Thiscanleadtoalotofwastedprocessingifthemeshisonlypartiallyvisiblemostofthetime.

ThistechniquealsocomeswiththedrawbackthatitgeneratesawholenewmeshassetfilethatwemustdepositintoourScene,whichmeansanychangeswemaketotheoriginalmesheswillnotbereflectedinthecombinedone.Thisresultsinalotoftediousworkflowefforteverytimechangesneedtobemade,soifStaticBatchingisanoption,itshouldbeusedinstead.

Thereareseveraltoolsavailableonline,whichcancombinemeshfilestogetherforusinUnity.TheyareonlyanAssetStoresearch,orGooglesearchaway.

http://freepdf-books.com

Page 205: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 206: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryTherearemanydifferentopportunitiesthatwecanexploretoachieveperformancegainsforourapplicationjustbytinkeringwithourimportedassets.Or,fromanotherperspective,thereareplentyofwaystoruinourapplication’sperformancethroughassetmismanagement.

Almosteverysingleopportunityisatrade-offbetweenoneperformancemetricorworkflowtaskandanother.So,wemustremainvigilantandonlypicktherighttechniquesintherightprojectsfortherightreasons.Theworstthingwecandoisimplementsuchchangeswithoutunderstandingtheimpact.It’sexcitingtostumbleonsomebigperformanceenhancingsuggestionoutinthebig,wideworld,butunlessweunderstandhowitworks,andtheresultingcosts,wecaninvitefurtherperformanceproblemsandbottleneckswithoutrealizingit,costingusmoretimeandeffortdowntheroad.

Thisconcludesourexplorationofimprovingperformancethroughartassetmanipulation.Inthenextchapter,wewillbeinvestigatingtheBox2DandPhysXphysicssolutionsprovidedbyUnity,thechangeswecanmaketoourscriptcode,Scene,andprojecttomakethesecomponentsprocessourdatafaster;andbehaviortoavoidthatmightcausethemtostumble.

http://freepdf-books.com

Page 207: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 208: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter5.FasterPhysicsEachoftheperformance-enhancingsuggestionswe’veexploredthusfarhavebeenprimarilycenteredonreducingsystemrequirementsandavoidingframerateissues.Butatitsmostfundamentallevel,seekingpeakperformancemeansimprovingtheuserexperience.Thisisbecauseeveryframeratehiccup,everycrash,andeverysystemrequirementthatistoocostlyforagivenmarketultimatelydetractsfromthequalityoftheproduct,andleavesuswonderingwhetherweshouldhavetriedhardertotweaksettingsandfixmorebugsbeforerelease.

TherearecertainlyopportunitiestomanipulatePhysicsEnginebehaviorthatimprovealloftheaforementionedissues,butPhysicsEnginesalsofallintoauniquecategoryofhavingadirectimpactongameplayquality.Ifimportantgameplaycollisioneventsgetmissed(suchastheplayerfallingthroughthefloor),orthegamefreezeswhileitcalculatesacomplexsituation,thenthesehaveasignificantimpactongameplayquality.Thisoftenresultsinpullingtheplayeroutoftheexperience,andit’sacoin-tosswhethertheuserfindsitinconvenient,obnoxious,orhilarious.UnlessourgameisspecificallytargetingtheComedyPhysicsgenre(which,incidentally,hasgrowninpopularityinrecentyearswithgameslikeQWOPandGoatSimulator),thesearesituationsweshouldstrivetoavoid.

Forsomegames,thePhysicsEngineisusedtohandleasignificantnumberoftasksduringgameplay,fromcollisiondetectionwithotherobjectsandinvisibletriggerboxestoraycastingandgatheringalistofobjectsinagivenregion.Forexample,itisessentialinplatformerandactiongamestotunethephysicsproperly;howtheplayercharacterreactstoinputandhowtheworldreactstotheplayercharactercanbetwoofthemostimportantaspectsofwhatmakesthegamefeelresponsiveandfun.Othergamesmayonlyusephysicsforsimplegameplayevents,interestingspectacles,andothereye-candy,butthemoreefficientlythePhysicsSystemisused,themoreofaspectaclethatcanbecreated.

Therefore,inthischapter,wewillnotonlycoverwaystoreduceCPUspikes,overhead,andmemoryconsumptionthroughUnity’sPhysicsSystem,butalsoincludewaystoalterphysicsbehaviorwiththeaimofimprovinggameplayquality.Inaddition,becauseUnity’sPhysicsSystemsarea“black-box”,inthatwecan’tdomuchinternaldebugging,itcanbeverytrickytofigureoutexactlywhen,where,andwhycertainphysicsglitchesareplaguingourproject,andwhatweshoulddotopreventthem.Asaresult,themethodscoveredinthischapterwillincludeseveralsuggestionsonhowtoreduceinstabilityandproblematicphysicssituations.

http://freepdf-books.com

Page 209: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PhysicsEngineinternalsUnitytechnicallyfeaturestwodifferentPhysicsEngines:NvidiaPhysXfor3DphysicsandtheOpenSourceprojectBox2Dfor2Dphysics.However,theirimplementationishighlyabstracted,andfromtheperspectiveoftheUnityAPI,bothenginesoperateinanearlyidenticalfashion.

Ineithercase,themoreweunderstandaboutUnity’sPhysicsSystem,themoresensewecanmakeofpossibleperformanceenhancements.So,firstwe’llcoversometheoryaboutUnity’sPhysicsEngines.

http://freepdf-books.com

Page 210: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PhysicsandtimePhysicsEnginesgenerallyoperateundertheassumptionthattimeisiteratinginfixedvaluesoftime,andbothofUnity’sPhysicsEnginesoperateinthismanner.ThePhysicsEnginewillonlycalculateusingveryspecificvaluesoftime,independentofhowmuchtimeittooktorenderthepreviousframe.ThisisknownastheFixedUpdateTimestep,anditissettoavalueof20millisecondsbydefault,or50updatespersecond.

NoteItcanbeverydifficulttogenerateconsistentresultsforcollisionsandforcesbetweentwodifferentcomputersifaPhysicsEngineusesavariabletimestep.Suchenginestendtogenerateinconsistentresultsbetweenmultiplayerclients,andduringrecordedreplays.

Iftoomuchtimehaspassedbetweenframes(alowframerate),thenthePhysicsSystemmayupdatemultipletimesbeforerenderingbeginsagain.Conversely,ifnotenoughtimehaspassedsincethepreviousrender(ahighframerate),thenthephysicsupdatemaybeskippeduntilafterthenextrendercall.

TheFixedUpdate()methodrepresentsthemomentwhenthePhysicsSystemperformssimulationtimestepupdates.ItisoneofseveralimportantUnitycallbackswecandefineinaMonoBehaviourscriptand,ingeneral,FixedUpdate()isusedtodefineframe-rate-independentbehavior.Thiscallbackisusuallyusedforcalculationssuchasartificialintelligence(whicharealsoeasiertoworkwithifweassumeafixedupdatefrequency),butthisisalsowhereweshouldmodifyRigidbodyobjectsduringgameplay.

ThefollowingdiagramshowsanimportantsnippetoftheUnityOrderofExecutiondiagram:

Note

http://freepdf-books.com

Page 211: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThefullOrderofExecutiondiagramcanbefoundat:http://docs.unity3d.com/Manual/ExecutionOrder.html.

TheFixedUpdateloopAswecansee,FixedUpdate()isinvokedjustpriortothePhysicsSystemperformingitsownupdateandthetwoareinextricablylinked.TheprocessbeginswithdeterminingwhetherenoughtimehaspassedtobeginthenextFixedUpdate.TheoutcomewillvarydependingonhowmuchtimehaspassedsincethelastFixedUpdate.

Ifenoughtimehaspassed,thentheFixedUpdate()methodisinvokedglobally,andanyCoroutinestiedtoFixedUpdates(thatis,yieldstoWaitForFixedUpdate())arehandledimmediatelyafterward,followedbyphysicsupdatesandtrigger/collidercallbacks.

Iflessthan20mshasgonebysincethelastFixedUpdate,thenthecurrentFixedUpdateisskipped.Atthispoint,input,gameplaylogic,andrenderingmusttakeplaceandcompletebeforeUnityperformsthenextFixedUpdatecheck,andsoon,asthisprocessrepeatsitselfduringruntime.ThisdesigngivesbothFixedUpdatesandthePhysicsSystemahigherpriorityoverrendering,butforcesthephysicssimulationintoafixedframerate.

NoteInordertoensuresmoothmotionduringframeswherephysicsupdatesareskipped,somePhysicsEngines(includingUnity’s)interpolatethestatebetweenthepreviousstateandthecurrentstatebasedonhowmuchtimeremainsuntilthenextFixedUpdate.

Thisensuresthat,graphically,objectsappeartomovesmoothlyduringhighframerates,eventhoughtheyareonlybeingupdatedevery20ms.

MaximumAllowedTimestepItisimportanttonotethatifalotoftimehaspassedsincethelastFixedUpdate(forexample,thegamefrozemomentarily),thenphysicsandFixedUpdateswillcontinuetobecalculateduntiltheyhave“caughtup”withthecurrenttime.Forexample,ifthepreviousframetook100mstorender(forexample,asuddenperformancespikedroppingthegameto10FPS),thenthePhysicsSystemwillneedtoupdatefivetimes.TheFixedUpdate()methodwillthereforebecalledfivetimesbeforeUpdate()canbecalledagainduetothedefaultFixedUpdateTimestepof20ms.If,forwhateverreason,theprocessingofthesefiveupdatesconsumes20msormore,thenitwillneedtoinvokeasixthupdate!

Consequently,it’spossibleduringmomentsofheavyphysicsactivitythatthePhysicsEnginecantakemorethan20mstocompleteaphysicsupdate,whichitselftakesanother20ms,andsoon,suchthatitisneverabletoescapeandallowanotherframetorender(thisisoftenknownasthe“spiralofdeath”).TopreventthePhysicsEnginefromlockingupourgameduringthesemoments,thereisamaximumamountoftimethatthePhysicsEngineisallowedtoprocessbetweeneachrender.ThisthresholdiscalledtheMaximumAllowedTimestep,andifthecurrentFixedUpdateistakinglongertoprocessthanthisvalue,thenitwillsimplystopandforgofurtherprocessinguntiltheendofthenextrender.

http://freepdf-books.com

Page 212: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Thisdesignallowstherenderingsystemtoatleastrenderthecurrentstate,andallowforgameplaylogictomakesomedecisionsduringraremomentswherephysicscalculationhasgoneballistic(punintended).

PhysicsupdatesandruntimechangesWhenthePhysicsSystemprocessesthenexttimestep,itmustmoveanyactiveRigidbodyobjects,detectanycollision,andinvokethecollisioncallbacksonthecorrespondingobjects.It’sforexactlythisreasonthattheUnitydocumentationexplicitlywarnsustoonlymakechangestoRigidbodyobjectsinFixedUpdate()andotherphysicscallbacks.Thesemethodsaretightly-coupledwiththeupdatefrequencyofthePhysicsEngine,asopposedtootherpartsofthegameloop,suchasUpdate().

ThismeansthatcallbackssuchasOnTriggerEnter()aresafeplacestomakeRigidbodychanges,whilemethodssuchasUpdate()andtime-basedCoroutinesarenot.NotfollowingthisadvicecouldcauseunexpectedphysicsbehaviorasmultiplechangesaremadetothesameobjectbeforethePhysicsSystemisgivenachancetocatchandprocessallofthem,resultinginsomeespeciallyconfusinggameplaybugs.

ItlogicallyfollowsthatthemoretimewespendinanygivenFixedUpdateiteration,thelesstimewehaveforthenextgameplayandrenderingpass.Mostofthetimethisresultsinminor,unnoticeablebackgroundprocessingtasks,asthePhysicsEnginebarelyhasanyworktodo,andFixedUpdate()callbackshavealotoftimetocompletetheirwork.

But,insomegames,thePhysicsEnginecouldbeperformingalotofcalculationsduringeachandeveryFixedUpdate.Thiskindofbottleneckinginphysicsprocessingtimewillaffectourrenderingframerate,causingittoplummetasthePhysicsSystemistaskedwithgreaterandgreaterworkloads.Essentially,therenderingsystemwillproceedasnormal,butwheneverit’stimeforaFixedUpdate,thenitwouldbegivenverylittletimetogeneratethecurrentdisplay,causingasuddenstutter.ThisisinadditiontothevisualeffectofthePhysicsSystemstoppingearlybecauseithittheMaximumAllowedTimestep.Allofthistogetherwillgenerateapooruserexperience.

Hence,tokeepasmoothandconsistentframerate,thegoalistofreeupasmuchtimeaswecanforrenderingbyminimizingtheamountoftimethePhysicsSystemtakestoprocessanygiventimestep.Thisappliesinboththebest-casescenario(nothingmoving)andworst-casescenario(everythingsmashingintoeverythingelseatonce).Thereareanumberoftime-relatedfeaturesandvalueswecantweakwithinthePhysicsSystemtoavoidperformancepitfallssuchasthese.

http://freepdf-books.com

Page 213: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

StaticandDynamicCollidersThereisarathersignificantnamespaceconflictwiththeterm“static”inUnity.WehavealreadycoveredstaticGameObjects,thevariousStaticsubflags,theStaticBatchingfeature,andthenthere’stheuseofstaticvariablesandclassesinC#.Meanwhile,Unity’soriginalphysicsimplementationfor3DobjectshasitsownconceptofStaticColliders.Later,when2Dphysicswasimplemented,itkeptthesameconceptofStaticColliderstokeepthingsconsistentbetweenthem.

So,withthisinminditisveryimportanttorememberthatStaticCollidersarenotobjectswiththeStaticflagenabled,sincethoseflagsareaUnityEngineconcept.StaticCollidersaresimplycollidersthatdonothaveanattachedRigidbody.Meanwhile,colliderswithanattachedRigidbodyarecalledDynamicColliders.

ThePhysicsSystemcombinesStaticCollidersintoadifferent,optimizeddatastructure,whichhelpstosimplifyfutureprocessingtasks.Theseobjectswillnotreacttoimpulsesappliedbyobjectscollidingwiththem,butwillpreventotherobjectsfrommovingthroughthem.ThismakesStaticCollidersidealforworldbarriersandotherobstaclesthatmustnotmove.

http://freepdf-books.com

Page 214: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CollisiondetectionTherearethreesettingsforcollisiondetectioninUnity:Discrete,Continuous,andContinuousDynamic.TheDiscretesettingeffectivelyteleportsobjectsasmalldistanceeverytimestepbasedontheirvelocityandhowmuchtimehaspassed.Afteralltheobjectshavebeenmoved,itthenperformsabounding-volumecheckforanyoverlaps,treatsthemascollisions,andresolvesthembasedontheirphysicalpropertiesandhowtheyoverlap.Thismethodriskscollisionsbeingmissedifsmallobjectsaremovingtooquickly.

Bothofthecontinuouscollisiondetectionmethodsworkbyinterpolatingobjectsfromtheirstartingandendingpositionsforthecurrenttimestepandcheckingforanycollisionsalongtheway.Thisreducestheriskofmissedcollisionsandgeneratesamoreaccuratesimulation,attheexpenseofsignificantlygreaterCPUoverheadcomparedtotheDiscretesetting.

TheContinuoussettingonlyenablescontinuouscollisiondetectionbetweenthegivencolliderandStaticColliders(recallthatStaticCollidersaresimplycolliderswithoutanyattachedRigidbody).ThesameobjectswillbesimultaneouslytreatedasusingtheDiscretesettingwhenitcomestocollisiondetectionwithotherdynamicobjects(thosewithanattachedRigidbody).Meanwhile,theContinuousDynamicsettingisslightlydifferentasitenablesthesamecontinuouscollisiondetection,butdoessobetweenthegivencolliderandallothercolliders,bothStaticandDynamic.

Thefollowingscreenshotshowshowthediscreteandcontinuouscollisiondetectionmethodswouldworkforapairofsmall,fast-movingobjects:

Thisisanextremeexampleforthesakeofillustration.Inthediscretecase,wecanseethattheobjectsare“teleporting”adistancearoundfourtimestheirownsizeinasingletimestep,whichwouldtypicallyonlyhappenwithverysmallobjectswithveryhighvelocities,andishenceveryrareifourgameisrunningoptimally.Inmostcases,thedistancestheobjectstravelinasingle20mstimesteparemuchsmallerrelativetothesizeoftheobject,andsothecollisioniseasilydetected.

http://freepdf-books.com

Page 215: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CollidertypesTherearefivedifferenttypesof3DCollidersinUnity5.Inorderofthelowestperformancecosttothegreatest,theyare:Sphere,Capsule,Cylinder,Box,andMeshColliders.Thefirstfourcollidertypesareconsideredprimitivesandmaintainconsistentshapes,althoughtheycangenerallybescaledindifferentdirectionstomeetcertainneeds.MeanwhileMeshColliderscanbecustomizedtoaparticularshapedependingontheassignedmesh.

NoteTherearealsothreemain2DColliders:Circle,Box,andPolygon,whicharefunctionallysimilartoSphere,Box,andMeshCollidersin3D.Allofthefollowinginformationisessentiallytransferabletotheequivalent2Dshape.

Inaddition,therearetwovarietiesofMeshCollider:convexandconcave.Thedifferenceisthataconcaveshapefeaturesatleastoneinternalangle(ananglebetweentwoedgesinsidetheshape)ofgreaterthan180degrees.Toillustratethis,thefollowingscreenshotshowsthedistinguishingdifferencebetweenconvexandconcaveshapes:

TipAneasywaytorememberthedifferencebetweenconvexandconcaveshapesisthataconcaveshapehasatleastone“cave”withinit.

BothMeshCollidertypesusethesameComponent(aMeshCollider!),andwhichtypeofMeshCollidergetsgeneratedistoggledusingtheConvexcheckbox.EnablingthisoptionwillallowtheobjecttocollidewithotherMeshCollidersmarkedasConvex,aswellasprimitiveshapes(Spheres,Boxes,andsoon.).Inaddition,iftheConvexcheckboxisenabledforaMeshColliderwithaconcaveshape,thenthePhysicsSystemwillautomaticallysimplifytheconcaveshape,generatingacolliderwiththenearestconvexshapeitcan.Intheprecedingexample,ifweimporttheconcavemeshontheright,and

http://freepdf-books.com

Page 216: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

enabletheConvexcheckbox,itwouldgenerateacollidershapeclosertotheconvexmeshontheleft.

Ineithercase,thePhysicsSystemwillattempttogenerateacolliderthatmatchestheshapeoftheattachedmesh,withanupperlimitof255vertices.Ifthetargetmeshhasmoreverticesthanthis,thenitwillthrowanerrorduringgenerationofthemesh.NotethatConcaveMeshColliderswithattachedRigidbodyobjectsarenotsupportedinUnity5.ConcaveshapescanonlybeusedasStaticColliders(forexample,acollidableobjectintheworldthatdoesn’tmove),orTriggerVolumes(forexample,anoddly-shapedpoolofacid).

http://freepdf-books.com

Page 217: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheCollisionMatrixThePhysicsSystemfeaturesaCollisionMatrixthatdefineswhichobjectsareallowedtocollidewithwhichotherobjects.ObjectsthatdonotfitthismatrixareautomaticallyignoredbythePhysicsSystemwhenthetimecomestoresolveboundingvolumeoverlapsandcollisions.Thissavesonphysicsprocessingduringcollisiondetectionstages,andalsoallowstheobjectstomovethroughoneanotherwithoutanycollisionstakingplace.

TheCollisionMatrixsystemworksthroughUnity’sLayersystem.Thematrixrepresentseverypossiblelayer-to-layercombinationthatmightbepossible,andenablingacheckboxmeansthatcollidersinbothofthoselayerswillbecheckedduringthecollisiondetectionphase.Notethatthere’snowaytoallowonlyoneofthetwoobjectstorespondtothecollision.Ifonelayercancollidewithanother,thentheymustbothrespondtothecollision(withtheexceptionofStaticColliders,whicharen’tallowedtorespondtocollisions).

TheCollisionMatrixcanbeaccessedthroughEdit|ProjectSettings|Physics(orPhysics2D)|LayerCollisionMatrix.

Notethatwearelimitedtoonly32totallayersforourentireproject(sincethePhysicsSystemusesa32-bitbitmasktodetermineinter-layercollisionopportunities),sowemustorganizeourobjectsintosensiblelayersthatwillextendthroughouttheentirelifetimeoftheproject.If,forwhateverreason,32layersarenotenoughforourproject,thenwemightneedtofindcunningwaystoreuselayers,orremovelayersthataren’tnecessary.

http://freepdf-books.com

Page 218: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

RigidbodyactiveandsleepingstatesEverymodernPhysicsEnginesharesacommonoptimizationtechniquewherebyobjectsthathavecometoresthavetheirinternalstatechangedfromanactivestatetoasleepingstate.Whilesleeping,little-to-noprocessortimewillbespentupdatingtheobjectuntilithasbeenawokenbysomeexternalforceorevent.

Thevalueofmeasurementthatisusedtodetermine“rest”tendstovarybetweenengines;itcouldbecalculatedusinglinearandrotationalspeed,kineticenergy,momentum,orsomeotherphysicalpropertyoftheRigidbody.Inanycase,ifanobjecthasnotexceededsomethresholdvalueinashorttime,thenthePhysicsEnginewillassumetheobjectwillnolongerneedtomoveagainuntilithasundergoneanewcollision,oranewforcehasbeenappliedtoit.Untilthen,thesleepingobjectwillmaintainitscurrentposition.

Inessence,thePhysicsEngineisautomaticallycullingsomeprocessingtasksforobjectsthathaveasmallamountofkineticenergy.Butthisdoesnotremoveitentirelyfromthesimulation.IfamovingRigidbodyapproachesthesleepingobject,thenitmuststillperformcheckstoseewhethernearbyobjectshavecollidedwithit,whichwouldreawakenthesleepingobject,reintroducingittothesimulationforprocessing.ThethresholdvalueforthesleepingstatecanbemodifiedunderEdit|ProjectSettings|Physics|SleepThreshold.WecanalsogetacountofthetotalnumberofactiveRigidbodyobjectsfromthePhysicsareaoftheProfiler.

http://freepdf-books.com

Page 219: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

RayandobjectcastingAnothercommonfeatureofPhysicsEnginesistheabilityto“cast”arayfromonepointtoanother,andgatherdataaboutoneormoreoftheobjectsinitspath.Itisprettycommontoimplementimportantgameplaytasksthroughcastingandbounding-volumechecks.Firinggunsistypicallyimplementedbyperformingraycastsfromtheplayertothetargetlocationandfindinganyviabletargetsinitspath(evenifit’sjustawall).

Wecanalsoobtainalistoftargetswithinanexplosionradius,suchasfromagrenadeorfireball,usingaPhysics.OverlapSphere()check,andsothisistypicallyhowsucharea-of-effectabilitiesareimplemented.

Wecanevencastentireobjectsforwardinspace,usingPhysics.SphereCast()andPhysics.CapsuleCast().Thesemethodsareoftenusedifweneedraysoflargersizes,orwewishtoseewhatwouldbeinthepathofamovingcharacter.

http://freepdf-books.com

Page 220: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 221: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PhysicsperformanceoptimizationsNowthatwehaveanunderstandingofthemostsignificantfeaturesoftheUnityPhysicsEngine,wecancoversomeoptimizationtechniquestoimproveourgame’sphysicsperformance.

http://freepdf-books.com

Page 222: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ScenesetupFirstly,thereareanumberofbestpracticeswecanapplytoourScenestoimproveconsistencyofthephysicssimulation.NotethatthesetechniqueswillnotnecessarilyimproveCPUormemoryusage,buttheywillresultinareducedlikelihoodofinstabilityfromthePhysicsEngine.

ScalingWeshouldtrytokeepallphysicsobjectscalesintheworldascloseto1:1:1aswepossiblycan.Thismeansthatforthedefaultgravityvalueof-9.81,theunitscaleoftheworldisimpliedtobe1meterperunit,sincetheforceofgravityatthesurfaceoftheEarthis9.81m/s²(mostgamesaretryingtosimulatethissituation).Ourobjectsizesshouldreflectourimpliedworldscale,sincescalingthemtoolargewillcausegravitytoappeartomovetheobjectsmuchmoreslowlythanwewouldexpect.Theconverseisalsotrue;scalingobjectstoosmallwillmakethemappeartofalltooquicklyandwillnotseemrealistic.

Wecantweaktheworld’simpliedscalebymodifyingthestrengthofgravityunderEdit|ProjectSettings|Physics(orPhysics2D)|Gravity.However,beawarethatanyfloating-pointarithmeticwillbemoreaccuratewithvaluescloserto0,soifwehavesomeobjectsthathavescalevaluesfarabove(1,1,1),eveniftheymatchtheimpliedworld-scale,thenwecouldstillobserveerraticphysicsbehavior.So,earlyintheprojectweshouldimportandscaleourmostcommonphysicsobjectsaroundascalevalueof(1,1,1),andthenadjustthevalueofgravitytomatch.Thiswillgiveusareferencepointtoworkwithasweintroducenewobjects.

TipBewarnedthatUnity4alsohasavalueforSpeedofSoundinitsAudiosettings,whichisusedduringanyDoppler-basedaudioeffects.Thedefaultvalueis343tomatchthespeedofsoundinairof343ms-1.Changingtheimpliedworldscaleviagravitywillrequirethisvaluetobeadjustedtomaintainconsistency.Unity5calculatestheDopplerEffectdifferentlyandsothisvariablewasremoved,nolongermakingthisissueaconcern.

PositioningSimilarly,keepingallobjectscloseto(0,0,0)inpositionwillresultinbetterfloating-pointaccuracy,improvingtheconsistencyofthesimulation.SpaceSimulatorandFree-Runninggamestrytosimulateincrediblylargespaces,andtheytypicallyusethistechniqueasmuchaspossiblebysecretlyteleporting,(orsimplykeeping)theplayercharactercenteredintheworld.Atthispoint,eithereverythingelseismovedtosimulatetravel,orvolumesofspacearecompartmentalizedsothatphysicscalculationsarealwayscalculatedwithvaluesclosetozero.Thisensuresthatallobjectsremaincloseto(0,0,0)inordertoavoidfloating-pointinaccuraciesastheplayertravelsgreatdistances.

Othertypesofgamesshouldnotriskintroducingfloating-pointinaccuracy,sounlesswe’realreadydeepintoourproject(suchthatchangingandre-testingeverythingatalate

http://freepdf-books.com

Page 223: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

stagewouldbetoomuchhassle),weshouldtrytokeepallofourphysicsobjectscloseto(0,0,0).Plus,thisissimplygoodpracticeforourprojectworkflowasitmakesitmuchfastertoaddandpositionobjectsinourgameworld.

MassTheUnitydocumentationrecommendsthatobjectmassvaluesstayaround0.1,withnovaluesexceeding10,duetotheinstabilityitgenerates:http://docs.unity3d.com/ScriptReference/Rigidbody-mass.html.

Thismeansweshouldnotthinkofmassintermsofmeasurementssuchaspoundsorkilograms,butratherarelativevaluebetweenobjects.Weshouldtrytomaintainconsistentandreasonableratiosofmassbetweencollidingobjects.Havingobjectscollidingwithamassratioofgreaterthan1,000willmostcertainlyresultinerraticbehaviorduetothelargemomentumdifferenceandeventuallossoffloatingpointprecision.Weshouldtrytoensureinter-objectcollisionsoccurwithobjectswithsimilarvaluesoftheirmassproperty,andobjectpairsthathaveasignificantscaledifferenceshouldbeculledwiththeCollisionMatrix(moreonthisshortly).

TipImpropermassratiosarethemostcommoncauseforphysicsinstabilityanderraticbehavior.

NotethattheforceofgravityatthecentreoftheEarthaffectsallobjectsequally,regardlessoftheirmass,soitdoesnotmatterifweconsideramasspropertyvalueof1tobethemassofarubberballorthemassofawarship.There’snoneedtoadjusttheforceofgravitytocompensateforanyassumptionswe’remakingwiththeserelativemasspropertyvalues.Whatdoesmatter,however,istheamountofairresistancethegivenobjectundergoeswhilefalling(thisiswhyafeatherfallsslowerthanasolidobjectofidenticalmass).So,tomaintainrealisticbehavior,wemayneedtocustomizethedragpropertyforsuchobjectsorcustomizetheforceofgravityonaper-objectbasis(suchasdisablingtheUseGravitycheckboxandapplyingacustomgravitationalforceviaScriptcode).

http://freepdf-books.com

Page 224: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UseStaticCollidersappropriatelyAspreviouslymentioned,thePhysicsSystemautomaticallygeneratesadatastructurefromthedataofallStaticColliders(colliderswithoutRigidbodyobjects)separatelyfromthestructurethatmanagesDynamicColliders(colliderswithRigidbodyobjects).Unfortunately,ifnewobjectsareintroducedintothedatastructureatruntime,thenitmustberegenerated.ThisislikelytocauseasignificantCPUspike.ThismakesitvitalthatweavoidinstantiatingnewStaticCollidersduringgameplay.

Inaddition,merelymoving,rotating,orscalingStaticCollidersalsotriggersthisregenerationprocessandshouldbeavoided.Ifwehavecollidersthatwewishtomovearoundwithoutreactingtootherobjectscollidingwiththeminaphysicalway,thenweshouldattachaRigidbodytomakeitaDynamicColliderandsettheKinematicflagtotrue.Thisflagpreventstheobjectfromreactingtoexternalimpulsesfrominter-objectcollisions.ThisallowsittobehavesimilartoaStaticCollider,butitisnowinadatastructurethatproperlysupportsmovingobjects,sowecanmoveitaroundfromScriptcode(duringFixedUpdates!),anditwillapplyimpulsestootherobjects.

TipIt’sforthisreasonthattheKinematicflagisoftenusedonobjectscontrolledbyplayers;theycanpushotherobjectsaroundbutshouldn’tbepushedaroundthemselves.

http://freepdf-books.com

Page 225: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

OptimizetheCollisionMatrixAsweknow,thePhysicsSystem’sCollisionMatrixdefineswhichobjectsassignedtocertainlayersareallowedtocollidewithobjectsassignedtootherlayers.Ortoputitmoresuccinctly,whichobjectpairsareevenconsideredbythePhysicsSystem.Everyotherobject-layer-pairissimplyignoredbythePhysicsEngine,whichmakesthisanimportantavenueforminimizingPhysicsEngineworkloadsinceitreducesthenumberofbounding-volumechecksthatmustbeperformedateachandeverytimestep.

TipReminder:theCollisionMatrixcanbeaccessedthroughEdit|ProjectSettings|Physics(orPhysics2D)|LayerCollisionMatrix.

ThefollowingscreenshotshowsacommonCollisionMatrixforanarcadeshootergame:

Inthisexample,wehaveminimizedthenumberofpossibleinter-objectcollisionsforthePhysicsSystemtocheck.Sincepowerupscanonlybepickedupbytheplayer,thenthereisnoneedtocomparecollisionsbetweenpowerupsandobjectsfromanyotherlayers.Meanwhile,wedon’twishforprojectilestocollidewiththeobjectthatfiredit,whichexcludesEnemyProjectilesfromcollidingwithenemies,andPlayerProjectilesfromcollidingwiththeplayer.Wewanteverythingtocollidewiththegameworld(wallsandothersurfaces),andperhapswedon’twantprojectilescollidingwithotherprojectiles(althoughsomegamesmightwantthis!).

WeshouldperformlogicalsanitycheckslikethisforalloftheLayercombinationsintheCollisionMatrixtoseewhetherwe’rewastingprecioustimecheckingforinter-objectcollisionsbetweenobject-pairsthataren’tnecessary.

http://freepdf-books.com

Page 226: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PreferdiscretecollisiondetectionWeshouldusetheDiscreteoptionbydefaultforthemajorityofobjects.Teleportingobjectsonceandperformingasingleoverlapcheckbetweennearbyobject-pairsisafairlytrivialamountofwork.However,theamountofcalculationittakestointerpolatetheobjectsbetweentheirstartingandendingpositions,andsimultaneouslyverifyanyslightbounding-volumeoverlapsbetweenthesepointsovertime,issignificantlygreater.

Consequently,theContinuouscollisiondetectionoptionisanorderofmagnitudemoreexpensivethantheDiscretedetectionmethod,andtheContinuousDynamiccollisiondetectionsettingisanorderofmagnitudemoreexpensivethanContinuous!HavingtoomanyobjectsofthecontinuoustypeswillcauseseriousperformancedegradationincomplexScenes.Ineithercase,thecostsaremultipliedbythenumberofobjectsthatneedtobecomparedduringanygivenframeandwhetherornotthecomparisoncolliderisStaticorDynamic.

Ergo,thecontinuousdetectionsettingsshouldonlybeusedinextremecircumstances.TheContinuoussettingshouldbeusedwhenimportantcollisionsarefrequentlymissedwiththestaticworld,forinstance,ifweexpectcertainobjectstomovequickly,andwewishtobecertaintheyneverfallthroughthegameworldorteleportthroughwalls.Finally,theContinuousDynamicsettingshouldonlybeusedifthesamesituationappliesbutwewishtocatchcollisionsbetweenpairsofvery-fastmovingDynamicColliders.Unlesswehavegoodreasontousethem,allothersituationsshouldfavortheDiscretesetting.

But,perhaps,theDiscretesettingisn’tworkingwell-enoughonalargescale.Perhapsourentiregamerevolvesaroundalotofsmallphysicsobjectsanddiscretecollisiondetectionsimplyisn’tcatchingenoughcollisionstomaintainproductquality.Well,we’reinluck,becausewecancustomizethephysicstimesteptogivetheDiscretecollisionoptionabetterchanceofcatchingsuchcollisionsbymodifyinghowfrequentlytheenginechecksforFixedUpdates.

http://freepdf-books.com

Page 227: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ModifytheFixedUpdatefrequencyAsmentionedpreviously,FixedUpdatesandphysicstimestepprocessingarestrongly-coupled,sobymodifyingthefrequencyofFixedUpdatecheckswenotonlychangethefrequencythatthePhysicsSystemwillcalculateandresolvethenextcallback,butwewillalsochangehowfrequentlyFixedUpdate()callbacksarebeinginvoked.Consequently,changingthisvaluecanberiskyifwe’redeepintoourprojectandhavealotofbehaviorthatdependsonthesecallbacks.

AlteringtheFixedUpdatefrequencycanbeaccomplishedthroughtheEdit|ProjectSettings|Time|FixedTimesteppropertyintheEditor,orthroughtheTime.fixedDeltaTimepropertyinscriptcode.

Reducingthisvalue(increasingthefrequency)willforcethePhysicsSystemtoprocessmorefrequently,givingitabetterchanceofcatchingcollisionsbetweenourDynamic,Discreteobjects.Naturally,thiscomeswithaCPUcostsincewe’reinvokingmoreFixedUpdate()callbacks,aswellasaskingthePhysicsEnginetoupdatemorefrequently,havingitmoveobjectsandverifycollisionsmoreoften.

Conversely,increasingthisvalue(decreasingthefrequency)providesmoretimefortheCPUtocompleteothertasksbeforeitmusthandlephysicsprocessingagain,orlookingatitfromanotherperspective,givingthePhysicsSystemmoretimetoprocessthelasttimestepbeforeitbeginsprocessingthenextone.But,loweringtheFixedUpdatefrequencywouldessentiallylowerthemaximumvelocityatwhichobjectscanbemovingbeforethePhysicsSystemcannolongercapturecollisionsbetweendiscreteobjects(dependingontheobjects’sizes).

ThismakesitabsolutelyvitaltoperformasignificantamountoftestingeachtimetheFixedTimestepvalueischanged.Evenwithacompleteunderstandingofhowthisvalueworks,itisdifficulttopredictwhattheoveralloutcomewilllooklikeduringgameplay,

http://freepdf-books.com

Page 228: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

andwhethertheresultispassableforqualitypurposes.Hence,changestothisvalueshouldbemadeearlyintheproject’slifecycleandthenmadeinfrequentlyinordertogetasufficientamountoftestingagainstasmanyphysicssituationsaspossible.

ItmighthelptocreateatestScenethatflingssomeofourhigh-velocityobjectsatoneanothertoseeiftheresultsareacceptable,andrunthroughthisScenewheneverFixedTimestepchangesaremade.Butactualgameplaytendstoberathercomplex,withmanybackgroundtasksandunanticipatedplayerbehaviorthatcausesadditionalworkforthePhysicsSystem,orgivesitlesstimetoprocessthecurrentiteration.Actualgameplayconditionsaredifficulttoduplicateinavacuum,andthere’snosubstitutefortherealthing,sothemoretestingwecanaccomplishagainstthecurrentvalueofFixedTimestep,themoreconfidentwecanbethatthechangesmeetacceptablequalitystandards.

Wealwayshavethecontinuouscollisiondetectionoptionsasalastresorttooffsetsomeoftheresultinginstabilitywe’reobserving.Butunfortunately,evenifthechangesaretargeted,itismorelikelythatthiswillcausefurtherperformanceissuesthanwestartedwithduetotheoverheadcostsofcontinuouscollisiondetection.ItwouldbewisetoprofileourScenebeforeandafterenablingcontinuouscollisiondetectiontoverifythatthebenefitsareoutweighingthecosts.

http://freepdf-books.com

Page 229: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AdjusttheMaximumAllowedTimestepIftheMaximumAllowedTimestepvaluegetshitregularly,thenitwillresultinsomeprettybizarre-lookingphysicsbehavior.Rigidbodyobjectswillappeartoslowdownorfreezeinspace,sincethePhysicsEngineneedstokeepexitingearlybeforeithasfullyresolveditsentiretimequota.Inthiscase,itisaclearsignthatweneedtooptimizeourphysicsfromotherangles.Butattheveryleastwecanbeconfidentthethresholdwillpreventthegamefromcompletelylockingupduringaphysicsprocessingspike.

ThissettingcanbeaccessedthroughEdit|ProjectSettings|Time|MaximumAllowedTimestep.Thedefaultsettingistoconsumeamaximumof0.333seconds,whichwouldmanifestitselfasaverynoticeabledropinframerate(amere3FPS)ifitwerebreached.Ifweeverfeeltheneedtochangethissetting,thenweobviouslyhavesomebigproblemswithourphysicsworkload,soitisrecommendedtoonlytweakthisvalueifwehaveexhaustedallotherapproaches.

http://freepdf-books.com

Page 230: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Minimizecastandbounding-volumechecksAlloftheraycastingmethodsareincrediblyuseful,buttheyarerelativelyexpensive(particularlyCapsuleCast()andSphereCast()),requiringustominimizehowoftentheyarecalled.WeshouldavoidcallingthesemethodsregularlywithinUpdatecallbacksorCoroutines,savingthemonlyforkeyeventsinourscriptcode.

Ifweabsolutelymustrelyonpersistentline,ray,orarea-of-effectcollisionareasinourScene(examplesincludesecuritylasers,orcontinuouslyburningfires),thentheywouldbebettersimulatedusingasimpleTriggerCollider,ratherthanperformingcontinuousraycastingoroverlapchecks.

Ifsuchreplacementsarenotpossible,andwetrulyneedpersistentcastingchecksusingthesemethods(suchasared-dotlasersight),thenwecanminimizetheamountofprocessingeachcallmakesbyexploitingtheLayerMaskobjects.

Forexample,alazyraycastwouldlooklikeso:

[SerializeField]float_maxRaycastDistance;

voidPerformRaycast(){

RaycastHithitInfo=newRaycastHit();

if(Physics.Raycast(newRay(transform.position,transform.forward),

outhit,_maxRaycastDistance)){

//handleraycastresulthere

}

}

ButthisoverloadofPhysics.Raycast()willcausetheraytocollidewiththefirstobjectofanylayerinitspath.ThePhysics.RaycastmethodhasmultipleoverloadsthatacceptaLayerMaskobjectforanargument.Wecanusethistocustomizewhichobjectsshouldbecheckedbytheraycast,simplifyingtheworkloadforthePhysicsEngine:

[SerializeField]float_maxRaycastDistance;

[SerializeField]LayerMask_layerMask;

voidPerformRaycast(){

RaycastHithitInfo=newRaycastHit();

if(Physics.Raycast(newRay(transform.position,transform.forward),

outhit,_maxRaycastDistance,_layerMask)){

//handleraycastresulthere

}

}

TheLayerMaskobjectcanthenbeconfiguredthroughtheobject’sInspectorview:

http://freepdf-books.com

Page 231: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TipNotethat,becausetheRaycastHitandRayclassesaremanagedbythenativememoryspaceoftheUnityEngine,theydon’tresultinmemoryallocationsthatdrawtheattentionoftheGarbageCollector.WewilllearnmoreaboutsuchactivityinChapter7,MasterfulMemoryManagement.

http://freepdf-books.com

Page 232: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AvoidcomplexMeshCollidersInorderofefficiency,thevariouscollidersare:Spheres,Capsules,Cylinders,Boxes,ConvexMeshColliders,andfinallyConcaveMeshColliders.However,thefourmainprimitivesareanorderofmagnitudemoreefficientthaneitheroftheMeshColliders,asthemathematicalcalculationsfordetectingandresolvingcollisionsbetweenthemarefairlysuccinctandoptimized.Performingcomparisonsbetweenaconvexshapeandanothercollidercanbeacostlyprocess,whilecomparingbetweenaconcaveshapeandanythingelseisevenmoreexpensive.

NotePerformingruntimebounding-volumechecksbetweenpairsofconcaveshapesisperhapstheclosestthingto“MathematicalArmageddon”thatwemightfindinareal-timephysicssimulation(atleastforafewmoreyears!).Toprotectusfromourownstupidity,Unityeffectivelybansusfromperformingconcave-to-concaveMeshColliderboundingvolumechecks.

Agreatironybetweenphysicsandgraphicsin3Dapplicationsishowdifficultitistohandlesphericalandboxobjectsbetweenthetwoofthem.Theperfectsphericalmeshwouldrequireaninfinitenumberofpolygonstogenerate,buthowasphereisrepresentedinaPhysicsEngineisrelativelytrivialtoresolveforcontactpointsandcollisions.Conversely,asimpleboxtakesaminisculenumberofpolygonsandefforttoproducegraphically,andyettakessignificantlymoremathematicsandprocessingpowertofindcontactpointsandresolvecollisionsfor.Thisimpliesthatgettingthemostoutofbothgraphicsandphysicswouldbetopopulateourworldwithlow-polygongraphicalobjects,representedassphereswithinthePhysicsSystem.However,thiswouldmakeabsolutelynosensetoahumanobserverastheywitnesssharp,pointyobjectsrollingaroundlikeballs.

ItisalwaysimportanttorememberwhenworkingwithPhysicsEnginesthatthephysicalrepresentationofanobjectdoesnotnecessarilyneedtomatchitsgraphicalrepresentation.Thisisbeneficialasagraphicalmeshcanoftenbecondenseddownintoamuchsimplershape,generatingaverysimilarphysicsbehaviorandsparingustheneedtouseanoverly-complexMeshCollider.

Thisseparationofrepresentationsbetweengraphicsandphysicsallowsustooptimizetheperformanceofonesystemwithout(necessarily)negativelyaffectingtheother.Iftherewouldbenonoticeablerepercussionsongameplay,thenwearefreetorepresentcomplexgraphicalobjectswiththesimplestphysicsshapesbehind-the-scenes.Iftheplayernevernotices,thennoharmisdone!

So,wecansolvethisprobleminoneoftwoways:eitherbyapproximatingthephysicsbehaviorofthecomplexshapeusingone(ormore)ofthestandardprimitives,orausingamuchsimplerMeshCollider.

UsesimplerprimitivesMostshapescanbeapproximatedusingoneofthefourprimitivecolliders(inorderof

http://freepdf-books.com

Page 233: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

efficiency):Spheres,Capsules,Cylinders,orBoxes.Infact,wedonotneedtorepresenttheobjectusingonlyasinglecollider;wearefreetouseseveralcollidersifitservesourneedsforcreatingacomplexcollisionshapebyattachingadditionalchildGameObjectswiththeirowncolliders.ThisisalmostalwayslesscostlythanusingasingleMeshColliderandshouldbepreferredovermorecomplexsolutions.

Thefollowingimageshowsahandfulofcomplexgraphicalobjects,representedbyoneormoresimplerprimitivesinthePhysicsSystem:

UsingaMeshColliderforanyoneoftheseobjectswouldbesignificantlymorecostlythantheprimitivecollidersshownhere.Itisworthexploringanyandallopportunitiestosimplifyourobjectsdownusingtheseprimitivesasmuchaswecan,astheycanprovidesignificantperformancegains.

Forexample,concavemeshesareuniqueinthattheycanfeaturegaps,orholes,thatallowothermeshesto“fall”into,oreventhroughthem,whichintroducesopportunitiesfortheobjectstofallthroughtheworldifconcaveshapesareusedforworldcollisionareas.ItisoftenbettertoplaceBoxCollidersinstrategiclocationsforthispurpose.

UsesimplerMeshCollidersThemeshassignedtotheMeshColliderdoesnotnecessarilyneedtomatchthegraphicalrepresentationofthesameobject(Unitysimplypicksitasthedefault).ThisgivesusanopportunitytoreplacetheMeshCollider’smeshpropertywithadifferent,simplermeshforanobject’scolliderfromtheoneweuseforitsgraphicalrepresentation.

ThefollowingimageshowsanexampleofacomplexgraphicalmeshthathasbeengivenasimplifiedmeshforitsMeshCollider:

http://freepdf-books.com

Page 234: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Simplifyingtherenderedmeshintoconvexshapeswithlowerpolygoncountsinthiswaywillgreatlyreducetheoverheadneededtodeterminebounding-volumeoverlapswithothercolliders.Dependingonhowwelltheoriginalobjectisestimated,theremaybefewtononoticeablegameplaydifferences,especiallyinthecaseofthisaxe,whichweexpecttobemovingquicklyascreaturesswingitduringattacks,makingitunlikelythatplayerswillnoticethedifferencebetweenthetwomeshesascolliders.

http://freepdf-books.com

Page 235: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AvoidcomplexphysicscomponentsCertainspecialphysicsColliderComponents,suchasTerrain,Cloth,andWheelColliders,areordersofmagnitudemorecostlythanallprimitivecolliders,andevenMeshCollidersinsomecases.WeshouldsimplynotincludesuchComponentsinourScenesunlesstheyareabsolutelynecessary.Forinstance,ifwehaveTerrainobjectsinthedistancethattheplayerwillneverapproach,thenthere’slittlereasontoincludeanattachedTerrainCollider.

GamesfeaturingClothComponentsshouldconsiderinstantiatingdifferentobjectswithoutthemwhenrunninginlower-qualitysettings,orsimplyanimatingclothbehavior(althoughitistotallyunderstandableiftheteamhasgrownattachedandfalleninlovewithhowthestuffmovesaround).

GamesusingWheelCollidersshouldsimplytrytousefewerwheelcolliders!Vehicleswithmorethanfourwheelsmaybeabletouseonlyfourwheelstogeneratethecorrectphysicsbehavior,whilefakingthegraphicalrepresentationofadditionalwheels.

http://freepdf-books.com

Page 236: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LetphysicsobjectssleepThePhysicsEngine’ssleepfeaturecanposeseveralproblemsforourgame.

NoteReminder:thesleepthresholdcanbemodifiedunderEdit|ProjectSettings|Physics|SleepThreshold.

Firstly,somedevelopersdon’trealizethatmanyoftheirRigidbodyobjectsaresleepingduringmostofthelifetimeoftheirapplication.Thistendstoleaddeveloperstoassumethattheycangetawaywith(forexample)doublingthenumberofRigidbodyobjectsintheirgame,andthecostswillsimplydoubletomatchit.Thisisunlikely.Thefrequencyofcollisionsandtotalaccumulatedtimeofactiveobjectsismorelikelytoincreaseinanexponentialfashion,ratherthanalinearone.Thisleadstounexpectedperformancecostswhennewphysicsobjectsareintroducedintothesimulation.WeshouldkeepthisinmindwhenwedecidetoincreasethephysicscomplexityofourScenes.

Secondly,thereisthedangerof“islands”ofsleepingphysicsobjectsbeinggenerated.IslandsarecreatedwhenalargenumberofRigidbodyobjectsaretouchingoneanother,andhavegraduallycometorest—imagineapileofboxesthathavebeenspawnedandformedalargepile.Eventually,alloftheRigidbodyobjectswillfallasleeponceenoughenergyinthesystemislostandtheyallcometorest.However,becausethey’reallstilltouchingoneanother,assoonasoneoftheseobjectsisawoken,itwillstartachainreaction,awakeningallothernearbyRigidbodyobjects.SuddenlywehavealargespikeinCPUusagebecausedozensofobjectshavenowre-enteredthesimulation,andtherearesuddenlymanymorecollisionstoresolveuntiltheobjectsfallasleepagain.

Ifwecouldfindawaytodetectthatislandsareforming,wecouldstrategicallydestroy/despawnsomeofthemtopreventtoomanylargeislandsfrombeinggenerated.Butworkaroundssuchasthesewillbedependentuponthegameitself,asperformingregular,globalchecks,anddistancecomparisonsbetweenallofourRigidbodyobjectsisnotacheaptasktoaccomplish.Forexample,agamethatrequirestheplayertomovelotsofphysicsobjectsintoanarea(forexample,agamethatinvolvesherdingsheepintoapen)couldchoosetodespawntheDynamicColliderobjectassoonastheplayermovesitintoposition,lockingtheobjecttoitsfinaldestination,andeasingtheworkloadonthePhysicsEngine.

Thirdly,changinganyofaRigidbody’spropertiesatruntime,suchasmass,drag,UseGravity,andsoon,willalsoreawakentheobject.Ifwe’reregularlychangingthesevalues(suchasagamewhereobjectsizesandmasseschangeovertime),thentheywillremainactiveforlongerperiodsoftimethanusual.Thisisalsothecaseforapplyingforces,soifwe’reusingacustomgravitysolution(suchassuggestedbackinthesectionentitledMass),weshouldtrytoavoidapplyingthegravitationalforceeveryFixedUpdate,otherwisetheobjectwillbeunabletofallasleep.

Sleepingobjectscanbeablessingandacurse.Theycansaveusalotofprocessingpower,butiftoomanyofthemreawakenatthesametimeoroursimulationistoobusytoallow

http://freepdf-books.com

Page 237: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

enoughofthemtofallasleep,thenwecouldbeincurringsomeunfortunateperformancecostsduringgameplay.Weshouldstrivetolimitthesesituationsasmuchaspossiblebylettingourobjectsenterthesleepingstateasmuchaspossible,andavoidgroupingthemtogetherinlargeclusters.

http://freepdf-books.com

Page 238: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ModifySolverIterationCountJoints,Springs,andotherconnectedRigidbodyobjectsarenottrivialtosimulateintheworldofPhysicsEngines.Becauseoftheco-dependentinteractivity(internallyrepresentedasmovementconstraints)thatoccurswithjoiningtwoobjectstogether,thesystemmustoftenmakeseveralattemptsatsolvingthenecessarymathematicalequations.Thismulti-iterationapproachisrequiredtocalculateanaccurateresultwheneverthereisachangeinvelocitytoanypieceoftheobject-chain.

Itthereforebecomesabalancingactoflimitingthemaximumnumberofattemptsthe“Solver”makestoresolveaparticularsituation,versushowaccuratearesultwecangetawaywith.Wedon’twanttheSolvertospendtoomuchtimeonasinglecollision,becausethereisalotofotherworkthePhysicsEnginehastodowithinthesameiteration.But,wealsodon’twanttoreducethemaximumnumberofiterationstoofarasitwillonlyapproximatewhatthefinalsolutionwouldhavebeenifithadbeengivenmoretimetocalculatetheresult.

NoteThesameSolveralsogetsinvolvedwhenresolvinginter-objectcollisionsandcontacts.Itcanalmostalwaysdeterminethecorrectresultwithasingleiteration,withtheexceptionofsomeveryrareandcomplexcollisionsituations.Itisonlywhenthird-partyobjectswillbeaffectedthroughJointsthattheSolverrequiresadditionalefforttomathematicallyintegratethefinalresult.

TheSolverIterationCountcanbemodifiedunderEdit|ProjectSettings|Physics|SolverIterationCount.Inmostcases,thedefaultvalueofsixiterations(seveniterationsinUnity4)isperfectlyacceptable.But,gamesthatincludeverycomplexjointsystemsmaywishtoincreasethiscounttosuppressanyerratic(ordownrightexplosive)CharacterJointbehaviors,whilesomeprojectsmaybeabletogetawaywithreducingthiscount.Testingmustbeperformedafterchangingthisvaluetoseewhethertheprojectstillmaintainstheintendedlevelsofquality.

Incidentally,ifwefindourgameregularlyrunsintojarring,erratic,andphysics-breakingsituationswithcomplexJoint-basedobjects(suchasragdolls),thenweshouldconsidergraduallyincreasingtheSolverIterationCountuntiltheproblemshavebeensuppressed.TheseproblemstypicallyoccurifourragdollsabsorbtoomuchenergyfromcollidingobjectsandtheSolverisunabletoiteratethesolutiondowntosomethingreasonablebeforeitisaskedtogiveup.Atthispoint,oneoftheJointsgoessupernova,draggingtherestofthemintoorbitalongwithit!

Weshouldalsodoublecheckthatourragdoll’sRigidbodymassesareobeyingtherulessetforthearlierinthischapter,sothattheresultantenergyexchangeandvelocitieswillbemorereasonable.

http://freepdf-books.com

Page 239: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

OptimizingragdollsSpeakingofCharacterJoints,ragdollsareincrediblypopularfeaturesforgoodreason;they’retonsoffun!Ignoringthemorbidityofflingingcorpsesaroundagameworldforthemoment,there’ssomethingaboutwatchingacomplexchainofobjectsflailaroundandsmashintothingsthathitsalotofpsychological“funbuttons”.

ThismakesitverytemptingtoallowmanyragdollstocoexistwithinourSceneatthesametime,butaswequicklydiscover,thisrisksanenormousperformancehitwhentoomanyragdollsareinmotionand/orcollidewithotherobjectsduetotheamountofiterationstheSolverwouldneedtoresolvethemall.So,let’sexploresomewaystoimprovetheperformanceofanyragdollswewishtouse.

ReduceJointsandCollidersUnityprovidesasimpleragdoll-generationtoolunderGameObject|3DObject|Ragdoll…inUnity5,orGameObject|CreateOther|Ragdoll…inUnity4.Thistoolcanbeusedtocreateragdollsfromagivenobjectbyselectingtheappropriatechildobjectstoattachcolliderstoforanygivenbodypartorlimb.Thistoolalwayscreates11differentcollidersandassociatedJoints(pelvis,chest,head,andtwocollidersperlimb),butwemightwishtoconsiderusingonlysixcolliders(body,head,andonecolliderperlimb)togreatlyreducetheoverheadcostattheexpenseofragdollrealism.ThiscanbeachievedbydeletingunwantedcollidersandreassigningtheCharacterJoint’sConnectedBodypropertiestotheproperparentjoints.

Suchsimplificationscouldbeimplementedasameansofreducingoverheadforweakerhardware/lowerqualitysettings,asasimplecompromisetoallowmoreragdollstocoexistinourScene.Itcouldevenbeuseddynamicallyifaparticularnumberofragdollsarealreadypresent.Agodclasswouldneedtokeeptrackofhowmanyragdollscurrentlyexist,butwhennewragdollsareintroduced,wecouldinstantiateasimplerversioninordertokeepthingsrunningsmoothly.

Avoidinter-ragdollcollisionsUnlesswereallydesireinter-ragdollcollisionsthenweshouldperhapsdisablethemusingtheCollisionMatrix.Theperformancecostofragdollsgrowsexponentiallywhenragdollscollidewithoneanother,sincewewouldbeaskingtheSolvertoworkextrahardandriskingerraticbehaviorduetotheapproximationsitisforcedtomake.

DisableorremoveinactiveragdollsFinally,wecouldconsiderdisallowingragdollsfromre-enteringthephysicssimulationaftertheyhavecometorest.Insomegames,oncearagdollhasreacheditsfinal“destination,”wenolongerneedittoremaininthegameworldasaninteractableobject.

Wecanpollanygivencollider’ssleepstatewiththeIsSleepingmethodand,onceithasreachedthisstate,wehaveanumberofoptionswecanpursue.Wecoulddisablealloftheragdoll’scolliders,preventingitfrombeingreintroducedtothesimulation,wecouldremovetheragdollfromtheSceneforthesakeofcleanup,orwecouldkeeptrackofthis

http://freepdf-books.com

Page 240: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ragdollandonlyremoveitwhenadifferentragdollhasbeenintroducedtotheScene.

Whateverapproachwechoosetoimprovetheperformanceofourragdollswillnodoubtresultinlimitingragdollsasagameplayfeature,eitherbyinstantiatingfewerofthem,givingthemlesscomplexity,orgivingthemashorterlifetime,butthesearereasonablecompromisestomakegiventheperformance-savingopportunities.

http://freepdf-books.com

Page 241: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

KnowwhentousephysicsAsalways,thebestmethodofimprovingtheperformanceofafeatureistoavoidusingitasmuchaspossible.Forallmoveableobjectsinourgame,weshouldtakeamomenttoaskourselvesifgettingthePhysicsEngineinvolvedisevennecessary.Ifnot,weshouldlookforopportunitiestoreplacethemwithsomethingsimplerandlesscostly.

Perhapswe’reusingphysicstodetectwhethertheplayerfellintoakill-zone,butourgameissimpleenoughthatweonlyhavekill-zonesataspecificheight.Inthiscase,wecouldavoidphysicscollidersaltogetherandgetawaywithonlycheckingwhethertheplayer’sypositionfallsbelowaparticularvalue.

Asanotherexample,maybewe’retryingtosimulateameteorshower,andourfirstinstinctwastohavemanyfallingobjectsthatmoveviaphysicsRigidbodyobjects,detectcollisionswiththegroundviacolliders,andthengenerateanexplosionatthepointofimpact.ButperhapsthegroundisconsistentlyflatorwehaveaccesstotheTerrain’sHeightMapforsomerudimentarycollisiondetection.Inthiscase,objecttravelcouldbesimplifiedbytweeningtheobjects’transform.positionpropertiesovertimetosimulatethesamebehaviorwithoutrequiringanyphysicscomponents.Inbothcases,wecanreducethephysicsoverheadbysimplifyingthesituationandpushingtheworkintoScriptcode.

TipTweeningisacommonshort-handtermforin-betweening,whichistheactofinterpolatingpropertiesfromonevaluetoanothermathematicallyovertime.Therearemanyuseful(andfree!)tweeninglibraries,availableontheUnityAssetStore,thatprovidealotofusefulfunctionality.

Thereverseisalsopossible;theremightbeoccasionswherewe’reperformingagreatdealofcalculationthroughScriptcodethatcouldbehandledthroughphysicsrelativelysimply.Forexample,wemighthaveimplementedaninventorysystemwithmanyobjectsthatcanbepickedup.WhentheplayerhitsthePickupkey,eachoftheseobjectsmightbecomparedagainsttheplayer’spositiontofigureoutwhichobjectisclosest.WecouldconsiderreplacingalloftheScriptcodewithasinglePhysics.OverlapSphere()calltogetnearbyobjectswhenthekeyispressed,andthenfigureouttheclosestpickupobjectfromtheresult(orjustpickupallofthem!).Thiscouldgreatlyreducethetotalnumberofobjectsthatmustbecomparedeachtimethekeyispressed.

Theopportunitiesareaswideandfar-reachingasourowningenuity.Theabilitytorecognizeopportunitiestoremoveunnecessaryphysicsgrunt-workfromourScenes,and/orusephysicstoreplacebehaviorthatiscostlywhenperformedthroughScriptcode,isavitalskillthatwillserveuswellwhensavingperformanceincurrentandfuturegamedevelopmentprojects.

http://freepdf-books.com

Page 242: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ConsiderupgradingtoUnity5Ifwe’rerunningUnity4,anabsolutelastresorttoimprovephysicsperformancewouldbetoconsiderupgradingtoUnity5.TherewereamultitudeofhugeperformanceenhancementswithUnity5’supgradefromPhysXversion2.8.3toversion3.3.TheseimprovementscannotbeoverstatedastheygrantaboutdoubletheperformanceofthePhysicsSystemascomparedtoUnity4.TheupgradeincludeslessoverheadinmovingStaticColliders,improvedperformanceincontinuouscollisiondetectionmethods,supportformorerigidbodies,improvedClothandWheelCollidercomponents,aswellasmulticorephysicssupport.Inshort,itallowsustoreducetheperformancecostofthesameScene,orcrammorephysicsactivityintoourScenesforthesamecost.

However,thesechangesresultedinsomesignificantAPIchangesforcertaintasks,whichmeansScriptingandComponentsinUnity4maynotbefullycompatiblewithUnity5(andnotjustforphysics-relatedtasks).Consequently,theupgradeitselfisunlikelytobetrivial,andweshouldnotforgettomakeabackupofourprojectbeforeattemptingtodoso.TheamountofworkwillultimatelydependonthecomplexityofourprojectandhowitaffectsanyAssetStorepurchaseswerelyon.Eachassetislikelytoneedupdatesofitsownandanyassetsthathavefallenoutofsupportwillneedtobereplaced.

http://freepdf-books.com

Page 243: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 244: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryWe’vecoverednumerousmethodstoimproveourgame’sphysicssimulationbothintermsofperformance,andconsistency.ThebesttechniquewhenitcomestocostlysystemssuchasPhysicsEnginesissimplyavoidance.Thelessweneedtousethesystem,thelessweneedtoworryaboutitgeneratingbottlenecks.Intheworstcase,wemayneedtoreducethescopeofourgametocondensephysicsactivitydowntoonlytheessentials,butaswe’velearned,thereareplentyofwaystoreducephysicscomplexitywithoutcausinganynoticeablegameplayeffects.

Inthenextchapter,wewillimmerseourselvesinUnity’sgraphicssystem,discoveringhowtomaximizegraphicalfidelityusingalloftheCPUcycleswe’vefreedupusingtheperformanceenhancementsfromearlierchapters.

http://freepdf-books.com

Page 245: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 246: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter6.DynamicGraphicsThereisnoquestionthattherenderingsystemofmoderngraphicsdevicesiscomplicated.Evenrenderingasingletriangletothescreenengagesmanyofthesecomponents,sinceGPUsaredesignedforlargeamountsofparallelism,asopposedtoCPUs,whicharedesignedtohandlevirtuallyanycomputationalscenario.Moderngraphicsrenderingisahigh-speeddanceofprocessingandmemorymanagementthatspanssoftware,hardware,multiplememoryspaces,multiplelanguages,multipleprocessors,multipleprocessortypes,andalargenumberofspecial-casefeaturesthatcanbethrownintothemix.

Tomakemattersworse,everygraphicssituationwewillcomeacrossisdifferentinitsownway.Runningthesameapplicationagainstadifferentdevice,evenbythesamemanufacturer,oftenresultsinanapples-versus-orangescomparisonduetothedifferentcapabilitiesandfunctionalitytheyprovide.Itcanbedifficulttodeterminewhereabottleneckresideswithinsuchacomplexchainofdevicesandsystems,anditcantakealifetimeofindustryworkin3Dgraphicstohaveastrongintuitionaboutthesourceofperformanceissuesinmoderngraphicssystems.

Thankfully,Profilingcomestotherescueonceagain.Ifwecangatherdataabouteachcomponent,usemultipleperformancemetricsforcomparison,andtweakourScenestoseehowdifferentgraphicsfeaturesaffecttheirbehavior,thenweshouldhavesufficientevidencetofindtherootcauseoftheissueandmakeappropriatechanges.Sointhischapter,youwilllearnhowtogathertherightdata,digjustdeepenoughintothegraphicssystemtofindthetruesourceoftheproblem,andexplorevarioussolutionstoworkaroundagivenproblem.

Asyoulearnedinearlierchapters,theCPUandGPUworkintandemtodeterminewhattextures,meshes,renderstates,Shaders,andsoon,areneededtorenderourScenesatanygivenmoment.We’vealsocoveredseveraltechniquestoreducesomeoftherenderingworkloadthroughStaticandDynamicBatching,andbymanipulatingourmeshandtexturefilesthroughcompressionandencoding,MipMapping,Atlasing,andevensomeproceduralalternatives.

However,therearestillmanymoretopicstocoverwhenitcomestoimprovingrenderingperformance,sointhischapterwewillbeginwithsomegeneraltechniquesonhowtodeterminewhetherourrenderingislimitedbytheCPUorbytheGPU,andwhatwecandoabouteithercase.WewilldiscussoptimizationtechniquessuchasOcclusionCullingandLevelOfDetail(LOD)andprovidesomeusefuladviceonShaderoptimization,aswellaslarge-scalerenderingfeaturessuchaslightingandshadows.Finally,sincemobiledevicesareacommontargetforUnityprojects,wewillalsocoversometechniquesthatmayhelpimproveperformanceonlimitedhardware.

http://freepdf-books.com

Page 247: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ProfilingrenderingissuesPoorrenderingperformancecanmanifestitselfinanumberofways,dependingonwhetherthedeviceisCPU-bound,orGPU-bound;inthelattercase,therootcausecouldoriginatefromanumberofplaceswithinthegraphicspipeline.Thiscanmaketheinvestigatorystageratherinvolved,butoncethesourceofthebottleneckisdiscoveredandtheproblemisresolved,wecanexpectsignificantimprovementsassmallfixestendtoreapbigrewardswhenitcomestotherenderingsubsystem.

WebrieflytoucheduponthesubjectofbeingCPU/GPU-boundinChapter3,TheBenefitsofBatching.Tosummarizetheearlierdiscussion,weknowthattheCPUsendsrenderinginstructionsthroughthegraphicsAPI,thatfunnelthroughthehardwaredrivertotheGPUdevice,whichresultsincommandsenteringtheGPU’sCommandBuffer.ThesecommandsareprocessedbythemassivelyparallelGPUsystemonebyoneuntilthebufferisempty.Buttherearealotmorenuancesinvolvedinthisprocess.

Thefollowingshowsa(greatlysimplified)diagramofatypicalGPUpipeline(whichcanvarybasedontechnologyandvariousoptimizations),andthebroadrenderingstepsthattakeplaceduringeachstage:

ThetoprowrepresentstheworkthattakesplaceontheCPU,theactofcallingintothegraphicsAPI,throughthehardwaredriver,andpushingcommandsintotheGPU.Ergo,aCPU-boundapplicationwillbeprimarilylimitedbythecomplexity,orsheernumber,ofgraphicsAPIcalls.

Meanwhile,aGPU-boundapplicationwillbelimitedbytheGPU’sabilitytoprocessthosecalls,andemptytheCommandBufferinareasonabletimeframetoallowfortheintendedframerate.Thisisrepresentedinthenexttworows,showingthestepstakingplaceintheGPU.But,becauseofthedevice’scomplexity,theyareoftensimplifiedintotwodifferentsections:thefrontendandthebackend.

http://freepdf-books.com

Page 248: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThefrontendreferstothepartoftherenderingprocesswheretheGPUhasreceivedmeshdata,adrawcallhasbeenissued,andalloftheinformationthatwasfedintotheGPUisusedtotransformverticesandrunthroughVertexShaders.Finally,therasterizergeneratesabatchoffragmentstobeprocessedinthebackend.ThebackendreferstotheremainderoftheGPU’sprocessingstages,wherefragmentshavebeengenerated,andnowtheymustbetested,manipulated,anddrawnviaFragmentShadersontotheframebufferintheformofpixels.

TipNotethat“FragmentShader”isthemoretechnicallyaccuratetermforPixelShaders.Fragmentsaregeneratedbytherasterizationstage,andonlytechnicallybecomepixelsoncethey’vebeenprocessedbytheShaderanddrawntotheFrameBuffer.

Thereareanumberofdifferentapproacheswecanusetodeterminewheretherootcauseofagraphicsrenderingissuelies:

ProfilingtheGPUwiththeProfilerExaminingindividualframeswiththeFrameDebuggerBruteForceCulling

http://freepdf-books.com

Page 249: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

GPUprofilingBecausegraphicsrenderinginvolvesboththeCPUandGPU,wemustexaminetheproblemusingboththeCPUUsageandGPUUsageareasoftheProfilerasthiscantelluswhichcomponentisworkinghardest.

Forexample,thefollowingscreenshotshowstheProfilerdataforaCPU-boundapplication.Thetestinvolvedcreatingthousandsofsimpleobjects,withnobatchingtechniquestakingplace.ThisresultedinanextremelylargeDrawCallcount(around15,000)fortheCPUtoprocess,butgivingtheGPUrelativelylittleworktododuetothesimplicityoftheobjectsbeingrendered:

ThisexampleshowsthattheCPU’s“rendering”taskisconsumingalargeamountofcycles(around30msperframe),whiletheGPUisonlyprocessingforlessthan16ms,indicatingthatthebottleneckresidesintheCPU.

Meanwhile,ProfilingaGPU-boundapplicationviatheProfilerisalittletrickier.Thistime,thetestinvolvescreatingasmallnumberofhighpolycountobjects(foralowDrawCallpervertexratio),withdozensofreal-timepointlightsandanexcessivelycomplexShaderwithatexture,normaltexture,heightmap,emissionmap,occlusionmap,andsoon,(forahighworkloadperpixelratio).

ThefollowingscreenshotshowsProfilerdatafortheexampleScenewhenitisruninastandaloneapplication:

http://freepdf-books.com

Page 250: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Aswecansee,therenderingtaskoftheCPUUsageareamatchescloselywiththetotalrenderingcostsoftheGPUUsagearea.WecanalsoseethattheCPUandGPUtimecostsatthebottomoftheimagearerelativelysimilar(41.48msversus38.95ms).ThisisveryunintuitiveaswewouldexpecttheGPUtobeworkingmuchharderthantheCPU.

TipBeawarethattheCPU/GPUmillisecondcostvaluesarenotcalculatedorrevealedunlesstheappropriateUsageAreahasbeenaddedtotheProfilerwindow.

However,let’sseewhathappenswhenwetestthesameexactScenethroughtheEditor:

ThisisabetterrepresentationofwhatwewouldexpecttoseeinaGPU-boundapplication.WecanseehowtheCPUandGPUtimecostsatthebottomareclosertowhatwewouldexpecttosee(2.74msvs64.82ms).

However,thisdataishighlypolluted.ThespikesintheCPUandGPUUsageareasarethe

http://freepdf-books.com

Page 251: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

resultoftheProfilerWindowUIupdatingduringtesting,andtheoverheadcostofrunningthroughtheEditorisalsoartificiallyincreasingthetotalGPUtimecost.

Itisunclearwhatcausesthedatatobetreatedthisway,andthiscouldcertainlychangeinthefutureifenhancementsaremadetotheProfilerinfutureversionsofUnity,butitisusefultoknowthisdrawback.

NoteTryingtodeterminewhetherourapplicationistrulyGPU-boundisperhapstheonlygoodexcusetoperformaProfilertestthroughtheEditor.

http://freepdf-books.com

Page 252: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheFrameDebuggerAnewfeatureinUnity5istheFrameDebugger,adebuggingtoolthatcanrevealhowtheSceneisrenderedandpiecedtogether,oneDrawCallatatime.WecanclickthroughthelistofDrawCallsandobservehowtheSceneisrendereduptothatpointintime.ItalsoprovidesalotofusefuldetailsfortheselectedDrawCall,suchasthecurrentrendertarget(forexample,theshadowmap,thecameradepthtexture,themaincamera,orothercustomrendertargets),whattheDrawCalldid(drawingamesh,drawingastaticbatch,drawingdepthshadows,andsoon),andwhatsettingswereused(texturedata,vertexcolors,bakedlightmaps,directionallighting,andsoon).

ThefollowingscreenshotshowsaScenethatisonlybeingpartiallyrenderedduetothecurrentlyselectedDrawCallwithintheFrameDebugger.Notetheshadowsthatarevisiblefrombakedlightmapsthatwererenderedduringanearlierpassbeforetheobjectitselfisrendered:

IfweareboundbyDrawCalls,thenthistoolcanbeeffectiveinhelpingusfigureoutwhattheDrawCallsarebeingspenton,anddeterminewhetherthereareanyunnecessaryDrawCallsthatarenothavinganeffectonthescene.Thiscanhelpuscomeupwithwaystoreducethem,suchasremovingunnecessaryobjectsorbatchingthemsomehow.WecanalsousethistooltoobservehowmanyadditionalDrawCallsareconsumedbyrenderingfeatures,suchasshadows,transparentobjects,andmanymore.Thiscouldhelpus,whenwe’recreatingmultiplequalitylevelsforourgame,todecidewhatfeaturestoenable/disableunderthelow,medium,andhighqualitysettings.

http://freepdf-books.com

Page 253: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

BruteforcetestingIfwe’reporingoverourProfilingdata,andwe’restillnotsurewecandeterminethesourceoftheproblem,wecanalwaystrythebruteforcemethod:cullaspecificactivityfromtheSceneandseeifitresultsingreatlyincreasedperformance.Ifasmallchangeresultsinabigspeedimprovement,thenwehaveastrongclueaboutwherethebottlenecklies.There’snoharminthisapproachifweeliminateenoughunknownvariablestobesurethedataisleadingusintherightdirection.

Wewillcoverdifferentwaystobruteforcetestaparticularissueineachoftheupcomingsections.

http://freepdf-books.com

Page 254: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CPU-boundIfourapplicationisCPU-bound,thenwewillobserveagenerallypoorFPSvaluewithintheCPUUsageareaoftheProfilerwindowduetotherenderingtask.However,ifVSyncisenabledthedatawilloftengetmuddiedupwithlargespikesrepresentingpausesastheCPUwaitsforthescreenrefreshratetocomearoundbeforepushingthecurrentframebuffer.So,weshouldmakesuretodisabletheVSyncblockintheCPUUsageareabeforedecidingtheCPUistheproblem.

Brute-forcingatestforCPU-boundingcanbeachievedbyreducingDrawCalls.Thisisalittleunintuitivesince,presumably,we’vealreadybeenreducingourDrawCallstoaminimumthroughtechniquessuchasStaticandDynamicBatching,Atlasing,andsoforth.Thiswouldmeanwehaveverylimitedscopeforreducingthemfurther.

Whatwecando,however,isdisabletheDraw-Call-savingfeaturessuchasbatchingandobserveifthesituationgetssignificantlyworsethanitalreadyis.Ifso,thenwehaveevidencethatwe’reeitheralready,orveryclosetobeing,CPU-bound.Atthispoint,weshouldseewhetherwecanre-enablethesefeaturesanddisablerenderingforafewchoiceobjects(preferablythosewithlowcomplexitytoreduceDrawCallswithoutover-simplifyingtherenderingofourscene).Ifthisresultsinasignificantperformanceimprovementthen,unlesswecanfindfurtheropportunitiesforbatchingandmeshcombining,wemaybefacedwiththeunfortunateoptionofremovingobjectsfromoursceneastheonlymeansofbecomingperformantagain.

TherearesomeadditionalopportunitiesforDrawCallreduction,includingOcclusionCulling,tweakingourLightingandShadowing,andmodifyingourShaders.Thesewillbeexplainedinthefollowingsections.

However,Unity’srenderingsystemcanbemultithreaded,dependingonthetargetedplatform,whichversionofUnitywe’rerunning,andvarioussettings,andthiscanaffecthowthegraphicssubsystemisbeingbottleneckedbytheCPU,andslightlychangesthedefinitionofwhatbeingCPU-boundmeans.

MultithreadedrenderingMultithreadedrenderingwasfirstintroducedinUnityv3.5inFebruary2012,andenabledbydefaultonmulticoresystemsthatcouldhandletheworkload;atthetime,thiswasonlyPC,Mac,andXbox360.Gradually,moredeviceswereaddedtothislist,andsinceUnityv5.0,allmajorplatformsnowenablemultithreadedrenderingbydefault(andpossiblysomebuildsofUnity4).

http://freepdf-books.com

Page 255: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MobiledeviceswerealsostartingtofeaturemorepowerfulCPUsthatcouldsupportthisfeature.Androidmultithreadedrendering(introducedinUnityv4.3)canbeenabledthroughacheckboxunderPlatformSettings|OtherSettings|MultithreadedRendering.MultithreadedrenderingoniOScanbeenabledbyconfiguringtheapplicationtomakeuseoftheAppleMetalAPI(introducedinUnityv4.6.3),underPlayerSettings|OtherSettings|GraphicsAPI.

Whenmultithreadedrenderingisenabled,tasksthatmustgothroughtherenderingAPI(OpenGL,DirectX,orMetal),arehandedoverfromthemainthreadtoa“workerthread”.Theworkerthread’spurposeistoundertaketheheavyworkloadthatittakestopushrenderingcommandsthroughthegraphicsAPIanddriver,togettherenderinginstructionsintotheGPU’sCommandBuffer.ThiscansaveanenormousnumberofCPUcyclesforthemainthread,wheretheoverwhelmingmajorityofotherCPUtaskstakeplace.Thismeansthatwefreeupextracyclesforthemajorityoftheenginetoprocessphysics,scriptcode,andsoon.

Incidentally,themechanismbywhichthemainthreadnotifiestheworkerthreadoftasksoperatesinaverysimilarwaytotheCommandBufferthatexistsontheGPU,exceptthatthecommandsaremuchmorehigh-level,withinstructionslike“renderthisobject,withthisMaterial,usingthisShader”,or“drawNinstancesofthispieceofproceduralgeometry”,andsoon.ThisfeaturehasbeenexposedinUnity5toallowdeveloperstotakedirectcontroloftherenderingsubsystemfromC#code.ThiscustomizationisnotaspowerfulashavingdirectAPIaccess,butitisastepintherightdirectionforUnitydeveloperstoimplementuniquegraphicaleffects.

NoteConfusingly,theUnityAPInameforthisfeatureiscalled“CommandBuffer”,sobesurenottoconfuseitwiththeGPU’sCommandBuffer.

ChecktheUnitydocumentationonCommandBuffertomakeuseofthisfeature:http://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.html.

Gettingbacktothetaskathand,whenwediscussthetopicofbeingCPU-boundingraphicsrendering,weneedtokeepinmindwhetherornotthemultithreadedrendererisbeingused,sincetheactualrootcauseoftheproblemwillbeslightlydifferentdependingonwhetherthisfeatureisenabledornot.

Insingle-threadedrendering,whereallgraphicsAPIcallsarehandledbythemainthread,andinanidealworldwherebothcomponentsarerunningatmaximumcapacity,ourapplicationwouldbecomebottleneckedontheCPUwhen50percentormoreofthetimeperframeisspenthandlinggraphicsAPIcalls.However,resolvingthesebottleneckscanbeaccomplishedbyfreeingupworkfromthemainthread.Forexample,wemightfindthatgreatlyreducingtheamountofworktakingplaceinourAIsubsystemwillimproveourrenderingsignificantlybecausewe’vefreedupmoreCPUcyclestohandlethegraphicsAPIcalls.

But,whenmultithreadedrenderingistakingplace,thistaskispushedontotheworkerthread,whichmeansthesamethreadisn’tbeingaskedtomanagebothengineworkand

http://freepdf-books.com

Page 256: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

graphicsAPIcallsatthesametime.Theseprocessesaremostlyindependent,andeventhoughadditionalworkmuststilltakeplaceinthemainthreadtosendinstructionstotheworkerthreadinthefirstplace(viatheinternalCommandBuffersystem),itismostlynegligible.Thismeansthatreducingtheworkloadinthemainthreadwillhavelittle-to-noeffectonrenderingperformance.

NoteNotethatbeingGPU-boundisthesameregardlessofwhethermultithreadedrenderingistakingplace.

GPUSkinningWhilewe’reonthesubjectofCPU-bounding,onetaskthatcanhelpreduceCPUworkload,attheexpenseofadditionalGPUworkload,isGPUSkinning.Skinningistheprocesswheremeshverticesaretransformedbasedonthecurrentlocationoftheiranimatedbones.Theanimationsystem,workingontheCPU,onlytransformsthebones,butanotherstepintherenderingprocessmusttakecareofthevertextransformationstoplacetheverticesaroundthosebones,performingaweightedaverageoverthebonesconnectedtothosevertices.

ThisvertexprocessingtaskcaneithertakeplaceontheCPUorwithinthefrontendoftheGPU,dependingonwhethertheGPUSkinningoptionisenabled.ThisfeaturecanbetoggledunderEdit|ProjectSettings|PlayerSettings|OtherSettings|GPUSkinning.

http://freepdf-books.com

Page 257: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 258: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

FrontendbottlenecksWehavealreadycoveredsometechniquesonmeshoptimizationinChapter4,KickstartYourArt,whichcanhelpreduceourmesh’svertexattributes.Asaquickreminder,itisnotuncommontouseameshthatcontainsalotofunnecessaryUVandNormalvectordata,soourmeshesshouldbedouble-checkedforthiskindofsuperfluousfluff.WeshouldalsoletUnityoptimizethestructureforus,whichminimizescachemissesasvertexdataisreadwithinthefrontend.

WewillalsolearnsomeusefulShaderoptimizationtechniquesshortly,whenwebegintodiscussbackendoptimizations,sincemanyoptimizationtechniquesapplytobothFragmentandVertexShaders.

Theonlyattackvectorlefttocoverisfindingwaystoreduceactualvertexcounts.Theobvioussolutionsaresimplificationandculling;eitherhavetheartteamreplaceproblematicmesheswithlowerpolycountversions,and/orremovesomeobjectsfromthescenetoreducetheoverallpolygoncount.Iftheseapproacheshavealreadybeenexplored,thenthelastapproachwecantakeistofindsomekindofmiddlegroundbetweenthetwo.

http://freepdf-books.com

Page 259: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LevelOfDetailSinceitcanbedifficulttotellthedifferencebetweenahighqualitydistanceobjectandalowqualityone,thereisverylittlereasontorenderthehighqualityversion.So,whynotdynamicallyreplacedistantobjectswithsomethingmoresimplified?

LevelOfDetail(LOD),isabroadtermreferringtothedynamicreplacementoffeaturesbasedontheirdistanceorformfactorrelativetothecamera.Themostcommonimplementationismesh-basedLOD:dynamicallyreplacingameshwithlowerandlowerdetailedversionsasthecameragetsfartherandfartheraway.Anotherexamplemightbereplacinganimatedcharacterswithversionsfeaturingfewerbones,orlesssamplingfordistantobjects,inordertoreduceanimationworkload.

TipThebuilt-inLODfeatureisavailableintheUnity4ProEditionandalleditionsofUnity5.However,itisentirelypossibletoimplementitviaScriptcodeinUnity4FreeEditionifdesired.

MakinguseofLODcanbeachievedbyplacingmultipleobjectsintheSceneandmakingthemchildrenofaGameObjectwithanattachedLODGroupcomponent.TheLODGroup’spurposeistogenerateaboundingboxfromtheseobjects,anddecidewhichobjectshouldberenderedbasedonthesizeoftheboundingboxwithinthecamera’sfieldofview.Iftheobject’sboundingboxconsumesalargeareaofthecurrentview,thenitwillenablethemesh(es)assignedtolowerLODgroups,andiftheboundingboxisverysmall,itwillreplacethemesh(es)withthosefromhigherLODgroups.Ifthemeshistoofaraway,itcanbeconfiguredtohideallchildobjects.So,withthepropersetup,wecanhaveUnityreplacemesheswithsimpleralternatives,orcullthementirely,whicheasestheburdenontherenderingprocess.

NoteChecktheUnitydocumentationformoredetailedinformationontheLODfeature:http://docs.unity3d.com/Manual/LevelOfDetail.html.

Thisfeaturecancostusalargeamountofdevelopmenttimetofullyimplement;artistsmustgeneratelowerpolygoncountversionsofthesameobject,andleveldesignersmustgenerateLODgroups,configurethem,andtestthemtoensuretheydon’tcausejarringtransitionsasthecameramovescloserorfartheraway.ItalsocostsusinmemoryandruntimeCPU;thealternativemeshesneedtobekeptinmemory,andtheLODGroupcomponentmustroutinelytestwhetherthecamerahasmovedtoanewpositionthatwarrantsachangeinLODlevel.

Inthiseraofgraphicscardcapabilities,vertexprocessingisoftentheleastofourconcerns.CombinedwiththeadditionalsacrificesneededforLODtofunction,developersshouldavoidpreoptimizingbyautomaticallyassumingLODwillhelpthem.Excessiveuseofthefeaturewillleadtoburdeningotherpartsofourapplication’sperformance,andchewuppreciousdevelopmenttime,allforthesakeofparanoia.Ifithasn’tbeenproventobeaproblem,thenit’sprobablynotaproblem!

http://freepdf-books.com

Page 260: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Scenesthatfeaturelarge,expansiveviewsoftheworld,andlotsofcameramovement,shouldconsiderimplementingthistechniqueveryearly,astheaddeddistanceandmassivenumberofvisibleobjectswillexacerbatethevertexcountenormously.Scenesthatarealwaysindoors,orfeatureacamerawithaviewpointlookingdownattheworld(real-timestrategyandMOBAgames,forexample)shouldprobablysteerclearofimplementingLODfromthebeginning.Gamessomewherebetweenthetwoshouldavoidituntilnecessary.Italldependsonhowmanyverticesareexpectedtobevisibleatanygiventimeandhowmuchvariabilityincameradistancetherewillbe.

TipNotethatsomegamedevelopmentmiddlewarecompaniesofferthird-partytoolsforautomatedLODmeshgeneration.Thesemightbeworthinvestigatingtocomparetheireaseofuseversusqualitylossversuscosteffectiveness.

http://freepdf-books.com

Page 261: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DisableGPUSkinningAspreviouslymentioned,wecouldenableGPUSkinningtoreducetheburdenonaCPU-boundapplication,butenablingthisfeaturewillpushthesameworkloadintothefrontendoftheGPU.SinceSkinningisoneofthose“embarrassinglyparallel”processesthatfitswellwiththeGPU’sparallelarchitecture,itisoftenagoodideatoperformthetaskontheGPU.Butthistaskcanchewupprecioustimeinthefrontendpreparingtheverticesforfragmentgeneration,sodisablingitisanotheroptionwecanexploreifwe’rebottleneckedinthisarea.Again,thisfeaturecanbetoggledunderEdit|ProjectSettings|PlayerSettings|OtherSettings|GPUSkinning.

TipGPUSkinningisavailableinUnity4ProEdition,andalleditionsofUnity5.

http://freepdf-books.com

Page 262: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ReducetessellationThereisonelasttaskthattakesplaceinthefrontendprocessandthatweneedtoconsider:tessellation.TessellationthroughGeometryShaderscanbealotoffun,asitisarelativelyunderusedtechniquethatcanreallymakeourgraphicaleffectsstandoutfromthecrowdofgamesthatonlyusethemostcommoneffects.But,itcancontributeenormouslytotheamountofprocessingworktakingplaceinthefrontend.

Therearenosimpletrickswecanexploittoimprovetessellation,besidesimprovingourtessellationalgorithms,oreasingtheburdencausedbyotherfrontendtaskstogiveourtessellationtasksmoreroomtobreathe.Eitherway,ifwehaveabottleneckinthefrontendandaremakinguseoftessellationtechniques,weshoulddouble-checkthattheyarenotconsumingthelion’sshareofthefrontend’sbudget.

http://freepdf-books.com

Page 263: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 264: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

BackendbottlenecksThebackendisthemoreinterestingpartoftheGPUpipeline,asmanymoregraphicaleffectstakeplaceduringthisstage.Consequently,itisthestagethatissignificantlymorelikelytosufferfrombottlenecks.

Therearetwobruteforcetestswecanattempt:

ReduceresolutionReducetexturequality

Thesechangeswilleasetheworkloadduringtwoimportantstagesatthebackendofthepipeline:fillrateandmemorybandwidth,respectively.Fillratetendstobethemostcommonsourceofbottlenecksinthemoderneraofgraphicsrendering,sowewillcoveritfirst.

http://freepdf-books.com

Page 265: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

FillrateByreducingscreenresolution,wehaveaskedtherasterizationsystemtogeneratesignificantlyfewerfragmentsandtransposethemoverasmallercanvasofpixels.Thiswillreducethefillrateconsumptionoftheapplication,givingakeypartoftherenderingpipelinesomeadditionalbreathingroom.Ergo,ifperformancesuddenlyimproveswithascreenresolutionreduction,thenfillrateshouldbeourprimaryconcern.

FillrateisaverybroadtermreferringtothespeedatwhichtheGPUcandrawfragments.But,thisonlyincludesfragmentsthathavesurvivedallofthevariousconditionaltestswemighthaveenabledwithinthegivenShader.Afragmentismerelya“potentialpixel,”andifitfailsanyoftheenabledtests,thenitisimmediatelydiscarded.Thiscanbeanenormousperformance-saverasthepipelinecanskipthecostlydrawingstepandbeginworkonthenextfragmentinstead.

OnesuchexampleisZ-testing,whichcheckswhetherthefragmentfromacloserobjecthasalreadybeendrawntothesamepixelalready.Ifso,thenthecurrentfragmentisdiscarded.Ifnot,thenthefragmentispushedthroughtheFragmentShaderanddrawnoverthetargetpixel,whichconsumesexactlyonedrawfromourfillrate.Nowimaginemultiplyingthisprocessbythousandsofoverlappingobjects,eachgeneratinghundredsorthousandsofpossiblefragments,forhighscreenresolutionscausingmillions,orbillions,offragmentstobegeneratedeachandeveryframe.Itshouldbefairlyobviousthatskippingasmanyofthesedrawsaswecanwillresultinbigrenderingcostsavings.

Graphicscardmanufacturerstypicallyadvertiseaparticularfillrateasafeatureofthecard,usuallyintheformofgigapixelspersecond,butthisisabitofamisnomer,asitwouldbemoreaccuratetocallitgigafragmentspersecond;howeverthisargumentismostlyacademic.Eitherway,largervaluestellusthatthedevicecanpotentiallypushmorefragmentsthroughthepipeline,sowithabudgetof30GPix/sandatargetframerateof60Hz,wecanaffordtoprocess30,000,000,000/60=500millionfragmentsperframebeforebeingbottleneckedonfillrate.Witharesolutionof2560x1440,andabest-casescenariowhereeachpixelisonlydrawnoveronce,thenwecouldtheoreticallydrawtheentiresceneabout125timeswithoutanynoticeableproblems.

Sadly,thisisnotaperfectworld,andunlesswetakesignificantstepstoavoidit,wewillalwaysendupwithsomeamountofredrawoverthesamepixelsduetotheorderinwhichobjectsarerendered.Thisisknownasoverdraw,anditcanbeverycostlyifwe’renotcareful.

TipThereasonthatresolutionisagoodattackvectortocheckforfillrateboundingisthatitisamultiplier.Areductionfromaresolutionof2560x1440to800x600isanimprovementfactorofabouteight,whichcouldreducefillratecostsenoughtomaketheapplicationperformwellagain.

OverdrawDetermininghowmuchoverdrawwehavecanberepresentedvisuallybyrenderingall

http://freepdf-books.com

Page 266: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

objectswithadditivealphablendingandaverytransparentflatcolor.Areasofhighoverdrawwillshowupmorebrightlyasthesamepixelisdrawnoverwithadditiveblendingmultipletimes.ThisispreciselyhowtheSceneview’sOverdrawshadingmoderevealshowmuchoverdrawoursceneissuffering.

Thefollowingscreenshotshowsascenewithseveralthousandboxesdrawnnormally,anddrawnusingtheSceneview’sOverdrawshadingmode:

Attheendoftheday,fillrateisprovidedasameansofgaugingthebest-casebehavior.Inotherwords,it’sprimarilyamarketingtermandmostlytheoretical.But,thetechnicalsideoftheindustryhasadoptedthetermasawayofdescribingthebackendofthepipeline:thestagewherefragmentdataisfunneledthroughourShadersanddrawntothescreen.

Ifeveryfragmentrequiredanabsoluteminimumlevelofprocessing(suchasaShaderthatreturnedaconstantcolor),thenwemightgetclosetothattheoreticalmaximum.TheGPUisacomplexbeast,however,andthingsareneversosimple.Thenatureofthedevicemeansitworksbestwhengivenmanysmalltaskstoperform.But,ifthetasksgettoolarge,thenfillrateislostduetothebackendnotbeingabletopushthroughenoughfragmentsintimeandtherestofthepipelineisleftwaitingfortaskstodo.

Thereareseveralmorefeaturesthatcanpotentiallyconsumeourtheoreticalfillratemaximum,includingbutnotlimitedtoalphatesting,alphablending,texturesampling,theamountoffragmentdatabeingpulledthroughourShaders,andeventhecolorformatofthetargetrendertexture(thefinalFrameBufferinmostcases).Thebadnewsisthatthisgivesusalotofsubsectionstocover,andalotofwaystobreaktheprocess,butthegoodnewsisitgivesusalotofavenuestoexploretoimproveourfillrateusage.

OcclusionCullingOneofthebestwaystoreduceoverdrawistomakeuseofUnity’sOcclusionCullingsystem.ThesystemworksbypartitioningScenespaceintoaseriesofcellsandflyingthroughtheworldwithavirtualcameramakingnoteofwhichcellsareinvisiblefrom

http://freepdf-books.com

Page 267: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

othercells(areoccluded)basedonthesizeandpositionoftheobjectspresent.

NotethatthisisdifferenttothetechniqueofFrustumCulling,whichcullsobjectsnotvisiblefromthecurrentcameraview.Thisfeatureisalwaysactiveinallversions,andobjectsculledbythisprocessareautomaticallyignoredbytheOcclusionCullingsystem.

TipOcclusionCullingisavailableintheUnity4ProEditionandalleditionsofUnity5.

OcclusionCullingdatacanonlybegeneratedforobjectsproperlylabeledOccluderStaticandOccludeeStaticundertheStaticFlagsdropdown.OccluderStaticisthegeneralsettingforstaticobjectswherewewantittohideotherobjects,andbehiddenbylargeobjectsinitsway.OccludeeStaticisaspecialcasefortransparentobjectsthatallowsobjectsbehindthemtoberendered,butwewantthemtobehiddenifsomethinglargeblockstheirvisibility.

Naturally,becauseoneofthestaticflagsmustbeenabledforOcclusionCulling,thisfeaturewillnotworkfordynamicobjects.

ThefollowingscreenshotshowshoweffectiveOcclusionCullingcanbeatreducingthenumberofvisibleobjectsinourScene:

http://freepdf-books.com

Page 268: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Thisfeaturewillcostusinbothapplicationfootprintandincursomeruntimecosts.ItwillcostRAMtokeeptheOcclusionCullingdatastructureinmemory,andtherewillbeaCPUprocessingcosttodeterminewhichobjectsarebeingoccludedineachframe.

TheOcclusionCullingdatastructuremustbeproperlyconfiguredtocreatecellsoftheappropriatesizeforourScene,andthesmallerthecells,thelongerittakestogeneratethedatastructure.But,ifitisconfiguredcorrectlyfortheScene,OcclusionCullingcanprovidebothfillratesavingsthroughreducedoverdraw,andDrawCallsavingsbycullingnon-visibleobjects.

ShaderoptimizationShaderscanbeasignificantfillrateconsumer,dependingontheircomplexity,howmuchtexturesamplingtakesplace,howmanymathematicalfunctionsareused,andsoon.Shadersdonotdirectlyconsumefillrate,butdosoindirectlybecausetheGPUmustcalculateorfetchdatafrommemoryduringShaderprocessing.TheGPU’sparallelnaturemeansanybottleneckinathreadwilllimithowmanyfragmentscanbepushedintothethreadatalaterdate,butparallelizingthetask(sharingsmallpiecesofthejobbetween

http://freepdf-books.com

Page 269: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

severalagents)providesanetgainoverserialprocessing(oneagenthandlingeachtaskoneafteranother).

Theclassicexampleisavehicleassemblyline.Acompletevehiclerequiresmultiplestagesofmanufacturetocomplete.Thecriticalpathtocompletionmightinvolvefivesteps:stamping,welding,painting,assembly,andinspection,andeachstepiscompletedbyasingleteam.Foranygivenvehicle,nostagecanbeginbeforethepreviousoneisfinished,butwhateverteamhandledthestampingforthelastvehiclecanbeginstampingforthenextvehicleassoonasithasfinished.Thisorganizationallowseachteamtobecomemastersoftheirparticulardomain,ratherthantryingtospreadtheirknowledgetoothin,whichwouldlikelyresultinlessconsistentqualityinthebatchofvehicles.

Wecandoubletheoveralloutputbydoublingthenumberofteams,butifanyteamgetsblocked,thenprecioustimeislostforanygivenvehicle,aswellasallfuturevehiclesthatwouldpassthroughthesameteam.Ifthesedelaysarerare,thentheycanbenegligibleinthegrandscheme,butifnot,andonestagetakesseveralminuteslongerthannormaleachandeverytimeitmustcompletethetask,thenitcanbecomeabottleneckthatthreatensthereleaseoftheentirebatch.

TheGPUparallelprocessorsworkinasimilarway:eachprocessorthreadisanassemblyline,eachprocessingstageisateam,andeachfragmentisavehicle.Ifthethreadspendsalongtimeprocessingasinglestage,thentimeislostoneachfragment.Thisdelaywillmultiplysuchthatallfuturefragmentscomingthroughthesamethreadwillbedelayed.Thisisabitofanoversimplification,butitoftenhelpstopaintapictureofhowpoorlyoptimizedShadercodecanchewupourfillrate,andhowsmallimprovementsinShaderoptimizationprovidebigbenefitsinbackendperformance.

Shaderprogrammingandoptimizationhavebecomeaverynicheareaofgamedevelopment.Theirabstractandhighly-specializednaturerequiresaverydifferentkindofthinkingtogenerateShadercodecomparedtogameplayandenginecode.Theyoftenfeaturemathematicaltricksandback-doormechanismsforpullingdataintotheShader,suchasprecomputingvaluesintexturefiles.Becauseofthis,andtheimportanceofoptimization,Shaderstendtobeverydifficulttoreadandreverse-engineer.

Consequently,manydevelopersrelyonprewrittenShaders,orvisualShadercreationtoolsfromtheAssetStoresuchasShaderForgeorShaderSandwich.ThissimplifiestheactofinitialShadercodegeneration,butmightnotresultinthemostefficientformofShaders.Ifwe’rerelyingonpre-writtenShadersortools,wemightfinditworthwhiletoperformsomeoptimizationpassesoverthemusingsometried-and-truetechniques.So,let’sfocusonsomeeasilyreachablewaysofoptimizingourShaders.

ConsiderusingShadersintendedformobileplatformsThebuilt-inmobileShadersinUnitydonothaveanyspecificrestrictionsthatforcethemtoonlybeusedonmobiledevices.Theyaresimplyoptimizedforminimumresourceusage(andtendtofeaturesomeoftheotheroptimizationslistedinthissection).

DesktopapplicationsareperfectlycapableofusingtheseShaders,buttheytendtofeaturealossofgraphicalquality.Itonlybecomesaquestionofwhetherthelossofgraphical

http://freepdf-books.com

Page 270: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

qualityisacceptable.So,considerdoingsometestingwiththemobileequivalentsofcommonShaderstoseewhethertheyareagoodfitforyourgame.

Usesmalldatatypes

GPUscancalculatewithsmallerdatatypesmorequicklythanlargertypes(particularlyonmobileplatforms!),sothefirsttweakwecanattemptisreplacingourfloatdatatypes(32-bit,floatingpoint)withsmallerversionssuchashalf(16-bit,floatingpoint),orevenfixed(12-bit,fixedpoint).

NoteThesizeofthedatatypeslistedabovewillvarydependingonwhatfloatingpointformatsthetargetplatformprefers.Thesizeslistedarethemostcommon.Theimportanceforoptimizationisintherelativesizebetweenformats.

Colorvaluesaregoodcandidatesforprecisionreduction,aswecanoftengetawaywithlessprecisecolorvalueswithoutanynoticeablelossincoloration.However,theeffectsofreducingprecisioncanbeveryunpredictableforgraphicalcalculations.So,changessuchasthesecanrequiresometestingtoverifywhetherthereducedprecisioniscostingtoomuchgraphicalfidelity.

NotethattheeffectsofthesetweakscanvaryenormouslybetweenoneGPUarchitectureandanother(forexample,AMDversusNvidiaversusIntel),andevenGPUbrandsfromthesamemanufacturer.Insomecases,wecanmakesomedecentperformancegainsforatrivialamountofeffort.Inothercases,wemightseenobenefitatall.

Avoidchangingprecisionwhileswizzling

SwizzlingistheShaderprogrammingtechniqueofcreatinganewvector(anarrayofvalues)fromanexistingvectorbylistingthecomponentsintheorderinwhichwewishtocopythemintothenewstructure.Herearesomeexamplesofswizzling:

float4input=float4(1.0,2.0,3.0,4.0);//initialtestvalue

float2val1=input.yz;//swizzletwocomponents

float3val2=input.zyx;//swizzlethreecomponentsinadifferentorder

float4val3=input.yyy;//swizzlethesamecomponentmultipletimes

floatsclr=input.w;

float3val4=sclr.xxx//swizzleascalarmultipletimes

Wecanuseboththexyzwandrgbarepresentationstorefertothesamecomponents,sequentially.Itdoesnotmatterwhetheritisacolororvector;theyjustmaketheShadercodeeasiertoread.Wecanalsolistcomponentsinanyorderweliketofillinthedesireddata,repeatingthemifnecessary.

ConvertingfromoneprecisiontypetoanotherinaShadercanbeacostlyoperation,butconvertingtheprecisiontypewhilesimultaneouslyswizzlingcanbeparticularlypainful.Ifwehavemathematicaloperationsthatrelyonbeingswizzledintodifferentprecision

http://freepdf-books.com

Page 271: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

types,itwouldbewiserifwesimplyabsorbedthehigh-precisioncostfromtheverybeginning,orreducedprecisionacrosstheboardtoavoidtheneedforchangesinprecision.

UseGPU-optimizedhelperfunctions

TheShadercompileroftenperformsagoodjobofreducingmathematicalcalculationsdowntoanoptimizedversionfortheGPU,butcompiledcustomcodeisunlikelytobeaseffectiveasboththeCglibrary’sbuilt-inhelperfunctionsandtheadditionalhelpersprovidedbytheUnityCgincludedfiles.IfweareusingShadersthatincludecustomfunctioncode,perhapswecanfindanequivalenthelperfunctionwithintheCgorUnitylibrariesthatcandoabetterjobthanourcustomcodecan.

TheseextraincludefilescanbeaddedtoourShaderwithintheCGPROGRAMblocklikeso:

CGPROGRAM

//otherincludes

#include"UnityCG.cginc"

//Shadercodehere

ENDCG

ExampleCglibraryfunctionstouseareabs()forabsolutevalues,lerp()forlinearinterpolation,mul()formultiplyingmatrices,andstep()forstepfunctionality.UsefulUnityCG.cgincfunctionsincludeWorldSpaceViewDir()forcalculatingthedirectiontowardsthecamera,andLuminance()forconvertingacolortograyscale.

NoteCheckthefollowingURLforafulllistofCgstandardlibraryfunctions:http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html.

ChecktheUnitydocumentationforacompleteandup-to-datelistofpossibleincludefilesandtheiraccompanyinghelperfunctions:http://docs.unity3d.com/Manual/SL-BuiltinIncludes.html.

Disableunnecessaryfeatures

PerhapswecanmakesavingsbysimplydisablingShaderfeaturesthataren’tvital.DoestheShaderreallyneedmultiplepasses,transparency,Z-writing,alpha-testing,and/oralphablending?Willtweakingthesesettingsorremovingthesefeaturesgiveusagoodapproximationofourdesiredeffectwithoutlosingtoomuchgraphicalfidelity?Makingsuchchangesisagoodwayofmakingfillratecostsavings.

Removeunnecessaryinputdata

SometimestheprocessofwritingaShaderinvolvesalotofbackandforthexperimentationineditingcodeandviewingitintheScene.ThetypicalresultofthisisthatinputdatathatwasneededwhentheShaderwasgoingthroughearlydevelopmentisnowsurplusfluffoncethedesiredeffecthasbeenobtained,andit’seasytoforgetwhatchangesweremadewhen/iftheprocessdragsonforalongtime.But,theseredundantdatavaluescancosttheGPUvaluabletimeastheymustbefetchedfrommemoryeveniftheyarenotexplicitlyusedbytheShader.So,weshoulddoublecheckourShaderstoensure

http://freepdf-books.com

Page 272: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

alloftheirinputgeometry,vertex,andfragmentdataisactuallybeingused.

Onlyexposenecessaryvariables

ExposingunnecessaryvariablesfromourShadertotheaccompanyingMaterial(s)canbecostlyastheGPUcan’tassumethesevaluesareconstant.ThismeanstheShadercodecannotbecompiledintoamoreoptimizedform.ThisdatamustbepushedfromtheCPUwitheverypasssincetheycanbemodifiedatanytimethroughtheMaterial’smethodssuchasSetColor(),SetFloat(),andsoon.Ifwefindthat,towardstheendoftheproject,wealwaysusethesamevalueforthesevariables,thentheycanbereplacedwithaconstantintheShadertoremovesuchexcessruntimeworkload.Theonlycostisobfuscatingwhatcouldbecriticalgraphicaleffectparameters,sothisshouldbedoneverylateintheprocess.

Reducemathematicalcomplexity

Complicatedmathematicscanseverelybottlenecktherenderingprocess,soweshoulddowhateverwecantolimitthedamage.ComplexmathematicalfunctionscouldbereplacedwithatexturethatisfedintotheShaderandprovidesapre-generatedtableforruntimelookup.Wemaynotseeanyimprovementwithfunctionssuchassinandcos,sincethey’vebeenheavilyoptimizedtomakeuseofGPUarchitecture,butcomplexmethodssuchaspow,exp,log,andothercustommathematicalprocessescanonlybeoptimizedsomuch,andwouldbegoodcandidatesforsimplification.Thisisassumingweonlyneedoneortwoinputvalues,whicharerepresentedthroughtheXandYcoordinatesofthetexture,andmathematicalaccuracyisn’tofparamountimportance.

Thiswillcostusadditionalgraphicsmemorytostorethetextureatruntime(moreonthislater),butiftheShaderisalreadyreceivingatexture(whichtheyareinmostcases)andthealphachannelisnotbeingused,thenwecouldsneakthedatainthroughthetexture’salphachannel,costingusliterallynoperformance,andtherestoftheShadercodeandgraphicssystemwouldbenone-the-wiser.Thiswillinvolvethecustomizationofartassetstoincludesuchdatainanyunusedcolorchannel(s),requiringcoordinationbetweenprogrammersandartists,butisaverygoodwayofsavingShaderprocessingcostswithnoruntimesacrifices.

Infact,MaterialpropertiesandtexturesarebothexcellententrypointsforpushingworkfromtheShader(theGPU)ontotheCPU.Ifacomplexcalculationdoesnotneedtovaryonaperpixelbasis,thenwecouldexposethevalueasapropertyintheMaterial,andmodifyitasneeded(acceptingtheoverheadcostofdoingsofromtheprevioussectionOnlyexposenecessaryvariables).Alternatively,iftheresultvariesperpixel,anddoesnotneedtochangeoften,thenwecouldgenerateatexturefilefromscriptcode,containingtheresultsofthecalculationsintheRGBAvalues,andpullingthetextureintotheShader.Lotsofopportunitiesarisewhenweignoretheconventionalapplicationofsuchsystems,andremembertothinkofthemasjustrawdatabeingtransferredaround.

Reducetexturelookups

Whilewe’reonthesubjectoftexturelookups,theyarenottrivialtasksfortheGPUtoprocessandtheyhavetheirownoverheadcosts.Theyarethemostcommoncauseof

http://freepdf-books.com

Page 273: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

memoryaccessproblemswithintheGPU,especiallyifaShaderisperformingsamplesacrossmultipletextures,orevenmultiplesamplesacrossasingletexture,astheywilllikelyinflictcachemissesinmemory.SuchsituationsshouldbesimplifiedasmuchaspossibletoavoidsevereGPUmemorybottlenecking.

Evenworse,samplingatextureinarandomorderwouldlikelyresultinsomeverycostlycachemissesfortheGPUtosufferthrough,soifthisisbeingdone,thenthetextureshouldbereorderedsothatitcanbesampledinamoresequentialorder.

Avoidconditionalstatements

InmoderndayCPUarchitecture,conditionalstatementsundergoalotofcleverpredictivetechniquestomakeuseofinstruction-levelparallelism.ThisisafeaturewheretheCPUattemptstopredictwhichdirectionaconditionalstatementwillgoinbeforeithasactuallybeenresolved,andspeculativelybeginsprocessingthemostlikelyresultoftheconditionalusinganyfreecomponentsthataren’tbeingusedtoresolvetheconditional(fetchingsomedatafrommemory,copyingsomefloatsintounusedregisters,andsoon).Ifitturnsoutthatthedecisioniswrong,thenthecurrentresultisdiscardedandtheproperpathistakeninstead.

Solongasthecostofspeculativeprocessinganddiscardingfalseresultsislessthanthetimespentwaitingtodecidethecorrectpath,anditisrightmoreoftenthanitiswrong,thenthisisanetgainfortheCPU’sspeed.

However,thisfeatureisnotpossibleonGPUarchitecturebecauseofitsparallelnature.TheGPU’scoresaretypicallymanagedbysomehigher-levelconstructthatinstructsallcoresunderitscommandtoperformthesamemachine-code-levelinstructionsimultaneously.So,iftheFragmentShaderrequiresafloattobemultipliedby2,thentheprocesswillbeginbyhavingallcorescopydataintotheappropriateregistersinonecoordinatedstep.Onlywhenallcoreshavefinishedcopyingtotheregisterswillthecoresbeinstructedtobeginthesecondstep:multiplyingallregistersby2.

Thus,whenthissystemstumblesintoaconditionalstatement,itcannotresolvethetwostatementsindependently.Itmustdeterminehowmanyofitschildcoreswillgodowneachpathoftheconditional,grabthelistofrequiredmachinecodeinstructionsforonepath,resolvethemforallcorestakingthatpath,andrepeatforeachpathuntilallpossiblepathshavebeenprocessed.So,foranif-elsestatement(twopossibilities),itwilltellonegroupofcorestoprocessthe“true”path,thenasktheremainingcorestoprocessthe“false”path.Unlesseverycoretakesthesamepath,itmustprocessbothpathseverytime.

So,weshouldavoidbranchingandconditionalstatementsinourShadercode.Ofcourse,thisdependsonhowessentialtheconditionalistoachievingthegraphicaleffectwedesire.But,iftheconditionalisnotdependentonperpixelbehavior,thenwewouldoftenbebetteroffabsorbingthecostofunnecessarymathematicsthaninflictingabranchingcostontheGPU.Forexample,wemightbecheckingwhetheravalueisnon-zerobeforeusingitinacalculation,orcomparingagainstsomeglobalflagintheMaterialbeforetakingoneactionoranother.Bothofthesecaseswouldbegoodcandidatesforoptimizationbyremovingtheconditionalcheck.

http://freepdf-books.com

Page 274: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Reducedatadependencies

ThecompilerwilltryitsbesttooptimizeourShadercodeintothemoreGPU-friendlylow-levellanguagesothatitisnotwaitingondatatobefetchedwhenitcouldbeprocessingsomeothertask.Forexample,thefollowingpoorly-optimizedcode,couldbewritteninourShader:

floatsum=input.color1.r;

sum=sum+input.color2.g;

sum=sum+input.color3.b;

sum=sum+input.color4.a;

floatresult=calculateSomething(sum);

IfwewereabletoforcetheShadercompilertocompilethiscodeintomachinecodeinstructionsasitiswritten,thenthiscodehasadatadependencysuchthateachcalculationcannotbeginuntilthelastfinishesduetothedependencyonthesumvariable.But,suchsituationsareoftendetectedbytheShadercompilerandoptimizedintoaversionthatusesinstruction-levelparallelism(thecodeshownnextisthehigh-levelcodeequivalentoftheresultingmachinecode):

floatsum1,sum2,sum3,sum4;

sum1=input.color1.r;

sum2=input.color2.g;

sum3=input.color3.b

sum4=input.color4.a;

floatsum=sum1+sum2+sum3+sum4;

floatresult=CalculateSomething(sum);

Inthiscase,thecompilerwouldrecognizethatitcanfetchthefourvaluesfrommemoryinparallelandcompletethesummationonceallfourhavebeenfetchedindependentlyviathread-levelparallelism.Thiscansavealotoftime,relativetoperformingthefourfetchesoneafteranother.

However,longchainsofdatadependencycanabsolutelymurderShaderperformance.IfwecreateastrongdatadependencyinourShader’ssourcecode,thenithasbeengivennofreedomtomakesuchoptimizations.Forexample,thefollowingdatadependencywouldbepainfulonperformance,asonestepcannotbecompletedwithoutwaitingonanothertofetchdataandperformingtheappropriatecalculation.

float4val1=tex2D(_tex1,input.texcoord.xy);

float4val2=tex2D(_tex2,val1.yz);

float4val3=tex2D(_tex3,val2.zw);

Strongdatadependenciessuchastheseshouldbeavoidedwheneverpossible.

SurfaceShaders

Ifwe’reusingUnity’sSurfaceShaders,whichareawayforUnitydeveloperstogettogripswithShaderprogramminginamoresimplifiedfashion,thentheUnityEnginetakescareofconvertingourSurfaceShadercodeforus,abstractingawaysomeoftheoptimizationopportunitieswehavejustcovered.However,itdoesprovidesomemiscellaneousvaluesthatcanbeusedasreplacements,whichreduceaccuracybut

http://freepdf-books.com

Page 275: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

simplifythemathematicsintheresultingcode.SurfaceShadersaredesignedtohandlethegeneralcasefairlyefficiently,butoptimizationisbestachievedwithapersonaltouch.

Theapproxviewattributewillapproximatetheviewdirection,savingcostlyoperations.halfasviewwillreducetheprecisionoftheviewvector,butbewareofitseffectonmathematicaloperationsinvolvingmultipleprecisiontypes.noforwardaddwilllimittheShadertoonlyconsideringasingledirectionallight,reducingDrawCallssincetheShaderwillrenderinonlyasinglepass,butreducinglightingcomplexity.Finally,noambientwilldisableambientlightingintheShader,removingsomeextramathematicaloperationsthatwemaynotneed.

UseShader-basedLOD

WecanforceUnitytorenderdistantobjectsusingsimplerShaders,whichcanbeaneffectivewayofsavingfillrate,particularlyifwe’redeployingourgameontomultipleplatformsorsupportingawiderangeofhardwarecapability.TheLODkeywordcanbeusedintheShadertosettheonscreensizefactorthattheShadersupports.IfthecurrentLODleveldoesnotmatchthisvalue,itwilldroptothenextfallbackShaderandsoonuntilitfindstheShaderthatsupportsthegivensizefactor.WecanalsochangeagivenShaderobject’sLODvalueatruntimeusingthemaximumLODproperty.

Thisfeatureissimilartothemesh-basedLODcoveredearlier,andusesthesameLODvaluesfordeterminingobjectformfactor,soitshouldbeconfiguredassuch.

http://freepdf-books.com

Page 276: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MemorybandwidthAnothermajorcomponentofbackendprocessingandapotentialsourceofbottlenecksismemorybandwidth.MemorybandwidthisconsumedwheneveratexturemustbepulledfromasectionoftheGPU’smainvideomemory(alsoknownasVRAM).TheGPUcontainsmultiplecoresthateachhaveaccesstothesameareaofVRAM,buttheyalsoeachcontainamuchsmaller,localTextureCachethatstoresthecurrenttexture(s)theGPUhasbeenmostrecentlyworkingwith.ThisissimilarindesigntothemultitudeofCPUcachelevelsthatallowmemorytransferupanddownthechain,asaworkaroundforthefactthatfastermemorywill,invariably,bemoreexpensivetoproduce,andhencesmallerincapacitycomparedtoslowermemory.

WheneveraFragmentShaderrequestsasamplefromatexturethatisalreadywithinthecore’slocalTextureCache,thenitislightningfastandbarelyperceivable.But,ifatexturesamplerequestismade,thatdoesnotyetexistwithintheTextureCache,thenitmustbepulledinfromVRAMbeforeitcanbesampled.ThisfetchrequestriskscachemisseswithinVRAMasittriestofindtherelevanttexture.Thetransferitselfconsumesacertainamountofmemorybandwidth,specificallyanamountequaltothetotalsizeofthetexturefilestoredwithinVRAM(whichmaynotbetheexactsizeoftheoriginalfile,northesizeinRAM,duetoGPU-levelcompression).

It’sforthisreasonthat,ifwe’rebottleneckedonmemorybandwidth,thenperformingabruteforcetestbyreducingtexturequalitywouldsuddenlyresultinaperformanceimprovement.We’veshrunkthesizeofourtextures,easingtheburdenontheGPU’smemorybandwidth,allowingittofetchthenecessarytexturesmuchquicker.GloballyreducingtexturequalitycanbeachievedbygoingtoEdit|ProjectSettings|Quality|TextureQualityandsettingthevaluetoHalfRes,QuarterRes,orEighthRes.

Intheeventthatmemorybandwidthisbottlenecked,thentheGPUwillkeepfetchingthenecessarytexturefiles,buttheentireprocesswillbethrottledastheTextureCachewaitsforthedatatoappearbeforeprocessingthefragment.TheGPUwon’tbeabletopushdatabacktotheFrameBufferintimetoberenderedontothescreen,blockingthewholeprocessandculminatinginapoorframerate.

Ultimately,properusageofmemorybandwidthisabudgetingconcern.Forexample,withamemorybandwidthof96GB/secpercoreandatargetframerateof60framespersecond,thentheGPUcanaffordtopull96/60=1.6GBworthoftexturedataeveryframebeforebeingbottleneckedonmemorybandwidth.

TipMemorybandwidthisoftenlistedonapercorebasis,butsomeGPUmanufacturersmaytrytomisleadyoubymultiplyingmemorybandwidthbythenumberofcoresinordertolistabigger,butlesspracticalnumber.Becauseofthis,researchmaybenecessarytoconfirmthememorybandwidthlimitwehaveforthetargetGPUhardwareisgivenonapercorebasis.

Notethatthisvalueisnotthemaximumlimitonthetexturedatathatourgamecan

http://freepdf-books.com

Page 277: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

containintheproject,norinCPURAM,noteveninVRAM.Itisametricthatlimitshowmuchtextureswappingcanoccurduringoneframe.ThesametexturecouldbepulledbackandforthmultipletimesinasingleframedependingonhowmanyShadersneedtousethem,theorderthattheobjectsarerendered,andhowoftentexturesamplingmustoccur,sorenderingjustafewobjectscouldconsumewholegigabytesofmemorybandwidthiftheyallrequirethesamehighquality,massivetextures,requiremultiplesecondarytexturemaps(normalmaps,emissionmaps,andsoon),andarenotbatchedtogether,becausetheresimplyisn’tenoughTextureCachespaceavailabletokeepasingletexturefilelongenoughtoexploititduringthenextrenderingpass.

Thereareseveralapproacheswecantaketosolvebottlenecksinmemorybandwidth.

UselesstexturedataThisapproachissimple,straightforward,andalwaysagoodideatoconsider.Reducingtexturequality,eitherthroughresolutionorbitrate,isnotidealforgraphicalquality,butwecansometimesgetawaywithusing16-bittextureswithoutanynoticeabledegradation.

MipMaps(Chapter4,KickstartYourArt)areanotherexcellentwayofreducingtheamountoftexturedatabeingpushedbackandforthbetweenVRAMandtheTextureCache.NotethattheSceneViewhasaMipmapsShadingMode,whichwillhighlighttexturesinoursceneblueorreddependingonwhetherthecurrenttexturescaleisappropriateforthecurrentSceneView’scamerapositionandorientation.Thiswillhelpidentifywhattexturesaregoodcandidatesforfurtheroptimization.

TipMipMapsshouldalmostalwaysbeusedin3DScenes,unlessthecameramovesverylittle.

TestdifferentGPUTextureCompressionformatsTheTextureCompressiontechniquesyoulearnedbackinChapter4,KickstartYourArt,weredescribedinsuchawaythathelpedreduceourapplication’sfootprint(executablefilesize),andruntimeCPUmemoryusage,thatis,thestorageareawherealltextureresourcedataiskeptuntilitisneededbytheGPU.However,oncethedatareachestheGPU,itusesadifferentformofcompressiontokeeptexturedatasmall.ThecommonformatsareDXT,PVRTC,ETC,andASTC.

Tomakemattersmoreconfusing,eachplatformandGPUhardwaresupportsdifferentcompressionformats,andifthedevicedoesnotsupportthegivencompressionformat,thenitwillbehandledatthesoftwarelevel.Inotherwords,theCPUwillneedtostopandrecompressthetexturetothedesiredformattheGPUwants,asopposedtotheGPUtakingcareofitwithaspecializedhardwarechip.

ThecompressionoptionsareonlyavailableifatextureresourcehasitsTextureTypefieldsettoAdvanced.Usinganyoftheothertexturetypesettingswillsimplifythechoices,andUnitywillmakeabestguesswhendecidingwhichformattouseforthetargetplatform,whichmaynotbeidealforagivenpieceofhardwareandthuswillconsumemorememorybandwidththannecessary.

http://freepdf-books.com

Page 278: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThebestapproachtodeterminingthecorrectformatistosimplytestabunchofdifferentdevicesandTextureCompressiontechniquesandfindonethatfits.Forexample,commonwisdomsaysthatETCisthebestchoiceforAndroidsincemoredevicessupportit,butsomedevelopershavefoundtheirgameworksbetterwiththeDXTandPVRTCformatsoncertaindevices.

Bewarethat,ifwe’reatthepointwhereindividuallytweakingTextureCompressiontechniquesisnecessary,thenhopefullywehaveexhaustedallotheroptionsforreducingmemorybandwidth.Bygoingdownthisroad,wecouldbecommittingtosupportingmanydifferentdeviceseachintheirownspecificway.Manyofuswouldprefertokeepthingssimplewithageneralsolutioninsteadofpersonalcustomizationandtime-consuminghandiworktoworkaroundproblemslikethis.

MinimizetexturesamplingCanwemodifyourShaderstoremovesometexturesamplingoverhead?Didweaddsomeextratexturelookupfilestogiveourselvessomefillratesavingsonmathematicalfunctions?Ifso,wemightwanttoconsiderloweringtheresolutionofsuchtexturesorrevertingthechangesandsolvingourfillrateproblemsinotherways.Essentially,thelesstexturesamplingwedo,thelessoftenweneedtousememorybandwidthandthecloserwegettoresolvingthebottleneck.

OrganizeassetstoreducetextureswapsThisapproachbasicallycomesbacktoBatchingandAtlasingagain.Arethereopportunitiestobatchsomeofourbiggesttexturefilestogether?Ifso,thenwecouldsavetheGPUfromhavingtopullinthesametexturefilesoverandoveragainduringthesameframe.Asalastresort,wecouldlookforwaystoremovesometexturesfromtheentireprojectandreusesimilarfiles.Forinstance,ifwehavefillratebudgettospare,thenwemaybeabletousesomeFragmentShaderstomakeahandfuloftexturesfilesappearinourgamewithdifferentcolorvariations.

http://freepdf-books.com

Page 279: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

VRAMlimitsOnelastconsiderationrelatedtotexturesishowmuchVRAMwehaveavailable.MosttexturetransferfromCPUtoGPUoccursduringinitialization,butcanalsooccurwhenanon-existenttextureisfirstrequiredbythecurrentview.Thisprocessisasynchronousandwillresultinablanktexturebeinguseduntilthefulltextureisreadyforrendering.Assuch,weshouldavoidtoomuchtexturevariationacrossourScenes.

TexturepreloadingEventhoughitdoesn’tstrictlyrelatetographicsperformance,itisworthmentioningthattheblanktexturethatisusedduringasynchronoustextureloadingcanbejarringwhenitcomestogamequality.WewouldlikeawaytocontrolandforcethetexturetobeloadedfromdisktothemainmemoryandthentoVRAMbeforeitisactuallyneeded.

AcommonworkaroundistocreateahiddenGameObjectthatfeaturesthetextureandplaceitsomewhereintheSceneontheroutethattheplayerwilltaketowardstheareawhereitisactuallyneeded.Assoonasthetexturedobjectbecomesacandidatefortherenderingsystem(evenifit’stechnicallyhidden),itwillbegintheprocessofcopyingthedatatowardsVRAM.Thisisalittleclunky,butiseasytoimplementandworkssufficientlywellinmostcases.

WecanalsocontrolsuchbehaviorviaScriptcodebychangingahiddenMaterial’stexture:

GetComponent<Renderer>().material.texture=textureToPreload;

TexturethrashingIntherareeventthattoomuchtexturedataisloadedintoVRAM,andtherequiredtextureisnotpresent,theGPUwillneedtorequestitfromthemainmemoryandoverwritetheexistingtexturedatatomakeroom.Thisislikelytoworsenovertimeasthememorybecomesfragmented,anditintroducesariskthatthetexturejustflushedfromVRAMneedstobepulledagainwithinthesameframe.Thiswillresultinaseriouscaseofmemory“thrashing”,andshouldbeavoidedatallcosts.

ThisislessofaconcernonmodernconsolessuchasthePS4,XboxOne,andWiiU,sincetheyshareacommonmemoryspaceforbothCPUandGPU.Thisdesignisahardware-leveloptimizationgiventhefactthatthedeviceisalwaysrunningasingleapplication,andalmostalwaysrendering3Dgraphics.But,allotherplatformsmustsharetimeandspacewithmultipleapplicationsandbecapableofrunningwithoutaGPU.TheythereforefeatureseparateCPUandGPUmemory,andwemustensurethatthetotaltextureusageatanygivenmomentremainsbelowtheavailableVRAMofthetargethardware.

Notethatthis“thrashing”isnotpreciselythesameasharddiskthrashing,wherememoryiscopiedbackandforthbetweenmainmemoryandvirtualmemory(theswapfile),butitisanalogous.Ineithercase,dataisbeingunnecessarilycopiedbackandforthbetweentworegionsofmemorybecausetoomuchdataisbeingrequestedintooshortatimeperiodforthesmallerofthetwomemoryregionstoholditall.

http://freepdf-books.com

Page 280: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

NoteThrashingsuchasthiscanbeacommoncauseofdreadfulgraphicsperformancewhengamesareportedfrommodernconsolestothedesktopandshouldbetreatedwithcare.

Avoidingthisbehaviormayrequirecustomizingtexturequalityandfilesizesonaper-platformandper-devicebasis.Bewarnedthatsomeplayersarelikelytonoticetheseinconsistenciesifwe’redealingwithhardwarefromthesameconsoleordesktopGPUgeneration.Asmanyofuswillknow,evensmalldifferencesinhardwarecanleadtoalotofapples-versus-orangescomparisons,buthardcoregamerswillexpectasimilarlevelofqualityacrosstheboard.

http://freepdf-books.com

Page 281: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 282: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LightingandShadowingLightingandShadowingcanaffectallpartsofthegraphicspipeline,andsotheywillbetreatedseparately.Thisisperhapsoneofthemostimportantpartsofgameartanddesigntogetright.GoodLightingandShadowingcanturnamundanesceneintosomethingspectacularasthereissomethingmagicalaboutprofessionalcoloringthatmakesitvisuallyappealing.Eventhelow-polyartstyle(thinkMonumentValley)reliesheavilyonagoodlightingandshadowingprofileinordertoallowtheplayertodistinguishoneobjectfromanother.But,thisisn’tanartbook,sowewillfocusontheperformancecharacteristicsofvariousLightingandShadowingfeatures.

Unityofferstwostylesofdynamiclightrendering,aswellasbakedlightingeffectsthroughlightmaps.Italsoprovidesmultiplewaysofgeneratingshadowswithvaryinglevelsofcomplexityandruntimeprocessingcost.Betweenthetwo,therearealotofoptionstoexplore,andalotofthingsthatcantripusupifwe’renotcareful.

TheUnitydocumentationcoversallofthesefeaturesinanexcellentamountofdetail(startwiththispageandworkthroughthem:http://docs.unity3d.com/Manual/Lighting.html),sowe’llexaminethesefeaturesfromaperformancestandpoint.

Let’stacklethetwomainlightrenderingmodesfirst.ThissettingcanbefoundunderEdit|ProjectSettings|Player|OtherSettings|Rendering,andcanbeconfiguredonaper-platformbasis.

http://freepdf-books.com

Page 283: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ForwardRenderingForwardRenderingistheclassicalformofrenderinglightsinourscene.EachobjectislikelytoberenderedinmultiplepassesthroughthesameShader.Howmanypassesarerequiredwillbebasedonthenumber,distance,andbrightnessoflightsources.Unitywilltrytoprioritizewhichdirectionallightisaffectingtheobjectthemostandrendertheobjectina“basepass”asastartingpoint.Itwillthentakeuptofourofthemostpowerfulpointlightsnearbyandre-renderthesameobjectmultipletimesthroughthesameFragmentShader.Thenextfourpointlightswillthenbeprocessedonaper-vertexbasis.Allremaininglightsaretreatedasagiantblobbymeansofatechniquecalledsphericalharmonics.

Someofthisbehaviorcanbesimplifiedbysettingalight’sRenderModetovaluessuchasNotImportant,andchangingthevalueofEdit|ProjectSettings|Quality|PixelLightCount.Thisvaluelimitshowmanylightswillbetreatedonaperpixelbasis,butisoverriddenbyanylightswithaRenderModesettoImportant.Itisthereforeuptoustousethiscombinationofsettingsresponsibly.

Asyoucanimagine,thedesignofForwardRenderingcanutterlyexplodeourDrawCallcountveryquicklyinsceneswithalotofpointlightspresent,duetothenumberofrenderstatesbeingconfiguredandShaderpassesbeingreprocessed.CPU-boundapplicationsshouldavoidthisrenderingmodeifpossible.

NoteMoreinformationonForwardRenderingcanbefoundintheUnitydocumentation:http://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html.

http://freepdf-books.com

Page 284: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

DeferredShadingDeferredShadingorDeferredRenderingasitissometimesknown,isonlyavailableonGPUsrunningatleastShaderModel3.0.Inotherwords,anydesktopgraphicscardmadeafteraround2004.Thetechniquehasbeenaroundforawhile,butithasnotresultedinacompletereplacementoftheForwardRenderingmethodduetothecaveatsinvolvedandlimitedsupportonmobiledevices.Anti-aliasing,transparency,andanimatedcharactersreceivingshadowsareallfeaturesthatcannotbemanagedthroughDeferredShadingaloneandwemustusetheForwardRenderingtechniqueasafallback.

DeferredShadingissonamedbecauseactualshadingdoesnotoccuruntilmuchlaterintheprocess;thatis,itisdeferreduntillater.Fromaperformanceperspective,theresultsarequiteimpressiveasitcangenerateverygoodperpixellightingwithsurprisinglylittleDrawCalleffort.TheadvantageisthatahugeamountoflightingcanbeaccomplishedusingonlyasinglepassthroughthelightingShader.ThemaindisadvantagesincludetheadditionalcostsifwewishtopileonadvancedlightingfeaturessuchasShadowingandanystepsthatmustpassthroughForwardRenderinginordertocomplete,suchastransparency.

NoteTheUnitydocumentationcontainsanexcellentsourceofinformationontheDeferredShadingtechnique,itsadvantages,anditspitfalls:http://docs.unity3d.com/Manual/RenderTech-DeferredShading.html.

http://freepdf-books.com

Page 285: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

VertexLitShading(legacy)Technically,therearemorethantwolightingmethods.Unityallowsustouseacoupleoflegacylightingsystems,onlyoneofwhichmayseeactualuseinthefield:VertexLitShading.Thisisamassivesimplificationoflighting,aslightingisonlyconsideredpervertex,andnotperpixel.Inotherwords,entirefacesarecoloredbasedontheincominglightcolor,andnotindividualpixels.

Itisnotexpectedthatmany,orreallyany,3Dgameswillmakeuseofthislegacytechnique,asalackofshadowsandproperlightingmakevisualizationsofdepthverydifficult.Itismostlyrelegatedto2Dgamesthatdon’tintendtomakeuseofshadows,normalmaps,andvariousotherlightingfeatures,butitisthereifweneedit.

http://freepdf-books.com

Page 286: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Real-timeShadowsSoftShadowsareexpensive,HardShadowsarecheap,andNoShadowsarefree.ShadowResolution,ShadowProjection,ShadowDistance,andShadowCascadesareallsettingswecanfindunderEdit|ProjectSettings|Quality|Shadowsthatwecanusetomodifythebehaviorandcomplexityofourshadowingpasses.ThatsummarizesalmosteverythingweneedtoknowaboutUnity’sreal-timeshadowingtechniquesfromahigh-levelperformancestandpoint.Wewillcovershadowsmoreinthefollowingsectiononoptimizingourlightingeffects.

http://freepdf-books.com

Page 287: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LightingoptimizationWithacursoryglanceatalloftherelevantlightingtechniques,let’srunthroughsometechniqueswecanusetoimprovelightingcosts.

UsetheappropriateShadingModeItisworthtestingbothofthemainrenderingmodestoseewhichonebestsuitsourgame.DeferredShadingisoftenusedasabackupintheeventthatForwardRenderingisbecomingaburdenonperformance,butitreallydependsonwhereelsewe’refindingbottlenecksasitissometimesdifficulttotellthedifferencebetweenthem.

UseCullingMasksALightComponent’sCullingMaskpropertyisalayer-basedmaskthatcanbeusedtolimitwhichobjectswillbeaffectedbythegivenLight.Thisisaneffectivewayofreducinglightingoverhead,assumingthatthelayerinteractionsalsomakesensewithhowweareusinglayersforphysicsoptimization.Objectscanonlybeapartofasinglelayer,andreducingphysicsoverheadprobablytrumpslightingoverheadinmostcases;thus,ifthereisaconflict,thenthismaynotbetheidealapproach.

NotethatthereislimitedsupportforCullingMaskswhenusingDeferredShading.Becauseofthewayittreatslightinginaveryglobalfashion,onlyfourlayerscanbedisabledfromthemask,limitingourabilitytooptimizeitsbehaviorthroughthismethod.

UseBakedLightmapsBakingLightingandShadowingintoaSceneissignificantlylessprocessor-intensivethangeneratingthematruntime.Thedownsideistheaddedapplicationfootprint,memoryconsumption,andpotentialformemorybandwidthabuse.Ultimately,unlessagame’slightingeffectsarebeinghandledexclusivelythroughLegacyVertexLightingorasingleDirectionalLight,thenitshouldprobablyincludeLightmappingtomakesomehugebudgetsavingsonlightingcalculations.Relyingentirelyonreal-timelightingandshadowsisarecipefordisasterunlessthegameistryingtowinanawardforthesmallestapplicationfilesizeofalltime.

OptimizeShadowsShadowingpassesmostlyconsumeourDrawCallsandfillrate,buttheamountofvertexpositiondatawefeedintotheprocessandourselectionfortheShadowProjectionsettingwillaffectthefrontend’sabilitytogeneratetherequiredshadowcastersandshadowreceivers.Weshouldalreadybeattemptingtoreducevertexcountstosolvefrontendbottleneckinginthefirstplace,andmakingthischangewillbeanaddedmultipliertowardsthateffort.

DrawCallsareconsumedduringshadowingbyrenderingvisibleobjectsintoaseparatebuffer(knownastheshadowmap)aseitherashadowcaster,ashadowreceiver,orboth.EachobjectthatisrenderedintothismapwillconsumeanotherDrawCall,whichmakesshadowsahugeperformancecostmultiplier,soitisoftenasettingthatgameswillexpose

http://freepdf-books.com

Page 288: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

tousersviaqualitysettings,allowinguserswithweakerhardwaretoreducetheeffectorevendisableitentirely.

ShadowDistanceisaglobalmultiplierforruntimeshadowrendering.Thefewershadowsweneedtodraw,thehappiertheentirerenderingprocesswillbe.Thereislittlepointinrenderingshadowsatagreatdistancefromthecamera,sothissettingshouldbeconfiguredspecifictoourgameandhowmuchshadowingweexpecttowitnessduringgameplay.Itisalsoacommonsettingthatisexposedtotheusertoreducetheburdenofrenderingshadows.

HighervaluesofShadowResolutionandShadowCascadeswillincreaseourmemorybandwidthandfillrateconsumption.Bothofthesesettingscanhelpcurbtheeffectsofartefactsinshadowrendering,butatthecostofamuchlargershadowmapsizethatmustbemovedaroundandofthecanvassizetodrawto.

NoteTheUnitydocumentationcontainsanexcellentsummaryonthetopicofthealiasingeffectofshadowmapsandhowtheShadowCascadesfeaturehelpstosolvetheproblem:http://docs.unity3d.com/Manual/DirLightShadows.html.

It’sworthnotingthatSoftShadowsdonotconsumeanymorememoryorCPUoverheadrelativetoHardShadows,astheonlydifferenceisamorecomplexShader.ThismeansthatapplicationswithenoughfillratetosparecanenjoytheimprovedgraphicalfidelityofSoftShadows.

http://freepdf-books.com

Page 289: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 290: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

OptimizinggraphicsformobileUnity’sabilitytodeploytomobiledeviceshascontributedgreatlytoitspopularityamonghobbyist,small,andmid-sizedevelopmentteams.Assuch,itwouldbeprudenttocoversomeapproachesthataremorebeneficialformobileplatformsthanfordesktopandotherdevices.

Notethatany,andall,ofthefollowingapproachesmaybecomeobsoletesoon,iftheyaren’talready.Themobiledevicemarketismovingblazinglyfast,andthefollowingtechniquesastheyapplytomobiledevicesmerelyreflectconventionalwisdomfromthelasthalfdecade.Weshouldoccasionallytesttheassumptionsbehindtheseapproachesfromtime-to-timetoseewhetherthelimitationsofmobiledevicesstillfitthemobilemarketplace.

http://freepdf-books.com

Page 291: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MinimizeDrawCallsMobileapplicationsaremoreoftenbottleneckedonDrawCallsthanonfillrate.Notthatfillrateconcernsshouldbeignored(nothingshould,ever!),butthismakesitalmostnecessaryforanymobileapplicationofreasonablequalitytoimplementMeshCombining,Batching,andAtlasingtechniquesfromtheverybeginning.DeferredRenderingisalsothepreferredtechniqueasitfitswellwithothermobile-specificconcerns,suchasavoidingtransparencyandhavingtoomanyanimatedcharacters.

http://freepdf-books.com

Page 292: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MinimizetheMaterialcountThisconcerngoeshandinhandwiththeconceptsofBatchingandAtlasing.ThefewerMaterialsweuse,thefewerDrawCallswillbenecessary.ThisstrategywillalsohelpwithconcernsrelatingtoVRAMandmemorybandwidth,whichtendtobeverylimitedonmobiledevices.

http://freepdf-books.com

Page 293: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MinimizetexturesizeandMaterialcountMostmobiledevicesfeatureaverysmallTextureCacherelativetodesktopGPUs.Forinstance,theiPhone3Gcanonlysupportatotaltexturesizeof1024x1024duetorunningOpenGLES1.1withsimplevertexrenderingtechniques.MeanwhiletheiPhone3GS,iPhone4,andiPadgenerationrunOpenGLES2.0,whichonlysupportstexturesupto2048x2048.Latergenerationscansupporttexturesupto4096x4096.Doublecheckthedevicehardwarewearetargetingtobesureitsupportsthetexturefilesizeswewishtouse(therearetoomanyAndroiddevicestolisthere).However,later-generationdevicesareneverthemostcommondevicesinthemobilemarketplace.Ifwewishourgametoreachawideaudience(increasingitschancesofsuccess),thenwemustbewillingtosupportweakerhardware.

NotethattexturesthataretoolargefortheGPUwillbedownscaledbytheCPUduringinitialization,wastingvaluableloadingtime,andleavinguswithunintendedgraphicalfidelity.ThismakestexturereuseofparamountimportanceformobiledevicesduetothelimitedVRAMandTextureCachesizesavailable.

http://freepdf-books.com

Page 294: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Maketexturessquareandpowerof2WehavealreadycoveredthistopicinChapter4,KickstartYourArt,butitisworthrevisitingthesubjectofGPU-levelTextureCompression.TheGPUwillfinditdifficult,orsimplybeunabletocompressthetextureifitisnotinasquareformat,somakesureyousticktothecommondevelopmentconventionandkeepthingssquareandsizedtoapowerof2.

http://freepdf-books.com

Page 295: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UsethelowestpossibleprecisionformatsinShadersMobileGPUsareparticularlysensitivetoprecisionformatsinitsShaders,sothesmallestformatsshouldbeused.Onarelatednote,formatconversionshouldbeavoidedforthesamereason.

http://freepdf-books.com

Page 296: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AvoidAlphaTestingMobileGPUshaven’tquitereachedthesamelevelsofchipoptimizationasdesktopGPUs,andAlphaTestingremainsaparticularlycostlytaskonmobiledevices.InmostcasesitshouldsimplybeavoidedinfavorofAlphaBlending.

http://freepdf-books.com

Page 297: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 298: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryIfyou’vemadeitthisfarwithoutskippingahead,thencongratulationsareinorder.ThatwasalotofinformationtoabsorbforjustonecomponentoftheUnityEngine,butthenitisclearlythemostcomplicatedofthemall,requiringamatchingdepthofexplanation.Hopefully,you’velearnedalotofapproachestohelpyouimproveyourrenderingperformanceandenoughabouttherenderingpipelinetoknowhowtousethemresponsibly!

Bynowweshouldbeusedtotheideathat,withtheexceptionofalgorithmimprovements,everyperformanceenhancementweimplementwillcomewithsomerelatedcostthatwemustbewillingtobearforthesakeofremovingonebottleneck.Weshouldalsobereadytoimplementmultipletechniquesuntilwe’vesquashedthemall.

We’vejustcoveredaveryabstractsystemingreatdetail,solet’smovethingsalongwithanexplorationofamoreconcretesystem:Unity’sunderlyingEngineandtheC#language.Inthenextchapter,wewilltakealookatourScriptcodeinamoreadvancedlightandinvestigatesomemethodstoimproveourCPUandmemorymanagement.

http://freepdf-books.com

Page 299: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 300: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter7.MasterfulMemoryManagementUsingmemoryproperlywithintheUnityEnginerequiresagoodamountofunderstandingoftheunderlyingUnityEngineandMonoFramework.Thiscanbeabitofanintimidatingplaceforsomedevelopers,sincemanypickedUnityastheirsolutionprimarilytoavoidthekindoflow-levelgruntworkthatcomesfromenginedevelopmentandmemorymanagement.Theywouldpreferinsteadtofocusonhigher-levelconcernsrelatedtogameplayimplementation,leveldesign,andartassetmanagement.

Manygamesoflimitedscopecangetawaywithfocusingonsuchhigher-levelconcerns,atthecostofwastedresources,andmayneverrunintoanyproblemsrelatedtomemory.Thisisallwellandgooduntilthedayitbecomesaproblem.Atthispoint,theirneglectinunderstandingtheimportantcomponentsoftheengineleadstoascrambletofindsolutionsthatcanbedifficulttounderstandandimplementwithoutproperknowledgetobackitup.

Therefore,understandingwhatishappeningwithmemoryallocationsandC#languagefeatures,howtheyinteractwiththeMonoPlatform,howMonointeractswiththeunderlyingengine,andthevariouslibrarieswehaveavailableareabsolutelyparamounttomakinghigh-quality,efficientscriptcode.So,inthischapter,youwilllearnaboutallofthenutsandboltsoftheunderlyingUnityEngine,MonoPlatform,C#language,and.NETFramework.

Let’sstartbyexploringthefamiliarpartoftheengine,whichhandlesmostoftheworkforourgame’sscriptingcode—theMonoplatform.

http://freepdf-books.com

Page 301: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheMonoplatformMonoisamagicalsauce,mixedintotheUnityrecipe,whichgivesitalotofitscross-platformcapability.MonoisanopensourceprojectthatbuiltitsownframeworkandlibrariesbasedontheAPI,specifications,andtoolsfromMicrosoft’s.NETFrameworkandcommonlibraries.Essentially,itisarecreationofthe.NETFramework,asitwasaccomplishedwithlittletonoaccesstothesourcecode.Notethat,despiteMono’slibrariesbeinganopensourcerecreationofMicrosoft’sbase.NETclasslibrary,itisfullycompatiblewiththeoriginallibraryfromMicrosoft.

ThegoaloftheMonoprojectistoprovideaframeworktoallowcross-platformcompatibilityusingthe.NETFrameworkasacommonlayer.Itallowsapplicationstobewritteninacommonprogramminglanguageandrunagainstmanydifferenthardwareplatforms,includingLinux,OSX,Windows,ARM,PowerPC,andmore.Monoalsosupportsmanylanguages,notjusttheC#,Boo,andUnityScriptwemaybefamiliarwith.Anylanguagethatcanbecompiledinto.NET’spureCommonIntermediateLanguage(CIL–moreonthislater)issufficienttointegratewiththeMonoplatform.ThisincludesC#,butevenincludeslanguagessuchasF#,Java,VisualBasic.NET,PythonNet,andIronPython.

AcommonmisconceptionabouttheUnityEngineisthatitisbuiltontopoftheMonoplatform.Thisisuntrue,astheMonosidedoesnothandlemanyimportantgametaskssuchasaudio,rendering,physics,andsoon.UnityTechnologiesbuiltanativeC++backendforthesakeofspeed,andallowsitsuserscontroloftheenginethroughMonoasascriptinginterface.Assuch,MonoismerelyacomponentoftheunderlyingUnityEngine.Thisisequivalenttomanyothergameengines,whichrunC++underthehood,handlingimportanttaskssuchasrendering,animation,resourcemanagement,andsoon,whilesimultaneouslyprovidingascriptinglanguageforgameplaylogictobeimplemented.TheMonoplatformwaschosenbyUnityTechnologiesforthistask.

TipNativecodesimplymeanscodethatiscompileddirectlytothetargetOS,andexecuteswithoutadditionallayersofcomplexityintheruntimeenvironment.Thiskeepsoverheadcostslow,butattheexpenseofneedingtomanagememoryandothertaskswithinthecodeinamoredirectfashion.

Scriptinglanguagestypicallyabstractawaycomplexmemorymanagementthroughautomaticgarbagecollection,andprovidevarioussafetyfeatures,whichsimplifytheactofprogrammingattheexpenseofruntimeoverhead.Somescriptinglanguagescanalsobeinterpretedatruntime,meaningthattheydon’tneedtobecompiledbeforeexecution.Therawinstructionsareconverteddynamicallyintomachinecodeandexecutedthemomenttheyarereadduringruntime.Thelastfeature,andprobablythemostimportantone,isthattheyallowsimplersyntaxofprogrammingcommands.Thisusuallyimprovesthedevelopmentworkflowimmensely,asteammemberswithoutmuchexperienceusinglanguagessuchasC++cancontributetothecodebase.Thisenablesthemtoimplementthingssuchasgameplaylogicinasimplerformat,attheexpenseofacertainamountof

http://freepdf-books.com

Page 302: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

controlandruntimeexecutionspeed.

Notethatsuchlanguagesareoftencalled“managed”languages,whichfeaturemanagedcode.Technically,thiswasatermcoinedbyMicrosofttorefertoanysourcecodethatmustruninsidetheirCommonLanguageRuntime(CLR)environment(morelater),asopposedtocodethatiscompiledandrunnativelythroughthetargetOperatingSystem(OS).But,becauseoftheprevalenceandcommonfeaturesthatexistbetweentheCLRandotherlanguagesthatfeaturetheirownsimilarlydesignedruntimeenvironments(suchasJava),theterm“managed”hassincebecomealittlevague.Ittendstobeusedtorefertoanylanguageorcodethatdependsonitsownruntimeenvironmentandthatmay,ormaynot,includeautomaticgarbagecollection.Fortherestofthischapter,wewillusetheterm“managed”torefertocodethatbothdependsonaseparateruntimeenvironmentandhasundergoneautomaticgarbagecollection.

Theruntimeperformancecostofmanagedlanguagesisbecominglessandlesssignificanteveryyear.Thisispartlyduetogradualoptimizationsintoolsandruntimeenvironments,andpartlyduetothecomputingpoweroftheaveragedevicegraduallybecominggreater.Butthemainpointofcontroversyinmanagedlanguagesstillremainstheirautomaticmemorymanagement.Managingmemorymanuallycanbeacomplextaskthatcantakemanyyearsofdifficultdebuggingtobeproficientat,butmanydevelopersfeelthatmanagedlanguagessolvethisprobleminwaysthataretoounpredictable,riskingtoomuchproductquality.Suchdevelopersmightcitethatmanagedcodewillneverreachthesamelevelofperformanceasnativecode,anditisfoolhardytobuildhigh-performanceapplicationswiththem.

Thisistruetoanextent,asmanagedlanguagesinvariablyinflictruntimeoverheads,andwelosepartialcontroloverruntimememoryallocations.But,aswithallthings,itbecomesabalancingact,sincenotallresourceusagewillnecessarilyresultinabottleneck,andthebestgamesaren’tnecessarilytheonesthatuseeverysinglebytetotheirfullest.Forexample,imagineauserinterfacethatrefreshesin30microsecondsvianativecodeversus60microsecondsinmanagedcodeduetoanextra100percentoverhead(extremeexample).Themanagedcodeversionisstillfastenoughsuchthattheuserwillneverbeabletonoticethedifference,soistherereallyanyharminusingmanagedcodeforsuchatask?

Inreality,workingwithmanagedlanguagesoftenjustmeansthatdevelopershaveauniquesetofconcernstoworryaboutcomparedtonativecodedevelopers.Assuch,choosingtouseamanagedlanguageispartlyamatterofpreference,andpartlyacompromiseofcontroloverdevelopmentspeed.

http://freepdf-books.com

Page 303: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThecompilationprocessWhenwemakechangestoourC#code,itistypicallycompiledimmediatelyafterweswitchbackfromourfavoriteIDE(whichistypicallyeitherMonoDevelopor,themuchmorefeature-richVisualStudio)totheUnityEditor.However,theC#codeisnotconverteddirectlyintomachinecode,aswewouldexpecttohappenwithstaticcompilersinthelandofC++.Instead,thecodeisconvertedintoanintermediatelanguagecalledCommonIntermediateLanguage(CIL),whichisanabstractionabovenativecode.CILissimilartoJavabytecode,uponwhichitisbased,butCILcodeisentirelyuselessonitsown,asCPUshavenoideahowtoruntheinstructionsdefinedinthislanguage.

Atruntime,thisintermediatecodeisrunthroughtheMonoVirtualMachine(VM),whichisaninfrastructurecomponentthatallowsthesamecodetorunagainstmultipleplatformswithoutneedingtochangethecodeitself.Thisisanimplementationofthe.NETCommonLanguageRuntimeorCLR.Ifwe’rerunningoniOS,werunontheiOS-basedVirtualMachineinfrastructure,andifwe’rerunningonLinux,thenwesimplyuseadifferentonethatisbettersuitedforLinux.

WithintheCLR,theintermediateCILcodewillactuallybecompiledintonativecodeondemand.Thison-demandnativecompilationcanbeaccomplishedeitherbyanAhead-Of-Time(AOT)orJust-In-Time(JIT)compiler,dependingonwhichplatformisbeingtargeted.Thesecompilersallowcodesegmentstobecompiledintonativecode(thatis,machinecodespecifictotheOSitisrunningagainst),andthemaindifferencebetweenthetwotypesiswhenthecodeiscompiled.

AOTcompilationhappensearly(aheadoftime),eitherduringthebuildprocessorduringinitialization.Ineithercase,thecodehasbeenprecompiledandnofurtherruntimecostsareinflictedduetodynamiccompilation.InthecurrentversionofUnity(Version5.2.2),theonlyplatformsthatsupportAOTcompilationareWebGL(andonlywhenUnityScriptisbeingused)andiOS.

JITcompilationhappensdynamicallyatruntimeinaseparatethreadandbeginsjustpriortoexecution(“justintime”forexecution).Often,thisdynamiccompilationcausesthefirstinvocationofapieceofcodetorunalittle(oralot!)moreslowly,becausethecodemustfinishcompilingbeforeitcanbeexecuted.But,fromthatpointforward,wheneverthesamecodeblockisexecuted,thereisnoneedforrecompilation,andtheinstructionsrunthroughthepreviouslycompilednativecode.

Itiscommoninsoftwarethat90percentoftheworkisbeingdonebyonly10percentofthecode.ThisgenerallymeansthatJITcompilationturnsouttobeanetpositiveonperformancethanifwesimplytriedtointerprettheCILcodedirectly.However,becausetheJITcompilermustcompilecodequickly,itisnotabletomakeuseofmanyoptimizationtechniquesthatstaticcompilersareabletoexploit.

ManualJITcompilationIntheeventthatJITcompilationiscausingaruntimeperformanceloss,beawarethatitisactuallypossibletoforceJITcompilationofamethodatanytimeviareflection.

http://freepdf-books.com

Page 304: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ReflectionisausefulfeatureoftheC#language,thatallowsourcodebasetoexploreitselfintrospectivelyfortypeinformation,methods,values,andmetadata.Usingreflectionisoftenaverycostlyprocess.Itshouldbeavoidedatruntimeor,attheveryleast,onlyusedduringinitializationorotherloadingtimes.NotdoingsocaneasilycausesignificantCPUspikesandgameplayfreezing.

WecanmanuallyforceJITcompilationofamethodusingreflectiontoobtainafunctionpointertoit:

varmethod=typeof(MyComponent).GetMethod("MethodName");

if(method!=null){

method.MethodHandle.GetFunctionPointer();

Debug.Log("JITcompilationcomplete!");

}

Thiscodeonlyworksonpublicmethods.Obtainingnon-publicmethodscanbeaccomplishedthroughtheuseofBindingFlags:

usingSystem.Reflection;

//...

varmethod=typeof(MyComponent).GetMethod("MethodName",

BindingFlags.NonPublic|BindingFlags.Instance);

ThiskindofcodeshouldonlyberunforverytargetedmethodswherewearecertainthatJITcompilationiscausingCPUspikes.Thiscanbeverifiedbyrestartingtheapplicationandprofilingamethod’sfirstinvocationversusallsubsequentinvocations.ThedifferencewilltellustheJITcompilationoverhead.

TipNotethattheofficialmethodforforcingJITcompilationinthe.NETlibraryisRuntimeHelpers.PrepareMethod(),butthisisnotproperlyimplementedinthecurrentversionofMonothatcomeswithUnity(MonoVersion2.6.5).TheaforementionedworkaroundshouldbeuseduntilUnityhaspulledinamorerecentversionoftheMonoproject.

http://freepdf-books.com

Page 305: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 306: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MemoryusageoptimizationInmostgameengines,wewouldhavetheluxuryofbeingabletoportinefficientscriptcodeintothefasterC++areaifwewerehittingperformanceissues.ThisisnotanoptionunlessweinvestseriouscashinobtainingtheUnitysourcecode,whichisofferedasalicenseseparatefromtheFree/Personal/Prolicensingsystem,andonapercase,pertitlebasis.ThisforcestheoverwhelmingmajorityofusintoapositionofneedingtomakeourC#script-levelcodeasperformantaspossible.So,whatdoesallofthisbackstorywe’vebeencoveringmeanforuswhenitcomestothetaskofperformanceoptimization?

Firstly,wewon’tbecoveringanythingthatisspecifictotheUnityScriptandBoolanguages(althoughmuchoftheknowledgetranslatestothoselanguages).

Secondly,eventhoughallofourscriptcodemightbeinC#,weneedtobeawarethattheoverallUnityEngineisbuiltfrommultiplecomponentsthateachmaintainsitsownmemorydomains.

Thirdly,onlysometasksweperformwillawakenthedreadedgarbagecollector.Therearequiteafewmemoryallocationapproachesthatwecanusetoavoiditentirely.

Finally,thingscanchangequiteabitdependingonthetargetplatformwe’rerunningagainstandeveryassumptionshouldbetestedforvalidityifwe’restumblingintounexpectedmemorybottlenecks.

http://freepdf-books.com

Page 307: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UnitymemorydomainsThememoryspacewithintheUnityEnginecanbeessentiallysplitintothreedifferentmemorydomains.Eachdomainstoresdifferenttypesofdataandtakescareofaverydifferentsetoftasks.

ThefirstdomainistheNativeDomain.ThisistheunderlyingfoundationoftheUnityEngine,whichiswritteninC++andcompiledtonativecodedependingonwhichplatformisbeingtargeted.ThisareatakescareofallocatingmemoryspaceforthingssuchasAssetdata,forexampleTexturesandMeshes,memoryspaceforvarioussubsystems,suchastheRenderingsystem,Physics,Input,andsoon.Finally,itincludesnativerepresentationsofimportantgameplayobjectssuchasGameObjectandComponent.ThisiswherealotofthebaseComponentclasseskeeptheirdata,suchastheTransformandRigidbodyComponents.

Thesecondmemorydomain,theManagedDomain,iswheretheMonoplatformdoesitswork,andistheareaofmemorythatismaintainedbytheGarbageCollector.Anyscriptingobjectsandcustomclassesarestoredwithinthismemorydomain.ItalsoincludeswrappersfortheverysameobjectrepresentationsthatarestoredwithintheNativeDomain.ThisiswherethebridgebetweenMonocodeandNativecodederivesfrom;eachdomainhasitsownrepresentationforthesameentity,andcrossingthebridgebetweenthemtoomuchcaninflictsomefairlysignificantperformancehitsonourgame,aswelearnedinthepreviouschapters.

WhenanewGameObjectorComponentisinstantiated,itinvolvesallocatingmemoryinboththeManagedandNativeDomains.ThisallowssubsystemssuchasPhysicsandRenderingsystemstocontrolandrenderanobjectthroughitstransformdataontheNativeDomain,whiletheTransformComponentfromourscriptcodeismerelyawaytoreferencethroughthebridgeintotheNativememoryspaceandchangetheobject’stransformdata.Crossingbackandforthacrossthisbridgeshouldbeminimizedasmuchaspossible,duetotheoverheadinvolved,aswe’velearnedthroughtechniquessuchascachingposition/rotationchangesbeforeapplyingthem,backinChapter2,ScriptingStrategies.

Thethirdandfinalmemorydomain(s)arethoseofNativeandExternalDLLs,suchasDirectX,OpenGL,andanycustomDLLs,weattachtoourproject.ReferencingfromMonoC#codeintosuchDLLswillcauseasimilarmemoryspacetransitionasthatbetweenMonocodeandNativecode.

NativememoryWehavenodirectcontroloverwhatisgoingonintheNativeDomainwithouttheUnityEnginesourcecode,butwedohavealotofindirectcontrolbymeansofvariousscript-levelfunctions.Therearetechnicallyavarietyofmemoryallocatorsavailable,whichareusedinternallyforthingssuchasGameObjects,Graphicsobjects,andtheProfiler,butthesearehiddenbehindtheNativecodewall.

However,wecanobservehowmuchmemoryhasbeenallocatedandreservedinthis

http://freepdf-books.com

Page 308: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

memorydomainviatheMemoryAreaoftheProfiler.Nativememoryallocationsshowupunderthevalueslabeled“Unity”,andwecanevengetmoreinformationusingtheDetailedviewandsamplingthecurrentframe.

UndertheSceneMemorysectionoftheDetailedview,wecanobservethatMonoBehaviourobjectsalwaysconsumeaconstantamountofmemory,regardlessoftheirmemberdata.ThisisthememoryconsumedbytheNativerepresentationoftheobject.Notethat376bytesofmemoryisconsumedbyaMonoBehaviourinEditorMode,whileonly156bytesisconsumedwhenprofilingthroughastandaloneapplication.

TipMemoryconsumptioninEditorModeisalwayswildlydifferenttothatofastandaloneversion,duetovariousdebuggingandeditorhookdatabeingapplied.ThisaddsafurtherincentivetoavoidusingEditorModeforprofilingandbenchmarkingpurposes(althoughitcanstillbeusefulattimes).

WecanalsousetheProfiler.GetRuntimeMemorySize()methodtogettheNativememoryallocationsizeofaparticularobject.

ManagedobjectrepresentationsareintrinsicallylinkedtotheirNativerepresentations.ThebestwaytominimizeourNativememoryallocationsistosimplyoptimizeourManagedmemoryusage.

ManagedmemoryMemoryinmostmodernoperatingsystemssplitsdynamicmemoryintotwocategories:thestackandtheheap.Thestackisaspecialreservedspaceinmemory,dedicatedtosmall,short-liveddatavalues,whichareautomaticallydeallocatedthemomenttheygooutofscope.Thestackcontainslocalvariables,aswellashandlestheloadingandunloadingoffunctionsasthey’recalled,andexpandsandcontractsalongwiththecallstack.Deallocationsinthestackarebasicallyfreebecausethedataisessentiallyinstantlyforgottenaboutandnolongerreferenceable.Newdatasimplyoverwritestheolddata,sincethestartofthenextmemoryallocationisalwaysknown,andthere’snoreasontoperformanyclean-upoperations.

Becausedatainthestackisveryshort-lived,thetotalstacksizeisusuallyverysmall;intheorderofMegabytes.It’spossibletocauseastackoverflowbyallocatingmorespacethanthestackcansupport.Thiscanoccurduringexceptionallylargecallstacks(forexample,infiniteloops),orhavingalargenumberoflocalvariables,butinmostcasescausingastackoverflowshouldnotbeaconcerndespiteitsrelativelysmallsize.

Theheaprepresentsallremainingmemoryspace,anditisusedfortheoverwhelming

http://freepdf-books.com

Page 309: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

majorityofdynamicmemoryallocation.Wheneveradatatypeistoobigtofitinthestackormustexistoutsidethefunctionitwasdeclaredin,thenitmustbeallocatedontheheap.Mono’sheapisspecialinthatitismanagedbyaGarbageCollector(itissometimesreferredtoasaManagedHeap).Duringapplicationinitialization,MonowillrequestagivenchunkofmemoryfromtheOSanduseittogeneratetheheap.Theheapstartsofffairlysmall,lessthanoneMegabyte,butwillgrowasnewblocksofmemoryareneededbyourscriptcode.

WecanverifyhowmuchmemoryhasbeenallocatedandreservedfortheheapusingtheMemoryAreaoftheProfiler,butunderthevalueslabeled“Mono”.

WecanalsodeterminethecurrentusedandreservedheapspaceatruntimeusingtheProfiler.GetMonoUsedSize()andProfiler.GetMonoHeapSize()methods,respectively.

Garbagecollection

Whenamemoryrequestismade,andthereisenoughemptyspaceinthereservedheapblocktosatisfytherequest,thenMonoallocatesthespaceandhandsitovertowhoeverrequestedit.But,iftheheapdoesnothaveroomforit,thentheGarbageCollectorwillawakenandscanalltheexistingmemoryallocationsforanythingwhichisnolongerbeingusedandcleansthemupfirst,beforeattemptingtoexpandthecurrentheapspace.

TheGarbageCollectorintheversionofMonothatUnityusesisatypeofTracingGarbageCollector,whichusesaMark-and-Sweepstrategy.Thisalgorithmworksintwophases:eachallocatedobjectistrackedwithanadditionalbit.Thisflagswhethertheobjecthasbeenmarkedornot.Theseflagsstartoffsetto0(orfalse).

Whenthecollectionprocessbegins,itmarks(setstheflagto1ortrue)allobjectsthatarestillreachabletotheprogram.Eitherthereachableobjectisadirectreference,suchasstaticorlocalvariablesonthestack,oritisanindirectreferencethroughthefields(memberdata)ofotherdirectlyorindirectlyaccessibleobjects.Inthisway,itisgatheringasetofobjectsthatarestillreferenceable.

Thesecondphaseinvolvesiteratingthrougheveryobjectreferenceintheheap(whichMonowillhavebeentrackingthroughoutthelifetimeoftheapplication)andverifyingwhetherornottheyaremarked.Ifso,thentheobjectisignored.But,ifitisnotmarked,thenitisacandidatefordeallocation.Duringthisphase,allmarkedobjectsareskippedover,butnotbeforesettingtheirflagbacktofalseforthefirstphaseofthenextgarbagecollection.

Oncethesecondphaseends,allunmarkedobjectsaredeallocatedtofreespace,andthentheinitialrequesttocreatetheobjectisrevisited.Ifthereisenoughspacefortheobject,thenitisallocatedinthatspaceandtheprocessends.But,ifnot,thenitmustallocatea

http://freepdf-books.com

Page 310: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

newblockfortheheapbyrequestingitfromtheOperatingSystem,atwhichpointthememoryallocationrequestcanfinallybecompleted.

Inanidealworld,whereweonlykeepallocatinganddeallocatingobjectsbutonlyafinitenumberofthemexistatonce,theheapwouldmaintainaconstantsizebecausethere’salwaysenoughspacetofittheobject.However,allobjectsinanapplicationarerarelydeallocatedinthesameordertheywereallocated,andevenmorerarelydotheyallhavethesamesizeinmemory.Thisleadstomemoryfragmentation.Memoryfragmentation

Fragmentationoccurswhenobjectsareallocatedanddeallocatedindifferentorders.Thisisbestexplainedthroughanexample.Thefollowingshowsfourstagesofmemoryallocationwithinatypicalheapmemoryspace:

Hereishowthememoryallocationtakesplace:

1. Westartwithanemptyheapspace(1).2. Wethenallocatefourobjectsontheheap,A,B,CandD,eachsizedat64bytes(2).3. Atsomelatertime,wedeallocatetwooftheobjectsAandC(3).4. Thistechnicallyfrees128bytesworthofspace,butsincetheobjectswerenot

contiguous(adjoiningneighbors)inmemory,wehavereallyonlydeallocatedtwoseparate64-byteregionsofmemory.If,atsomepointlater,wewishtoallocateanewobjectthatislargerthan64bytes(4),thenwecannotusethespacethatwaspreviouslyfreedbyobjectsAandC,sinceneitherisindividuallylargeenoughtofitthenewobject(objectsmustalwaysconsumecontiguousmemoryspaces).Therefore,thenewobjectmustbeallocatedinthenextavailable128contiguousbytesintheheapspace.

http://freepdf-books.com

Page 311: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Overtime,ourheapmemorywillbecomeriddledwithmoreandmore,smallerandsmalleremptyspacessuchasthese,asobjectsofdifferentsizesaredeallocated,andthenthesystemlatertriestoallocatenewobjectswithinthesmallestavailablespacethatitcanfitwithin.Thesmallertheseregionsbecome,thelessusabletheyarefornewmemoryallocations.Touseananalogy,thememoryspacebeginstoresembleSwisscheesewithmanysmallholesthatbecomeunusabletous.Intheabsenceofbackgroundtechniquesthatautomaticallycleanupthisfragmentation,thiseffectwouldoccurinliterallyanymemoryspace—RAM,heapspace,andevenharddrives—whicharejustlarger,slower,andmorepermanentmemorystorageareas(thisiswhyit’sagoodideatodefragmentourharddrivesfromtime-to-time!).

Memoryfragmentationcausestwoproblems.Firstly,iteffectivelyreducesthetotalusablememoryspacefornewobjectsoverlongperiodsoftime,dependingonthefrequencyofallocationsanddeallocations.Secondly,itmakesnewallocationstakelongertoresolve,duetotheextratimeittakestofindanewmemoryspacelargeenoughtofittheobject.

Thisbecomesimportantwhennewmemoryallocationsaremadeinaheap,sincewherethefreespacesarelocatedbecomesjustasimportantashowmuchfreespaceisavailable.Evenifwetechnicallyhave128bytesoffreespacetofitanewobject,ifitisnotcontiguousspace,thentheheapmusteithercontinuesearchinguntilitfindsalargeenoughspaceortheentireheapsizemustbeincreasedtofitthenewobject,byrequestinganewmemoryallocationfromtheOSinordertoexpandtheheapspace.Garbagecollectionatruntime

So,inaworstcasescenario,whenanewmemoryallocationisbeingrequestedbyourgame,theCPUwouldhavetospendcyclescompletingthefollowingtasksbeforetheallocationisfinallycompleted:

1. Verifyifthereisenoughcontiguousspaceforthenewobject.2. Ifnot,iteratethroughallknowndirectandindirectreferences,markingthemas

reachable.3. Iteratethroughtheentireheap,flaggingunmarkedobjectsfordeallocation.4. Verifyasecondtimeifthereisenoughcontiguousspaceforthenewobject.5. Ifnot,requestanewmemoryblockfromtheOS,inordertoexpandtheheap.6. Allocatethenewobjectatthefrontofthenewlyallocatedblock.

ThiscanbealotofworkfortheCPUtohandle,particularlyifthisnewmemoryallocationisanimportantgameobjectsuchasaparticleeffect,anewcharacterenteringthescene,acutscenetransition,andsoon.UsersarelikelytonotemomentswheretheGarbageCollectorisfreezinggameplaytohandlethesetasks.Tomakemattersworse,thegarbagecollectionworkloadscalesastheallocatedheapspacegrows,sincesweepingthroughafewmegabytesofspacewillbesignificantlyfasterthanscanningseveralgigabytesofspace.

Allofthismakesitabsolutelycriticaltocontrolourheapspaceintelligently.Thelazierourmemoryusagetacticsare,theworsetheGarbageCollectorwillbehaveinanalmostexponentialfashion.So,it’salittleironicthat,despitetheeffortsofmanagedlanguagesto

http://freepdf-books.com

Page 312: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

solvethememorymanagementproblem,managedlanguagedeveloperscanstillfindthemselvesbeingjustas,ifnotmore,concernedwithmemoryconsumptionthandevelopersofnativeapplications!Threadedgarbagecollection

TheGarbageCollectorrunsontwoseparatethreads:theMainthreadandtheFinalizerthread.WhentheGarbageCollectorisinvoked,itwillrunontheMainthreadandflagheapmemoryblocksforfuturedeallocation.Thisdoesnothappenimmediately.TheFinalizerthread,controlledbyMono,canhaveadelayofseveralsecondsbeforethememoryisfinallyfreedandavailableforreallocation.

WecanobservethisbehaviorintheTotalAllocatedblock(thegreenlinewithapologiestothat5percentofthepopulationwithdeuteranopia/deuteranomaly)oftheMemoryAreawithintheProfiler.Itcantakeseveralsecondsforthetotalallocatedvaluetodropafteragarbagecollectionhasoccurred.Becauseofthedelay,weshouldnotrelyonmemorybeingavailablethemomentithasbeendeallocated,andassuch,weshouldneverwastetimetryingtoekeouteverylastbyteofmemorythatwebelieveshouldbeavailable.Wemustensurethatthereisalwayssomekindofbufferzoneavailableforfutureallocations.

BlocksthathavebeenfreedbytheGarbageCollectormaysometimesbegivenbacktotheOperatingSystemaftersometime,whichwouldreducethereservedspaceconsumedbytheheapandallowthememorytobeallocatedforsomethingelse,suchasanotherapplication.But,thisisveryunpredictableanddependsontheplatformbeingtargeted,soweshouldn’trelyonit.Theonlysafeassumptiontomakeisthat,assoonasthememoryhasbeenallocatedtoMono,it’sthenreservedandisnolongeravailabletoeithertheNativeDomainoranyotherapplicationrunningonthesamesystem.Garbagecollectiontactics

Onestrategytominimizegarbagecollectionproblemsisconcealment;manuallyinvoketheGarbageCollectoratopportunemoments,whentheplayermaynotnotice.Acollectioncanbeinvokedbysimplycallingthefollowingmethod:

System.GC.Collect();

Goodopportunitiestoinvokeacollectionmaybeduringlevelloading,whengameplayispaused,shortlyafteramenuinterfacehasbeenopened,inthemiddleofcutscenetransitions,orreallyanybreakingameplaythattheplayerwouldnotwitness,orcareaboutasuddenperformancedrop.WecouldevenusetheProfiler.GetMonoUsedSize()andProfiler.GetMonoHeapSize()methodsatruntimetodetermineifagarbagecollectionneedstobeinvokedinthenearfuture.

Wecanalsocausethedeallocationofahandfulofspecificobjects.IftheobjectinquestionisoneoftheUnityobjectwrappers,suchasaGameObjectorMonoBehaviourcomponent,thentheFinalizerwillfirstinvoketheDispose()methodwithintheNativeDomain.Atthispoint,thememoryconsumedbyboththeNativeandManagedDomainswillthenbefreed.Insomerareinstances,iftheMonowrapperimplementstheIDisposableinterface(thatis,ithasaDispose()methodavailablefromscriptcode),thenwecanactuallycontrolthisbehaviorandforcethememorytobefreedinstantly.

http://freepdf-books.com

Page 313: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Theonlyknownandusefulcaseofthis(thatthisauthoriscurrentlyawareof)istheWWWclass.ThisclassismostoftenusedtoconnecttoawebserveranddownloadAssetdataduringruntime.ThisclassneedstoallocateseveralbuffersintheNativeDomaininordertoaccomplishthistask.Itneedstomakeroomforthecompressedfile,adecompressionbuffer,andthefinaldecompressedfile.Ifwekeptallofthismemoryforalongtime,itwouldbeacolossalwasteofpreciousspace.So,bycallingitsDispose()methodfromscriptcode,wecanensurethatthememorybuffersarefreedpromptlyandpreciselywhentheyneedtobe.

AllotherAssetobjectsoffersomekindofunloadingmethodtocleanupanyunusedassetdata,suchasResources.UnloadUnusedAssets().ActualassetdataisstoredwithintheNativeDomain,sotheGarbageCollectortechnicallyisn’tinvolvedhere,buttheideaisbasicallythesame.ItwilliteratethroughallAssetsofaparticulartype,checkifthey’renolongerbeingreferenced,and,ifso,deallocatethem.But,again,thisisanasynchronousprocessandwecannotguaranteewhendeallocationwilloccur.ThismethodisautomaticallycalledinternallyafteraSceneisloaded,butthisstilldoesn’tguaranteeinstantdeallocation.

Attheveryleast,Resources.UnloadAsset()(thatis,unloadingonespecificAssetatatime)isthepreferredwaytocleanupAssetdata,sincetimewillnotbespentiteratingthroughtheentirecollection.However,it’sworthnotingthattheseunloadingmethodswereupgradedtobemultithreadedinUnity5,whichimprovestheperformancecostofcleaningupAssetdatarathersignificantlyonmostplatforms.

However,thebeststrategyforgarbagecollectionwillalwaysbeavoidance;ifweallocateaslittleheapmemoryandcontrolitsusageasmuchaspossible,thenwewon’thavetoworryabouttheGarbageCollectorinflictingperformancecostsasfrequentlyorashard.Youwilllearnmanytacticsforthisduringtheremainderofthechapter,butyoushouldfirstcoversometheoryonhowandwherememoryisallocated.

http://freepdf-books.com

Page 314: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ValuetypesandReferencetypesNotallmemoryallocationswemakewithinMonowillgothroughtheheap.The.NETFramework(andbyextensiontheC#language,whichmerelyimplementsthe.NETspecification)hastheconceptofValuetypesandReferencetypes,andonlythelatterofwhichneedstobemarkedbytheGarbageCollectorwhileitisperformingitsMark-and-Sweepalgorithm.Referencetypesareexpectedto(orneedto)lastalongtimeinmemoryeitherduetotheircomplexity,theirsize,orhowthey’reused.Largedatasets,andanykindofobjectinstantiatedfromaclass,isaReferencetype.Thisalsoincludesarrays(whetheritisofValuetypesorReferencetypes),delegates,allclasses,suchasMonoBehaviour,GameObject,andanycustomclasseswedefine.

Valuetypesarenormallyallocatedonthestack.Primitivedatatypessuchasbools,ints,andfloatsareexamplesofValuetypes,butonlyifthey’restandaloneandnotamemberofaReferencetype.AssoonasaprimitivedatatypesiscontainedwithinaReferencetype,suchasaclassoranarray,thenitisimpliedthatitiseithertoolargeforthestackorwillneedtosurvivelongerthanthecurrentscopeandmustbeallocatedontheheapinstead.

Allofthiscanbebestexplainedthroughexamples.ThefollowingcodewillcreateanintegerasaValuetypethatexistsonthestackonlytemporarily:

publicclassTestComponent:MonoBehaviour{

voidStart(){

intdata=5;//allocatedonthestack

DoSomething(data);

}//integerisdeallocatedfromthestackhere

}

AssoonastheStart()methodends,thentheintegerisdeallocatedfromthestack.Thisisessentiallyafreeoperationsince,asmentionedpreviously,itdoesn’tbotherdoinganycleanup;itjustmovesthestackpointerbacktothepreviousmemorylocationinthecallstack.Anyfuturestackallocationssimplyoverwritetheolddata.Mostimportantly,noheapallocationtookplacetocreatethedata,andso,theGarbageCollectorwouldbecompletelyunawareofitsexistence.

But,ifwecreatedanintegerasamembervariableoftheMonoBehaviourclassdefinition,thenitisnowcontainedwithinaReferencetype(aclass)andmustbeallocatedontheheapalongwithitscontainer:

publicclassTestComponent:MonoBehaviour{

privateint_data=5;

voidStart(){

DoSomething(_data);

}

}

Similarly,ifweputtheintegerintoanindependentclass,thentherulesforReferencetypesstillapply,andtheobjectisallocatedontheheap:

http://freepdf-books.com

Page 315: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

publicclassTestData{

publicintdata=5;

}

publicclassTestComponent:MonoBehaviour{

voidStart(){

TestDatadataObj=newTestData();//allocatedontheheap

DoSomething(dataObj.data);

}//'dataObj'isnotdeallocatedhere,butitwillbecomeacandidate

duringthenextgarbagecollection

}

So,thereisabigdifferencebetweentemporarilyallocatingmemorywithinaclassmethodandstoringlong-termdatainaclass’memberdata.Inbothcases,we’reusingaReferencetype(aclass)tostorethedata,whichmeansitcanbereferencedelsewhere.Forexample,imagineDoSomething()storedthereferencetodataObjwithinamembervariable:

privateTestData_testDataObj;

voidDoSomething(TestDatadataObj){

_testDataObj=dataObj;//anewreferencecreated!Thereferenced

objectwillnowbemarkedduringmark-and-sweep

}

Inthiscase,wewouldnotbeabletodeallocatetheobjectpointedtodataObjassoonastheStart()methodendedbecausethetotalnumberofthingsreferencingtheobjectwouldgofrom2to1.Thisisnot0,andhencetheGarbageCollectorwouldstillmarkitduringmark-and-sweep.Wewillalsoneedtoset_testDataObjtonull,ormakeitreferencesomethingelse,beforetheobjectwasnolongerreachable.

NotethataValuetypemusthaveavalue,andcanneverbenull.Ifastack-allocatedValuetypeisassignedtoaReferencetype,thenthedataissimplycopied.ThisistrueevenforarraysoftheValuetypes:

publicclassTestClass{

privateint[]_intArray=newint[1000];//Referencetypefullof

Valuetypes

voidStoreANumber(intnum){

_intArray[0]=num;//storeaValuewithinthearray

}

}

Whentheinitialarrayiscreated(duringobjectinitialization),1,000integerswillbeallocatedontheheapsettoavalueof0.WhentheStoreANumber()methodiscalled,thevalueofnumismerelycopiedintothezerothelementofthearray,ratherthanstoringareferencetoit.

ThesubtlechangeinthereferencingcapabilityiswhatultimatelydecideswhethersomethingisaReferencetypeoraValuetype,andweshouldtrytousestandaloneValuetypeswheneverwehavetheopportunity,sothattheygeneratestackallocationsinsteadofheapallocations.Anysituationwherewe’rejustsendingaroundapieceofdatathatdoesn’tneedtolivelongerthanthecurrentscopeisagoodopportunitytouseaValuetypeinsteadofaReferencetype.Ostensibly,itdoesnotmatterifwepassthedataintoanother

http://freepdf-books.com

Page 316: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

methodofthesameclassoramethodofanotherclass;itstillremainsaValuetypethatwillexistonthestackuntilthemethodthatcreateditgoesoutofthescope.

PassbyvalueandpassbyreferenceTechnically,somethingisduplicatedeverytimeadatavalueispassedasanargumentfromonemethodtoanother,andthisistruewhetheritisaValuetypeoraReferencetype.Thisisknownaspassingbyvalue.ThemaindifferenceisthataReferencetypeismerelyapointerwhichconsumesonly4or8bytesinmemory(32-bitor64-bit,dependingonthearchitecture)regardlessofwhatitisactuallypointingto.WhenaReferencetypeispassedasanargumentitisactuallythevalueofthispointerthatgetscopied,whichisveryquicksincethedataisverysmall.

Meanwhile,aValuetypecontainsthefullandcompletebitsofdatastoredwithintheobject.Hence,allofthedataofaValuetypegetscopiedwhenevertheyarepassedbetweenmethods,orstoredinotherValuetypes.Insomecases,itcanmeanthatpassingalargeValuetypeasargumentsaroundtoomuchcanbemorecostlythanjustusingaReferencetype.FormostValuetypes,thisisnotaproblem,sincetheyarecomparableinsizetoapointer.Butthisbecomesimportantwhenwebegintotalkaboutstructs,inthenextsection.

Datacanbepassedaroundbyreferenceaswell,byusingtherefkeyword,butthisisverydifferentfromtheconceptofValueandReferencetypes,anditisveryimportanttokeepthemdistinctinourmindwhenwetrytounderstandwhatisgoingonunderthehood.WecanpassaValuetypebyvalue,orbyreference,andwecanpassaReferencetypebyvalue,orbyreference.Thismeansthattherearefourdistinctdatapassingsituationsthatcanoccurdependingonwhichtypeisbeingpassedandwhethertherefkeywordisbeingusedornot.

Whendataispassedbyreference(evenifitisaValuetype!)thenmakinganychangestothedatawillchangetheoriginal.Forexample,thefollowingcodewouldprintthevalue10:

voidStart(){

intmyInt=5;

DoSomething(refmyInt);

Debug.Log(String.Format("Value={0}",myInt));

}

voidDoSomething(refintval){

val=10;

}

Removingtherefkeywordfrombothplaceswouldmakeitprintthevalue5instead.Thisunderstandingwillcomeinhandywhenwestarttothinkaboutsomeofthemoreinterestingdatatypeswehaveaccessto.Namely,structs,arrays,andstrings.

StructsareValuetypesStructsareaninterestingspecialcaseinC#.IfwecomefromaC++backgroundtoC#,thenwewouldprobablyassumethattheonlydifferencebetweenastructandaclassis

http://freepdf-books.com

Page 317: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

thatastructhasadefaultaccessspecifier,public,whileaclassdefaultstoprivate.However,inC#,structsaresimilartoclassesinthattheycancontainotherprivate/protected/publicdata,havemethods,canbeinstantiatedatruntime,andsoon.ThecoredifferencebetweenthetwoisthatstructsareValuetypesandclassesareReferencetypes.

TherearesomeotherimportantdifferencesbetweenhowstructsandclassesaretreatedinC#;structsdon’tsupportinheritance,theirpropertiescannotbegivencustomdefaultvalues(memberdataalwaysdefaultstovaluessuchas0ornull,sinceitisaValuetype),andtheirdefaultconstructorscannotbeoverridden.Thisgreatlyrestrictstheirusagecomparedtoclasses,sosimplyreplacingallclasseswithstructs(undertheassumptionthatitwilljustallocateeverythingonthestack)isnotawisecourseofaction.

However,ifwe’reusingaclassinasituationwhoseonlypurposeistosendablobofdatatosomewhereelseinourapplication,anditdoesnotneedtolastbeyondthecurrentscope,thenweshoulduseastructinstead,sinceaclasswouldresultinaheapallocationfornoparticularlygoodreason:

publicclassDamageResult{

publicCharacterattacker;

publicCharacterdefender;

publicinttotalDamageDealt;

publicDamageTypedamageType;

publicintdamageBlocked;

//etc

}

publicvoidDealDamage(Character_target){

DamageResultresult=CombatSystem.Instance.CalculateDamage(this,

_target);

CreateFloatingDamageText(result);

}

Inthisexample,we’reusingaclasstopassabunchofdatafromonesubsystem(thecombatsystem)toanother(theUIsystem).Theonlypurposeofthisdataistobecalculatedandreadbyvarioussubsystems,sothisisagoodcandidatetoconvertintoastruct.

MerelychangingtheDamageResultdefinitionfromaclasstoastructcouldsaveusquiteafewunnecessarygarbagecollections,sinceitwouldbeallocatedonthestack.

publicstructDamageResult{

//...

}

Thisisnotacatch-allsolution.SincestructsareValuetypes,thismeanssomethingratheruniquewhenitispassedasanargumentbetweenmethods.Aswepreviouslylearned,everytimeaValuetypeispassedasanargumentbetweenonefunctionandanother,itwillbeduplicatedsinceitispassedbyvalue.ThiscreatesaduplicateValuetypeforthenextmethodtouse,whichwillbedeallocatedassoonasthatmethodgoesoutofscope,andsooneachtimeitispassedaround.So,ifastructispassedbyvaluebetweenfivedifferent

http://freepdf-books.com

Page 318: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

methodsinalongchain,thenfivedifferentstackcopieswilloccuratthesametime.Recallthatstackdeallocationsarefree,butdatacopyingisnot.

Thecopyingisprettymuchnegligibleforsmallvalues,suchasasingleintegerorfloat,butpassingaroundridiculouslylargedatasetsthroughstructsoverandoveragainisobviouslynotatrivialtaskandshouldbeavoided.Insuchcases,itwouldbewisertopassthestructbyreferenceusingtherefkeywordtominimizetheamountofdatabeingcopiedeachtime(justa32-bitor64-bitintegerforthememoryreference).However,thiscanbedangeroussincepassingbyreferenceallowsanysubsequentmethodstomakechangestothestruct,inwhichcaseitwouldbeprudenttomakeitsdatavaluesreadonly(itcanonlybeinitializedintheconstructor,andneveragain,evenbyitsownmemberfunctions)topreventlaterchanges.

AlloftheaboveisalsotruewhenstructsarecontainedwithinReferencetypes:

publicstructDataStruct{

publicintval;

}

publicclassStructHolder{

publicDataStruct_memberStruct;

publicvoidStoreStruct(DataStructds){

_memberStruct=ds;

}

}

Totheuntrainedeye,theprecedingcodeappearstobeattemptingtostoreastack-allocatedstructwithinaReferencetype.DoesthismeanthataStructHolderobjectontheheapcannowreferenceanobjectonthestack?WhatwillhappenwhentheStoreStruct()methodgoesoutofscopeandthestructiserased?Itturnsoutthatthesearethewrongquestions.

What’sactuallyhappeningisthat,whileaDataStructobject(_memberStruct)hasbeenallocatedontheheapwithintheStructHolderobject,itisstillaValuetypeanddoesnotmagicallytransformintoaReferencetype.So,alloftheusualrulesforValuetypesapply.The_memberStructvariablecannothaveavalueofnullandallofitsfieldswillbeinitializedto0ornullvalues.WhenStoreStruct()iscalled,thedatafromdswillbecopiedinto_memberStruct.Therearenoreferencestostackobjectstakingplace,andthereisnoconcernaboutlostdata.

ArraysareReferencetypesArrayscanpotentiallycontainahugeamountofdatawithinthem,whichmakethemdifficulttotreatasaValuetypesincethere’sprobablynotenoughroomonthestacktosupportthem.Therefore,theyaretreatedasaReferencetypesothattheentiredatasetcanbepassedaroundviaasinglereference,insteadofduplicatingtheentirearrayeverytimeitispassedaround.ThisistrueirrespectiveofwhetherthearraycontainsValuetypesorReferencetypes.

Thismeansthatthefollowingcodewillresultinaheapallocation:

TestStruct[]dataObj=newTestStruct[1000];

http://freepdf-books.com

Page 319: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

for(inti=0;i<1000;++i){

dataObj[i].data=i;

DoSomething(dataObj[i]);

}

Thefollowing,functionallyequivalentcode,wouldnotresultinanyheapallocations,sincethestructsareValuetypes,andhencewouldbecreatedonthestack:

for(inti=0;i<1000;++i){

TestStructdataObj=newTestStruct();

dataObj.data=i;

DoSomething(dataObj);

}

Thesubtledifferenceinthesecondcode-blockisthatonlyoneTestStructexistsonthestackatatime(atleastforthisfunctionDoSomething()canpotentiallycreatemore),whereasthefirstblockneedstoallocate1,000ofthemviaanarray.Obviously,thesemethodsarekindofridiculousasthey’rewritten,buttheyillustrateanimportantpointtoconsider.Thecompilerisn’tsmartenoughtoautomaticallyfindthesesituationsforusandmaketheappropriatechanges.OpportunitiestooptimizeourmemoryusagethroughValuetypereplacementswillbeentirelydowntoourabilitytodetectthem,andunderstandwhyachangewillresultinstackallocations,ratherthanheapallocations.

Notethat,whenweallocateanarrayofReferencetypes,we’recreatinganarrayofreferences,whichcaneachreferenceotherlocationsontheheap.However,whenweallocateanarrayofValuetypes,we’recreatingapackedlistofValuetypesontheheap.EachoftheseValuetypeswillbeinitializedwithavalueof0(orequivalent),sincetheycannotbenull,whileeachreferencewithinanarrayofReferencetypeswillalwaysinitializetonull,sincenoreferenceshavebeenassigned,yet.

StringsareimmutableReferencetypesWebrieflytoucheduponthesubjectofstringsbackinChapter2,ScriptingStrategies,butnowit’stimetogointomoredetailaboutwhyproperstringusageisextremelyimportant.

Becausestringsareessentiallyarraysofcharacters(chars),theyareReferencetypes,andfollowallofthesamerulesasotherReferencetypes;thevaluethatisactuallycopiedandpassedbetweenfunctionsismerelyapointer,andtheywillbeallocatedontheheap.

Theconfusingpartreallybeginswhenwediscoverthatstringsareimmutable,meaningtheycannotbechangedafterthey’vebeenallocated.Beinganarrayimpliesthattheentirelistofcharactersmustbecontiguousinmemory,whichcannotbetrueifweallowedstringstoexpandorcontractat-willwithinadynamicmemoryspace(howcouldwequicklyandsafelyexpandthestringifwe’veallocatedsomethingelseimmediatelyafterit?).

Thismeansthat,ifastringismodified,thenanewstringmustbeallocatedtoreplaceit,wherethecontentsoftheoriginalwillbecopiedandmodifiedas-neededintoawholenewcharacterarray.Inwhichcase,theoldversionwillnolongerbereferencedanywhere,willnotbemarkedduringmark-and-sweepandwillthereforeeventuallybegarbage-collected.Asaresult,lazystringprogrammingcanresultinalotofunnecessaryheapallocations

http://freepdf-books.com

Page 320: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

andgarbagecollection.

Forexample,ifwebelievedthatstringsworkedjustlikeotherReferencetypes,wemightbeforgivenforassumingthelogoutputofthefollowingtobeWorld!:

voidStart(){

stringtestString="Hello";

DoSomething(testString);

Debug.Log(testString);

}

voidDoSomething(stringlocalString){

localString="World!";

}

However,thisisnotthecase,anditwillstillprintoutHello.WhatisactuallyhappeningisthatthelocalStringvariable,withinthescopeofDoSomething(),startsoffreferencingthesameplaceinmemoryastestString,duetothereferencebeingpassedbyvalue.ThisgivesustworeferencespointingtothesamelocationinmemoryaswewouldexpectifweweredealingwithanyotherReferencetype.Sofar,sogood.

But,assoonaswechangethevalueoflocalString,werunintoalittlebitofaconflict.Stringsareimmutable,andwecannotchangethem,sothereforewemustallocateanewstringcontainingthevalueWorld!andassignitsreferencetothevalueoflocalString;nowthenumberofreferencestotheHellostringreturnsbacktoone.Theoriginalstring(Hello)willremaininmemorybecausethevalueoftestStringhasnotbeenchanged,andthatisstillthevaluewhichwillbeprintedbyDebug.Log().Allwe’vesucceededindoingbycallingDoSomething()iscreatinganewstringontheheapwhichgetsgarbage-collected,anddoesn’tchangeanything.Thisisthetextbookdefinitionofwasteful.

IfwechangethemethoddefinitionofDoSomething()topassthestringbyreference,viatherefkeyword,theoutputwouldindeedchangetoWorld!.ThisiswhatwewouldexpecttohappenwithaValuetype,whichleadsalotofdeveloperstoincorrectlyassumethatstringsareValuetypes.But,thisisanexampleofthefourthandfinaldata-passingcasewhereaReferencetypeisbeingpassedbyreference,whichallowsustochangewhattheoriginalreferenceisreferencing!

NoteSo,torecap;ifwepassaValuetypebyvalue,wecanonlychangethevalueofthecopy.IfwepassaValuetypebyreference,wecanchangetheactualvalueattributedtotheoriginalversion.IfwepassaReferencetypebyvalue,wecanmakechangestotheobjectthattheoriginalreferenceisreferencing.Andfinally,ifwepassaReferencetypebyreference,wecanchangewhichobjecttheoriginalreferenceisreferencing.

Stringconcatenation

Concatenationistheactofappendingstringstooneanothertoformalargerstring.Aswe’velearned,anysuchcasesarelikelytoresultinexcessheapallocations.Thebiggestoffenderinstring-basedmemorywasteisconcatenatingstringsusingthe+and+=operators,becauseoftheallocationchainingeffecttheycause.

http://freepdf-books.com

Page 321: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Forexample,thefollowingcodetriestocombineagroupofstringstogethertoprintsomeinformationaboutacombatresult:

voidCreateFloatingDamageText(DamageResultresult){

stringoutputText=result.attacker.GetCharacterName()+"dealt"+

result.totalDamageDealt.ToString()+""+result.damageType.ToString()+"

damageto"+result.defender.GetCharacterName()+"("+

result.damageBlocked.ToString()+"blocked)";

//...

}

Anexampleoutputofthisfunctionmightbeastringthatreads:

Dwarfdealt15SlashingdamagetoOrc(3blocked)

Thisfunctionfeaturesahandfulofstringliterals(hard-codedstringsthatareallocatedduringapplicationinitialization)suchasdealt,damageto,andblocked.But,becauseoftheusageofvariableswithinthiscombinedstring,itcannotbecompiledawayatbuildtime,andthereforemustbegenerateddynamicallyatruntime.

Anewheapallocationwillbegeneratedeachtimea+,or+=,operatorisexecuted;onlyasinglepairofstringswillbemergedatatime,anditallocatesanewstringeachtime.Then,theresultofonemergerwillbefedintothenext,andmergedwithanotherstring,andsoonuntiltheentirestringhasbeenbuilt.

So,thepreviousexamplewillresultin9differentstringsbeingallocatedallinonego.Allofthefollowingstringswouldbeallocatedtosatisfythisinstruction,andallwouldeventuallyneedtobegarbagecollected(notethattheoperatorsareresolvedfromright-to-left):

"3blocked)"

"(3blocked)"

"Orc(3blocked)"

"damagetoOrc(3blocked)"

"SlashingdamagetoOrc(3blocked)"

"SlashingdamagetoOrc(3blocked)"

"15SlashingdamagetoOrc(3blocked)"

"dealt15SlashingdamagetoOrc(3blocked)"

"Dwarfdealt15SlashingdamagetoOrc(3blocked)"

That’s262charactersbeingused,insteadof49;orbecauseacharisa2-bytedatatype,that’s524bytesofdatabeingallocatedwhenweonlyneed98bytes.Chancesarethat,ifthiscodeexistsinthecodebaseonce,thenitexistsallovertheplace,soforanapplicationthat’sdoingalotoflazystringconcatenationlikethis,thatisatonofmemorybeingwastedongeneratingunnecessarystrings.

TipNotethatbig,constantstringliteralscanbesafelycombinedusingthe+and+=operatorstomakethemmorereadablewithinthecodebase,butonlyiftheywillresultinaconstantstring.Ifso,thecompilerwilltakecareofmergingallofthestringliteralstogetheratcompiletime.

http://freepdf-books.com

Page 322: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

BetterapproachesforgeneratingstringsaretouseeithertheStringBuilderclass,oroneofseveralstringclassmethods.

TheStringBuilderclassiseffectivelyamutable(changeable)stringclass.Itworksbyallocatingabuffertocopythetargetstringsintoandallocatesadditionalspacewheneveritisneeded.WecanretrievethestringusingtheToString()methodwhich,naturally,resultsinamemoryallocationfortheresultantstring,butatleastweavoidedalloftheunnecessarystringallocationswewouldhavegeneratedusingthe+or+=operators.

Conventionalwisdomsaysthatifweroughlyknowthefinalsizeoftheresultantstring,thenwecanallocateanappropriatebufferaheadoftimeandsaveourselvesundueallocations.Forourexampleabove,wemightallocateabufferof100characterstomakeroomforlongcharacternamesanddamagevalues:

usingSystem.Text;

//...

StringBuildersb=newStringBuilder(100);

sb.Append(result.attacker.GetCharacterName());

sb.Append("dealt");

sb.Append(result.totalDamageDealt.ToString());

//etc…

stringresult=sb.ToString();

Ifwedon’tknowthefinalsize,thenusingaStringBuilderclassislikelytogenerateabufferthatdoesn’tfitthesizeexactly,orclosely.Wewilleitherendupwithabufferthat’stoolarge(wastedallocationtimeandspace),or,worse,abufferthat’stoosmall,whichmustkeepexpandingaswegeneratethecompletestring.Ifwe’reunsureaboutthetotalsizeofthestring,thenitmightbebesttouseoneofthevariousstringclassmethods.

Therearethreestringclassmethodsavailableforgeneratingstrings;Format(),Join(),andConcat().Eachoperatesslightlydifferently,buttheoveralloutputisthesame;anewstringisallocatedcontainingthecontentsofthestring(s)wepassintothem,anditisalldoneinasingleactionwhichreducesexcessstringallocations.

Itissurprisinglyhardtosaywhichoneofthetwoapproacheswouldbemorebeneficialinagivensituationastherearealotofreallydeepnuancesinvolved.There’salotofdiscussionsurroundingthetopic(justdoaGooglesearchfor"csharpstringconcatenationperformance"andyou’llseewhatImean),sothebestapproachistoimplementoneortheotherusingtheconventionalwisdomdescribedpreviously.Wheneverwerunintobadperformancewithonemethod,weshouldtrytheother,profilethemboth,andpickthebestoptionofthetwo.

BoxingTechnically,everythinginC#isanobject(caveatsapply).Evenprimitivedatatypessuchasints,floats,andboolsarederivedfromSystem.Objectattheirlowestlevel(aReferenceType!),whichallowsthemaccesstohelpermethodssuchasToString(),sothattheycancustomizetheirstringrepresentation.

ButtheseprimitivetypesaretreatedasspecialcasesviabeingtreatedasValuetypes.WheneveraValuetypeisimplicitlytreatedinsuchawaythatitmustactlikeanobject,

http://freepdf-books.com

Page 323: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

theCLRautomaticallycreatesatemporaryobjecttostore,or“box”,thevalueinsidesothatitcanbetreatedasatypicalReferencetypeobject.Asweshouldexpect,thisresultsinaheapallocationtocreatethecontainingvessel.

TipNotethatboxingisnotthesamethingasusingValuetypesasmembervariablesofReferencetypes.ItonlytakesplacewhenValuetypesaretreatedlikeobjectsthemselves.

Forexample,thefollowingcodewouldcausethevariableitobeboxedinsideobjectobj:

inti=128;

objectobj=i;

Thefollowingwouldusetheobjectrepresentationobjtoreplacethevaluestoredwithintheinteger,and“unbox”itbackintoaninteger,storingitini.Thefinalvalueofiwouldbe256:

obj=256;

i=(int)obj;

Thesetypescantechnicallybechangeddynamically.ThefollowingisperfectlylegalC#code,whichusesthesameobjectobjasabove,whichwasoriginallyboxedfromanint:

obj=512f;

floatf=(float)obj;

Thefollowingisalsolegal:

obj=false;

boolb=(bool)obj;

Notethatattemptingtounboxobjintoatypethatisn’tthemostrecentlyassignedtypewouldresultinanInvalidCastException.Allofthiscanbealittletrickytowrapourheadarounduntilwerememberthat,attheendoftheday,everythingisjustbitsinmemory.What’simportantisknowingthatwecantreatourprimitivetypesasobjectsbyboxingthem,convertingtheirtypes,andthenunboxingthemintoadifferenttypeatalatertime.

NoteNotethatit’spossibletoconvertaboxedobject’stypeusingoneofthemanySystem.Convert.To…()methods.

Boxingcanbeeitherimplicit,aspertheexamplesabove,orexplicit,bytypecastingtoSystem.Object.Unboxingmustalwaysbeexplicitbytypecastingbacktoitsoriginaltype.WheneverwepassaValuetypeintoamethodwhichusesSystem.Objectasarguments,boxingwillbeappliedimplicitly.

MethodssuchasString.Format(),whichtakeSystem.Objectsasarguments,areonesuchexample.WetypicallyusethembypassinginValuetypessuchasints,floats,boolsandsoon,togenerateastringwith.Boxingisautomaticallytakingplaceinthesesituations,causingadditionalheapallocationswhichweshouldbeawareof.

http://freepdf-books.com

Page 324: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Collections.Generic.ArrayListisanothersuchexample,sinceArrayListsalwayscontainSystem.Objectreferences.

AnytimeweuseafunctiondefinitionthattakesSystem.Objectasarguments,andwe’repassinginValuetypes,weshouldbeawarethatwe’reimplicitlycausingheapallocationsduetoboxing.

http://freepdf-books.com

Page 325: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheimportanceofdatalayoutTheimportanceofhowourdataisorganizedinmemorycanbesurprisinglyeasytoforgetabout,butcanresultinafairlybigperformanceboostifitishandledproperly.Cachemissesshouldbeavoidedwheneverpossible,whichmeansthatinmostcases,arraysofdatathatarecontiguousinmemoryshouldbeiteratedoversequentially,asopposedtoanyotheriterationstyle.

Thismeansthatdatalayoutisalsoimportantforgarbagecollection,sinceitisdoneinaniterativefashion,andifwecanfindwaystohavetheGarbageCollectorskipoverproblematicareas,thenwecanpotentiallysavealotofiterationtime.

Inessence,wewanttokeeplargegroupsofReferencetypesseparatedfromlargegroupsofValuetypes.IfthereisevenjustoneReferencetypewithinaValuetype,suchasastruct,thentheGarbageCollectorconsiderstheentireobject,andallofitsdatamembers,indirectlyreferenceableobjects.Whenitcomestimetomark-and-sweep,itmustverifyallfieldsoftheobjectbeforemovingon.But,ifweseparatethevarioustypesintodifferentarrays,thenwecanmaketheGarbageCollectorskipthemajorityofthedata.

Forinstance,ifwehaveanarrayofstructscontainingdatalikeso,thentheGarbageCollectorwillneedtoiterateovereverymemberofeverystruct,whichcouldbefairlytimeconsuming:

publicstructMyStruct{

intmyInt;

floatmyFloat;

boolmyBool;

stringmyString;

}

MyStruct[]arrayOfStructs=newMyStruct[1000];

But,ifwereplaceallofthisdatawithsimplearrays,thentheGarbageCollectorwillignorealloftheprimitivedatatypes,andonlycheckthestrings.Thiswouldresultinmuchafastergarbagecollectionsweep:

int[]myInts=newint[1000];

float[]myFloats=newfloat[1000];

bool[]myBools=newbool[1000];

string[]myStrings=newstring[1000];

Thereasonthisworksisbecausewe’regivingtheGarbageCollectorfewerindirectreferencestocheck.Whenthedataissplitintoseparatearrays(Referencetypes),itfindsthreearraysofValuetypes,marksthearrays,andthenimmediatelymovesonbecausethere’snoreasontomarkValuetypes.Itmuststilliteratethroughallofthestringswithinthestringarray,sinceeachisaReferencetypeanditneedstoverifythattherearenoindirectreferenceswithinit.Technically,stringscannotcontainindirectreferences,buttheGarbageCollectorworksatalevelwhereitonlyknowsiftheobjectisaReferencetypeorValuetype.However,wehavestillsparedtheGarbageCollectorfromneedingtoiterateoveranextra3,000piecesofdata(all1,000ints,floats,andbools).

http://freepdf-books.com

Page 326: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheUnityAPIThereareseveralinstructionswithintheUnityAPIwhichresultinheapmemoryallocations,whichweshouldbeawareof.Thisessentiallyincludeseverythingthatreturnsanarrayofdata.Forexample,thefollowingmethodsallocatememoryontheheap:

GetComponents<T>();//(T[])

Mesh.vertices;//(Vector3[])

Camera.allCameras;//(Camera[])

Suchmethodsshouldbeavoidedwheneverpossible,orattheveryleastcalledonceandcachedsothatwedon’tcausememoryallocationsmoreoftenthannecessary.

NotethatUnityTechnologieshashinteditmightcomeoutwithallocation-lessversionsofthesemethodssometimeinthelifecycleofUnity5.Presumably,itmightlooksomethinglikethewayParticleSystemsallowsaccesstoParticledata,whichinvolvesprovidingaParticle[]arrayreferencetopointtotherequireddata.Thisavoidsallocationsincewereusethesamebufferbetweencalls.

http://freepdf-books.com

Page 327: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheforeachloopsTheforeachloopkeywordisabitofacontroversialissueinUnitydevelopmentcircles.ItturnsoutthatalotofforeachloopsimplementedinUnityC#codewillincurunnecessaryheapmemoryallocationsduringthesecalls,astheyallocateanEnumeratorobjectasaclassontheheap,insteadofastructonthestack.Italldependsonthegivencollection’simplementationoftheGetEnumerator()method.

ItturnsoutthateverysinglecollectionthathasbeenimplementedintheversionofMonothatcomeswithUnity(Monoversion2.6.5)willcreateclassesinsteadofstructs,whichresultsinheapallocations.Thisincludes,butisnotlimitedto,List<T>,LinkedList<T>,Dictionary<K,V>,ArrayList,andsoon.But,notethatitisactuallysafetouseforeachloopsontypicalarrays!TheMonocompilersecretlyconvertsforeachoverarraysintosimpleforloops.

Thecostisfairlynegligibleastheheapallocationcostdoesnotscalewiththenumberofiterations.OnlyoneEnumeratorobjectisallocated,andreusedoverandoveragain,whichonlycostsahandfulofbytesofmemoryoverall.Sounlessourforeachloopsarebeinginvokedeveryupdate(whichistypicallydangerousinandofitself)thenthecostswillbemostlynegligibleonsmallprojects.Thetimetakentoconverteverythingtoaforloopmaynotbeworththetime.Butit’sdefinitelysomethingtokeepinmindforthenextprojectwebegintowrite.

Ifwe’reparticularlysavvywithC#,VisualStudio,andmanualcompilationoftheMonoassembly,thenwecanhaveVisualStudioperformcodecompilationforus,andcopytheresultingassemblyDLLintotheAssetsfolder,whichwillfixthismistakeforthegenericcollections.

NotethatperformingforeachoveraTransformComponentisatypicalshortcuttoiteratingoveraTransform’schildren.Forexample:

foreach(Transformchildintransform){

//dostuffwith'child'

}

However,thisresultsinthesameheapallocationsmentionedabove.Asaresult,thatcodingstyleshouldbeavoidedinfavorofthefollowing:

for(inti=0;i<transform.childCount;++i){

Transformchild=transform.GetChild(i);

//dostuffwith'child'

}

http://freepdf-books.com

Page 328: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

CoroutinesStartingaCoroutinecostsasmallamountofmemorytobeginwith,butnotethatnofurthercostsareincurredwhenthemethodyields.Ifmemoryconsumptionandgarbagecollectionaresignificantconcerns,weshouldtrytoavoidhavingtoomanyshort-livedCoroutines,andavoidcallingStartCoroutine()toomuchduringruntime.

http://freepdf-books.com

Page 329: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ClosuresClosuresareuseful,butdangeroustools.AnonymousmethodsandlambdaexpressionsarenotalwaysClosures,buttheycanbe.Italldependsonwhetherthemethodusesdataoutsideofitsownscopeandparameterlist,ornot.

Forexample,thefollowinganonymousfunctionwouldnotbeaClosure,sinceitisself-containedandfunctionallyequivalenttoanyotherlocallydefinedfunction:

System.Func<int,int>anon=(x)=>{returnx;};

intresult=anon(5);

But,iftheanonymousfunctionpulledindatafromoutsideitself,thenitbecomesaClosure,asit“closestheenvironment”aroundtherequireddata.ThefollowingwouldresultinaClosure:

inti=1024;

System.Func<int,int>anon=(x)=>{returnx+i;};

intresult=anon(5);

Inordertocompletethistransaction,thecompilermustdefineanewclassthatcanreferencetheenvironmentwherethedatavalueiwouldbeaccessible.Atruntimeitcreatesthecorrespondingobjectontheheapandprovidesittotheanonymousfunction.NotethatthisincludesValuetypes(aspertheaboveexample),whichwereoriginallyonthestack,possiblydefeatingthepurposeofthembeingallocatedonthestackinthefirstplace.So,weshouldexpecteachinvocationofthesecondmethodtoresultinheapallocationsandinevitablegarbagecollection.

http://freepdf-books.com

Page 330: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

.NETlibraryfunctionsThe.NETlibraryoffersahugeamountofcommonfunctionalitythathelpssolvenumerousproblemsthatprogrammersmaycomeacrossduringday-to-dayimplementation.Mostoftheseclassesandfunctionsareoptimizedforgeneralusecases,whichmaynotbeoptimalforaspecificsituation.Itmaybepossibletoreplaceaparticular.NETlibraryclasswithacustomimplementationthatismoresuitedtoourspecificusecase.

Therearealsotwobigfeaturesinthe.NETlibrarythatoftenbecomebigperformancehogswheneverthey’reused.Thistendstobebecausetheyareonlyincludedasaquick-and-hackysolutiontoagivenproblemwithoutmucheffortputintooptimization.ThesefeaturesareLINQandRegularExpressions.

LINQprovidesawaytotreatarraysofdataasminiaturedatabasesandperformqueriesagainstthemusingSQL-likesyntax.Thesimplicityofitscodingstyle,andcomplexityoftheunderlyingsystem(throughitsusageofClosures),impliesthatithasafairlylargeoverheadcost.LINQisahandytool,butisnotreallyintendedforhigh-performance,real-timeapplicationssuchasgames,anddoesnotevenfunctiononplatformsthatdonotsupportJITcompilation,suchasiOS.

Meanwhile,RegularExpressions,usingtheRegexclass,allowustoperformcomplexstringparsingtofindsubstringsthatmatchaparticularformat,replacepiecesofastring,orconstructstringsfromvariousinputs.RegularExpressionisanotherveryusefultool,buttendstobeoverusedinplaceswhereitislargelyunnecessary,orinseemingly“clever”waystoimplementafeaturesuchastextlocalization,whenstraightforwardstringreplacementwouldbefarmoreefficient.

Specificoptimizationsforbothofthesefeaturesgofarbeyondthescopeofthisbook,astheycouldfillentirevolumesbythemselves.Weshouldeithertrytominimizetheirusageasmuchaspossible,replacetheirusagewithsomethinglesscostly,bringinaLINQorRegexexperttosolvetheproblemforus,ordosomeGooglingonthesubjecttooptimizehowwe’reusingthem.

TipOneofthebestwaystofindthecorrectansweronlineistosimplypostthewronganswer!Peoplewilleitherhelpusoutofkindness,ortakesuchgreatoffensetoourimplementationthattheyconsiderittheircivicdutytocorrectus!Justbesuretodosomekindofresearchonthesubjectfirst.Eventhebusiestofpeoplearegenerallyhappytohelpiftheycanseethatwe’veputinourfairshareofeffortbeforehand.

http://freepdf-books.com

Page 331: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TemporaryworkbuffersIfwegetintothehabitofusinglarge,temporaryworkbuffersforonetaskoranother,thenitjustmakessensethatweshouldlookforopportunitiestoreusethem,insteadofreallocatingthemoverandoveragain,asthislowerstheoverheadinvolvedinallocation,aswellasgarbagecollection(so-called“memorypressure”).Itmightbeworthwhiletoextractsuchfunctionalityfromcase-specificclassesintoagenericgodclassthatcontainsabigworkareaformultipleclassestoreuse.

http://freepdf-books.com

Page 332: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ObjectpoolingSpeakingoftemporaryworkbuffers,objectpoolingisanexcellentwayofbothminimizingandestablishingcontroloverourmemoryusagebyavoidingdeallocationandreallocation.Theideaistoformulateourownsystemforobjectcreation,whichhidesawaywhethertheobjectwe’regettinghasbeenfreshlyallocatedorhasbeenrecycledfromanearlierallocation.Thetypicaltermstodescribethisprocessareto“spawn”and“despawn”theobject,ratherthancreatinganddeletingthem,sinceanytimeanobjectisdespawnedwe’resimplyhidingitfromviewuntilweneeditagain,atwhichpointitisrespawnedandreused.

Let’scoveraquickimplementationofanobjectpoolingsystem.

Thefirstrequirementistoallowthepooledobjecttodecidehowtorecycleitselfwhenthetimecomes.Thefollowinginterfacewillsatisfytherequirementsnicely:

publicinterfaceIPoolableObject{

voidNew();

voidRespawn();

}

Thisinterfacedefinestwomethods;New()andRespawn().Theseshouldbecalledwhentheobjectisfirstcreated,andwhenithasbeenrespawned,respectively.

Thesecondrequirementistoprovideabaseimplementationofthisinterfacethatallowsobjectsofanytypetohandleanybookkeepingrequiredtotakecareoftheinitialcreationandrespawningofobjects.

ThefollowingObjectPoolclassdefinitionisafairlysimpleimplementationoftheobjectpoolingconcept.Itusesgenericstosupportanyobjecttypesolongasitfitstwocriteria;itmustimplementtheIPoolableObjectinterface,andmustallowforaparameter-lessconstructor(thenew()keywordintheclassdeclaration).

publicclassObjectPool<T>whereT:IPoolableObject,new(){

privateStack<T>_pool;

privateint_currentIndex=0;

publicObjectPool(intinitialCapacity){

_pool=newStack<T>(initialCapacity);

for(inti=0;i<initialCapacity;++i){

Spawn();//instantiateapoolofNobjects

}

Reset();

}

publicintCount{

get{return_pool.Count;}

}

publicvoidReset(){

_currentIndex=0;

}

publicTSpawn(){

if(_currentIndex<Count){

Tobj=_pool.Pop();

http://freepdf-books.com

Page 333: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

_currentIndex++;

IPoolableObjectip=objasIPoolableObject;

ip.Respawn();

returnobj;

}else{

Tobj=newT();

_pool.Push(obj);

_currentIndex++;

IPoolableObjectip=objasIPoolableObject;

ip.New();

returnobj;

}

}

}

AnexamplePoolableobjectwouldlooklikeso.Itmustimplementtwopublicmethods,New()andRespawn(),whichareinvokedbytheObjectPoolclassattheappropriatetimes:

publicclassTestObject:IPoolableObject{

publicvoidNew(){

//veryfirstinitializationhere

}

publicvoidRespawn(){

//resetdatawhichallowstheobjecttoberecycledhere

}

}

Andfinally,anexampleusagetocreateapoolof100TestObjectobjects:

privateObjectPool<TestObject>_objectPool=newObjectPool<TestObject>

(100);

Thefirst100callstoSpawn()onthe_objectPoolobjectwillcausetheobjectstoberespawnedandprovidedtothecaller.Ifthestackrunsoutofspace,thenitwilladdevenmoreTestObjectobjectstothestack.Finally,ifReset()iscalledon_objectPool,thenitwillbeginagainfromthestart,recyclingobjectsandprovidingthemtothecaller.

Notethatthispoolingsolutionwillnotworkforclasseswehaven’tdefined,andcannotderivefrom,suchasVector3,andQuaternion.Inthesecases,wewouldneedtodefineacontainingclass:

publicclassPoolableVector3:IPoolableObject{

publicVector3vector=newVector3();

publicvoidNew(){

Reset();

}

publicvoidRespawn(){

Reset();

http://freepdf-books.com

Page 334: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

publicvoidReset(){

vector.x=vector.y=vector.z=0f;

}

}

Wecouldextendthissysteminanumberofways,suchasdefiningaDespawn()methodtohandledestructionoftheobject,makinguseoftheIDisposableinterfaceandusingblockswhenwewishtoautomaticallyspawnanddespawnobjectswithinasmallscope,and/orallowingobjectsinstantiatedoutsidethepooltobeaddedtoit.

http://freepdf-books.com

Page 335: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 336: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PrefabpoolingThepreviouspoolingsolutionisusefulfortypicalclasses,butitwon’tworkforspecialUnityobjects,suchasGameObjectandMonoBehaviour.Theseobjectstendtoconsumealargechunkofourruntimememory,cancostusagreatdealofCPUusagewhenthey’recreatedanddestroyed,andtendtoriskalargeamountofgarbagecollectionatruntime.Inotherwords,themaingoalofPrefabpoolingistopushtheoverwhelmingmajorityofobjectinstantiationtoSceneinitialization,ratherthanlettingthemgetcreatedatruntime.ThiscanprovidesomebigruntimeCPUsavings,andavoidsalotofspikescausedbyobjectcreation/destructionandgarbagecollection,attheexpenseofSceneloadingtimes,andruntimememoryconsumption.Asaresult,therearequiteafewpoolingsolutionsavailableontheAssetStoreforhandlingthistask,withvaryingdegreesofsimplicity,quality,andfeaturesets.

NoteItisoftenrecommendedthatpoolingshouldbeimplementedinanygamethatintendstodeployonmobiledevices,duetothegreateroverheadcostsinvolvedintheallocationanddeallocationofmemorycomparedtodesktopapplications.

However,creatingapoolingsolutionisaninterestingtopic,andbuildingonefromscratchisagreatwayofgettingtogripswithalotofimportantinternalUnityEnginebehavior.Also,knowinghowsuchasystemisbuiltmakesiteasiertoextendifwewishittomeettheneedsofourparticulargame,ratherthanrelyingonaprebuiltsolution.

ThegeneralideaofPrefabpoolingistocreateasystemthatcontainslistsofactiveandinactiveGameObjectsthatwereallinstantiatedfromthesamePrefabreference.Thefollowingdiagramshowshowthesystemmightlookafterseveralspawns,despawns,andrespawnsofvariousobjectsderivedfromfourdifferentPrefabs(Orc,Troll,Ogre,andDragon):

http://freepdf-books.com

Page 337: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

NoteNotethattheHeapMemoryarearepresentstheobjectsastheyexistinmemory,whilethePoolingSystemarearepresentsreferencestothoseobjects.

Inthisexample,severalinstancesofeachPrefabwereinstantiated(11Orcs,8Trolls,5Ogres,and1Dragon).Currentlyonlyelevenoftheseobjectsareactive,whiletheotherfourteenhavepreviouslybeendespawned,andareinactive.Notethatthedespawnedobjectsstillexistinmemory,althoughtheyarenotvisibleandcannotinteractwiththegameworlduntiltheyhavebeenrespawned.Naturally,thiscostsusaconstantamountofheapmemoryatruntimeinordertomaintaintheinactiveobjects,butwhenanewobjectisinstantiated,wecanreuseoneoftheexistinginactiveobjects,ratherthanallocatingmorememoryinordertosatisfytherequest.ThissavessignificantruntimeCPUcostsduringobjectcreationanddestruction,andavoidsgarbagecollection.

ThefollowingdiagramshowsthechainofeventsthatneedstooccurwhenanewOrcisspawned:

ThefirstobjectintheInactiveOrcpool(Orc7)isreactivatedandmovedintotheActivepool.Wenowhave6activeOrcs,and5inactiveOrcs.

ThefollowingfigureshowstheorderofeventswhenanOgreobjectisdespawned:

http://freepdf-books.com

Page 338: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThistimetheobjectisdeactivatedandmovedfromtheActivepoolintotheInactivepool,leavinguswith1activeOgreand4inactiveOgres.

Finally,thefollowingdiagramshowswhathappenswhenanewobjectisspawned,buttherearenoinactiveobjectstosatisfytherequest:

Inthisscenario,morememorymustbeallocatedtoinstantiatethenewDragonobject,sincetherearenoDragonobjectsinitsInactivepooltoreuse.Therefore,inordertoavoidruntimememoryallocationsforourGameObjects,itiscriticalthatweknowbeforehandhowmanywewillneed.Thiswillvarydependingonthetypeofobjectinquestion,and

http://freepdf-books.com

Page 339: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

requiresoccasionaltestinganddebuggingtoensurewehaveasensiblenumberofeachPrefabinstantiatedatruntime.

Withallofthisinmind,let’screateapoolingsystemforPrefabs!

http://freepdf-books.com

Page 340: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PoolableComponentsLet’sfirstdefineaninterfaceforaPoolableComponent:

publicinterfaceIPoolableComponent{

voidSpawned();

voidDespawned();

}

TheapproachforIPoolableComponentwillbeverydifferentfromtheapproachtakenforIPoolableObject.TheobjectsbeingcreatedthistimeareGameObjects,whicharealottrickiertoworkwiththanstandardobjectsbecauseofhowmuchoftheirruntimebehaviorisalreadyhandledthroughtheUnityEngine,andhowlittleaccesswehavetoit.

GameObjectsdonotgiveusaccesstoanequivalentNew()methodthatwecaninvokeanytimetheobjectiscreated,andwecannotderivefromtheGameObjectclassinordertoimplementone.GameObjectsarecreatedeitherbyplacingtheminaScene,orbyinstantiatingthematruntimethroughGameObject.Instantiate(),andtheonlyinputswecanapplyareaninitialpositionandrotation.Ofcourse,theirComponentshaveanAwake()methodwecandefine,whichisinvokedthefirsttimetheComponentisbroughttolife,butthisismerelyacompositionalobject—it’snottheactualparentobjectwe’respawninganddespawning.

So,becauseweonlyhavecontroloveraGameObjectclass’sComponents,itisassumedthattheIPoolableComponentinterfaceisimplementedbyatleastoneoftheComponentsthatisattachedtotheGameObjectwewishtopool.

TheSpawned()methodshouldbeinvokedoneveryimplementingComponenteachtimethepooledGameObjectisrespawned,whiletheDespawned()methodgetsinvokedwheneveritisdespawned.ThisgivesusentrypointstocontrolthedatavariablesandbehaviorduringthecreationanddestructionoftheparentGameObject.

TheactofdespawningaGameObjectistrivial;turnitsactiveflagtofalse(throughSetActive()).ThisdisablestheColliderandRigidbodyforphysicscalculations,removesitfromthelistofrenderableobjects,andessentiallytakescareofdisablinginteractionswithallbuilt-inUnityEnginesubsystemsinasinglestroke.TheonlyexceptionisanyCoroutinesthatarecurrentlyinvokingontheobject,sinceaswelearnedearlierinChapter2,ScriptingStrategies,CoroutinesareinvokedindependentlyofUpdate()andGameObjectactivity.WewillthereforeneedtocallStopCoroutine(),orStopAllCoroutines()duringthedespawningofsuchobjects.

Inaddition,Componentstypicallyhookintoourowncustomgameplaysubsystemsaswell,andsotheDespawn()methodgivesourComponentstheopportunitytotakecareofanycustomcleanupbeforeshuttingdown.Forexample,wewouldprobablywanttouseDespawn()toderegistertheComponentfromtheMessagingSystemwedefinedbackinChapter2,ScriptingStrategies.

Unfortunately,successfullyrespawningtheGameObjectisalotmorecomplicated.Whenwerespawnanobject,therewillbemanysettingsthatwereleftbehindwhentheobject

http://freepdf-books.com

Page 341: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

waspreviouslyactive,andthesemustberesetinordertoavoidconflictingbehaviors.AcommonproblemwiththisisRigidbodyvelocity.Ifthisvalueisnotexplicitlyresetbeforetheobjectisreactivated,thenthenewlyrespawnedobjectwillcontinuemovingwiththesamevelocitytheoldversionhadwhenitwasdespawned.

Thisproblembecomesfurthercomplicatedbythefactthatbuilt-inComponentsaresealed,andthereforecannotbederivedfrom.So,toavoidtheseissues,wecancreateacustomComponentthatresetstheattachedRigidbodywhenevertheobjectisdespawned:

publicclassResetPooledRigidbodyComponent:MonoBehaviour,

IPoolableComponent{

Rigidbody_body;

publicvoidSpawned(){}

publicvoidDespawned(){

if(_body==null){

_body=GetComponent<Rigidbody>();

if(_body==null){

//noRigidbody!

return;

}

}

_body.velocity=Vector3.zero;

_body.angularVelocity=Vector3.zero;

}

}

Notethatthebestplacetoperformthistaskisduringdespawning,becausewecannotbecertaininwhatordertheGameObjectclass’sIPoolableComponentinterfaceswillhavetheirSpawned()methodsinvoked.ItisunlikelythatanotherIPoolableComponentwillchangetheobject’svelocityduringdespawning,butitispossiblethatadifferentIPoolableComponentattachedtothesameobjectmightwanttosettheRigidbody’sinitialvelocitytosomeimportantvalueduringitsownSpawned()method.Ergo,performingthevelocityresetduringtheResetPooledRigidbodyComponentclass’sSpawned()methodcouldpotentiallyconflictwithotherComponentsandcausesomeveryconfusingbugs.

TipInfact,creatingPoolableComponentsthatarenotself-contained,andtendtotinkerwithotherComponentslikethis,isoneofthebiggestdangersofimplementingapoolingsystem.Weshouldminimizesuchimplementations,androutinelyverifythemwhenwe’retryingtodebugstrangeissuesinourgame.

Forthesakeofillustration,hereisthedefinitionofasimplePoolableComponentthatreplacestheTestMessageListenerclasswedefinedbackinChapter2,ScriptingStrategies.ThisComponentautomaticallyhandlessomebasictaskseverytimetheobjectisspawnedanddespawned:

publicclassPoolableTestMessageListener:MonoBehaviour,

IPoolableComponent{

publicvoidSpawned(){

MessagingSystem.Instance.AttachListener(typeof(MyCustomMessage),

this.HandleMyCustomMessage);

http://freepdf-books.com

Page 342: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

}

boolHandleMyCustomMessage(BaseMessagemsg){

MyCustomMessagecastMsg=msgasMyCustomMessage;

Debug.Log(string.Format("Gotthemessage!{0},{1}",

castMsg._intValue,castMsg._floatValue));

returntrue;

}

publicvoidDespawned(){

if(MessagingSystem.IsAlive){

MessagingSystem.Instance.DetachListener(typeof(MyCustomMessage),

this.HandleMyCustomMessage);

}

}

}

http://freepdf-books.com

Page 343: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThePrefabpoolingsystemHopefully,wenowhaveanunderstandingofwhatweneedfromourpoolingsystem,soallthat’sleftistoimplementit.Therequirementsareasfollows:

ItmustacceptrequeststospawnaGameObjectfromaPrefab,aninitialposition,andaninitialrotation:

Ifadespawnedversionalreadyexists,itshouldrespawnthefirstavailableoneIfitdoesnotexist,thenitshouldinstantiateanewGameObjectfromthePrefabIneithercase,theSpawned()methodshouldbeinvokedonallIPoolableComponentinterfacesattachedtotheGameObject

ItmustacceptrequeststodespawnaspecificGameObject:

Iftheobjectismanagedbythepoolingsystem,itshoulddeactivateitandcalltheDespawned()methodonallIPoolableComponentinterfacesattachedtotheGameObjectIftheobjectisnotmanagedbythepoolingsystem,itshouldsendanerror

Therequirementsarefairlystraightforward,buttheimplementationrequiressomeinvestigationifwewishtomakethesolutionperformance-friendly.Firstly,atypicalSingletonwouldbeagoodchoiceforthemainentrypoint,sincewewantthissystemtobegloballyaccessiblefromanywhere:

publicstaticclassPrefabPoolingSystem{

}

ThemaintaskforobjectspawninginvolvesacceptingaPrefabreference,andfiguringifwehaveanydespawnedGameObjectsthatwereoriginallyinstantiatedfromthesamereference.Todothis,wewillessentiallywantourpoolingsystemtokeeptrackoftwodifferentlistsforanygivenPrefabreference:alistofactive(spawned)GameObjects,andalistofinactive(despawned)objectsthatwereinstantiatedfromit.Thisdatawouldbebestabstractedintoaseparateclass,whichwewillnamePrefabPool.

Inordertomaximizetheperformanceofthissystem(andhencemakethelargestgainspossible,relativetojustallocatinganddeallocatingobjectsfrommemoryallofthetime),wewillwanttousesomefastdatastructuresinordertoacquirethecorrespondingPrefabPoolobjectswheneveraspawnordespawnrequestcomesin.

BecausespawninginvolvesbeinggivenaPrefab,wewillwantonedatastructurethatcanquicklymapPrefabstothePrefabPoolthatmanagesthem.AndbecausedespawninginvolvesbeinggivenaGameObject,wewillwantanotherdatastructurethatcanquicklymapspawnedGameObjectstothePrefabPoolthatoriginallyspawnedthem.ADictionaryisagoodchoiceforbothoftheseneeds.

Let’sdefinethesemapsinourpoolingsystem:

publicstaticclassPrefabPoolingSystem{

staticDictionary<GameObject,PrefabPool>_prefabToPoolMap=new

Dictionary<GameObject,PrefabPool>();

http://freepdf-books.com

Page 344: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

staticDictionary<GameObject,PrefabPool>_goToPoolMap=new

Dictionary<GameObject,PrefabPool>();

}

Nextwe’lldefinewhathappenswhenwespawnanobject:

publicstaticGameObjectSpawn(GameObjectprefab,Vector3position,

Quaternionrotation){

if(!_prefabToPoolMap.ContainsKey(prefab)){

_prefabToPoolMap.Add(prefab,newPrefabPool());

}

PrefabPoolpool=_prefabToPoolMap[prefab];

GameObjectgo=pool.Spawn(prefab,position,rotation);

_goToPoolMap.Add(go,pool);

returngo;

}

TheSpawn()methodwillbegivenaPrefabreference,aninitialposition,andaninitialrotation.WeneedtofigureoutwhichPrefabPoolthePrefabbelongsto(ifany),askittospawnanewGameObjectusingthedataprovided,andthenreturnthespawnedobjecttotherequestor.Wefirstcheckour“Prefab-to-Pool”map,toseeifapoolalreadyexistsforthisPrefab.Ifnot,wequicklycreateone.Ineithercase,wethenaskthePrefabPooltospawnusanewobject.ThePrefabPoolwilleitherenduprespawninganobjectthatwasdespawnedearlier,orinstantiateanewone(iftherearen’tanyinactiveinstancesleft).

Eitherway,thisclassdoesn’tparticularlycare.ItjustwantstheinstancegeneratedbythePrefabPoolclasssothatitcanbeenteredintothe“GameObject-to-Pool”mapandreturnedtotherequestor.

Forconvenience,wecanalsodefineanoverloadwhichplacestheobjectattheworld’scenter(usefulforGameObjectsthataren’tvisible,andjustneedtoexistsomewhere):

publicstaticGameObjectSpawn(GameObjectprefab){

returnSpawn(prefab,Vector3.zero,Quaternion.identity);

}

NoteNotethatnoactualspawninganddespawningaretakingplace,yet.ThistaskwilleventuallybehandledwithinthePrefabPoolclass.

DespawninginvolvesbeinggivenaGameObject,andthenfiguringoutwhichPrefabPoolismanagingit.ThiscouldbeachievedbyiteratingthroughourPrefabPoolclassesandcheckingiftheycontainthegivenGameObject.ButifweendupgeneratingalotofPrefabPools,thenthisiterativeprocesscantakeawhile.WewillalwaysendupwithasmanyPrefabPoolclassesaswehavePrefabs(atleastsolongaswemanageallofthemthroughthepoolingsystem).Mostprojectstendtohavedozens,hundreds,ifnotthousandsofdifferentPrefabs.

So,theGameObject-to-PoolmapismaintainedtoensurethatwealwayshaverapidaccesstothePrefabPoolthatoriginallyspawnedtheobject.ItcanalsobeusedtoquicklyverifyifthegivenGameObjectisevenmanagedbythepoolingsystemtobeginwith.Hereisthemethoddefinitionforthedespawningmethod,whichtakescareofthesetasks:

http://freepdf-books.com

Page 345: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

publicstaticboolDespawn(GameObjectobj){

if(!_goToPoolMap.ContainsKey(obj)){

Debug.LogError(string.Format("Object{0}notmanagedbypool

system!",obj.name));

returnfalse;

}

PrefabPoolpool=_goToPoolMap[obj];

if(pool.Despawn(obj)){

_goToPoolMap.Remove(obj);

returntrue;

}

returnfalse;

}

TipNotethattheDespawn()methodofbothPrefabPoolingSystemandPrefabPoolreturnsaBooleanthatcanbeusedtoverifywhetherornottheobjectwassuccessfullydespawned.

Asaresult,thankstothetwomapswe’remaintaining,wecanquicklyaccessthePrefabPoolthatmanagesthegivenreference,andthissolutionwillscaleforanynumberofPrefabthatthesystemmanages.

http://freepdf-books.com

Page 346: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PrefabpoolsNowthatwehaveasystemthatcanhandlemultiplePrefabpoolsautomatically,theonlythingleftistodefinethebehaviorofthepools.Asmentionedpreviously,wewillwantthePrefabPoolclasstomaintaintwodatastructures:oneforactive(spawned)objectsthathavebeeninstantiatedfromthegivenPrefabandanotherforinactive(despawned)objects.

Technically,thePrefabPoolingSystemclassalreadymaintainsamapofwhichPrefabisgovernedbywhichPrefabPool,sowecanactuallysavealittlememorybymakingthePrefabPoolaslavetothePrefabPoolingSystemclass,bynothavingitkeeptrackofwhichPrefabitismanaging.Consequently,thetwodatastructuresaretheonlymembervariablesthePrefabPoolneedstokeeptrackof.

However,foreachspawnedGameObject,itmustalsomaintainalistofallofitsIPoolableComponentreferencesinordertoinvoketheSpawned()andDespawned()methodsonthem.Acquiringthesereferencescanbeacostlyoperationtoperformatruntime,soitwouldbebesttocachethedatainasimplestruct:

publicstructPoolablePrefabData{

publicGameObjectgo;

publicIPoolableComponent[]poolableComponents;

}

ThisstructwillcontainareferencetotheGameObject,andtheprecachedlistofitsIPoolableComponents.

NowwecandefinethememberdataofourPrefabPoolclass:

publicclassPrefabPool{

Dictionary<GameObject,PoolablePrefabData>_activeList=new

Dictionary<GameObject,PoolablePrefabData>();

Queue<PoolablePrefabData>_inactiveList=newQueue<PoolablePrefabData>

();

}

ThedatastructurefortheactivelistshouldbeadictionaryinordertodoaquicklookupforthecorrespondingPoolablePrefabDatafromanygivenGameObjectreference.Thiswillbeusefulduringobjectdespawning.

Meanwhile,theinactivedatastructureisdefinedasaQueue,butitwillworkequallywellasaList,aStack,orreallyanydatastructurethatneedstoregularlyexpandorcontract,andwhereweonlyneedtopopitemsfromoneendofthelist,sinceitdoesnotmatterwhichobjectitis.Itonlymattersthatweretrieveoneofthem.AQueueisusefulinthiscasebecausewecanbothretrieveandremovetheobjectfromthedatastructureinasinglecall.

http://freepdf-books.com

Page 347: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ObjectspawningLet’sdefinewhatitmeanstospawnaGameObjectinthecontextofourpoolingsystem:atsomepoint,PrefabPoolwillgetarequesttospawnaGameObjectfromagivenPrefab,ataparticularpositionandrotation.ThefirstthingweshouldcheckiswhetherornotwehaveanyinactiveinstancesofthePrefab.Ifso,thenwecanpopthenextavailableonefromtheQueueandrespawnit.Ifnot,thenweneedtoinstantiateanewGameObjectfromthePrefabusingGameObject.Instantiate().Atthismoment,weshouldalsocreateaPoolablePrefabDataobjecttostoretheGameObjectreference,andacquirethelistofallIPoolableComponentsthatareattachedtoit.

Eitherway,wecannowactivatetheGameObject,setitspositionandrotation,andcalltheSpawned()methodonallofitsIPoolableComponents.Oncetheobjecthasbeenrespawned,wecanaddittothelistofactiveobjectsandreturnittotherequestor.

HereisthedefinitionoftheSpawn()methodthatdefinesthisbehavior:

publicGameObjectSpawn(GameObjectprefab,Vector3position,Quaternion

rotation){

PoolablePrefabDatadata;

if(_inactiveList.Count>0){

data=_inactiveList.Dequeue();

}else{

//instantiateanewobject

GameObjectnewGO=GameObject.Instantiate(prefab,position,

rotation)asGameObject;

data=newPoolablePrefabData();

data.go=newGO;

data.poolableComponents=newGO.GetComponents<IPoolableComponent>

();

}

data.go.SetActive(true);

data.go.transform.position=position;

data.go.transform.rotation=rotation;

for(inti=0;i<data.poolableComponents.Length;++i){

data.poolableComponents[i].Spawned();

}

_activeList.Add(data.go,data);

returndata.go;

}

http://freepdf-books.com

Page 348: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

InstanceprespawningBecauseweareusingGameObject.Instantiate()wheneverthepoolhasrunoutofdespawnedinstances,thissystemdoesnotcompletelyridusofruntimeobjectinstantiationandhence,heapmemoryallocation.It’simportanttoprespawntheexpectednumberofinstancesthatwewillneedduringthelifetimeofthecurrentScene,sothatwedon’tneedtoinstantiatemoreduringruntime.

TipItwouldbewastefultoprespawn100explosionparticleeffects,ifthemostwewilleverexpecttoseeintheSceneatanygiventimeisthreeorfour.Conversely,spawningtoofewinstanceswillcauseexcessiveruntimememoryallocations,andthegoalofthissystemistopushthemajorityofallocationtothestartofaScene’slifetime.Weneedtobecarefulabouthowmanyinstanceswemaintaininmemorysothatwedon’twastemorememoryspacethannecessary.

Let’sdefineamethodinourPrefabPoolingSystemclassthatwecanusetoquicklyprespawnagivennumberofobjectsfromaPrefab.ThisessentiallyinvolvesspawningNobjects,andthenimmediatelydespawningthemall:

publicstaticvoidPrespawn(GameObjectprefab,intnumToSpawn){

List<GameObject>spawnedObjects=newList<GameObject>();

for(inti=0;i<numToSpawn;i++){

spawnedObjects.Add(Spawn(prefab));

}

for(inti=0;i<numToSpawn;i++){

Despawn(spawnedObjects[i]);

}

spawnedObjects.Clear();

}

WewouldusethismethodduringSceneinitialization,toprespawnacollectionofobjectstouseinthelevel.Forexample:

publicclassOrcPreSpawner:MonoBehaviour

[SerializeField]GameObject_orcPrefab;

[SerializeField]int_numToSpawn=20;

voidStart(){

PrefabPoolingSystem.Prespawn(_orcPrefab,_numToSpawn);

}

}

http://freepdf-books.com

Page 349: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ObjectdespawningFinally,thereistheactofdespawningtheobjects.Asmentionedpreviously,thisprimarilyinvolvesdeactivatingtheobject,butwealsoneedtotakecareofvariousbookkeepingtasksandinvokingDespawned()onallofitsIPoolableComponentreferences.

HereisthemethoddefinitionforthePrefabPoolclass’sDespawn()method:

publicboolDespawn(GameObjectobjToDespawn){

if(!_activeList.ContainsKey(objToDespawn)){

Debug.LogError("ThisObjectisnotmanagedbythisobjectpool!");

returnfalse;

}

PoolablePrefabDatadata=_activeList[objToDespawn];

for(inti=0;i<data.poolableComponents.Length;++i){

data.poolableComponents[i].Despawned();

}

data.go.SetActive(false);

_activeList.Remove(objToDespawn);

_inactiveList.Enqueue(data);

returntrue;

}

Firstweverifytheobjectisbeingmanagedbythepool,andthenwegrabthecorrespondingPoolablePrefabDatainordertoaccessthelistofIPoolableComponentreferences.OnceDespawned()hasbeeninvokedonallofthem,wedeactivatetheobject,removeitfromtheactivelist,andpushitintotheinactivequeuesothatitcanberespawnedlater.

http://freepdf-books.com

Page 350: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PrefabpooltestingThefollowingclassdefinitionallowsustoperformasimplehands-ontestwiththePrefabPoolingSystemclass.ItwillsupportthreePrefabs,andprespawnfiveinstancesduringapplicationinitialization.Wecanpressthe1,2,or3keystospawnaninstanceofeachtype,andthenpressQ,W,orEtodespawnarandominstanceofeachtype.

publicclassPoolTester:MonoBehaviour{

[SerializeField]GameObject_prefab1;

[SerializeField]GameObject_prefab2;

[SerializeField]GameObject_prefab3;

List<GameObject>_go1=newList<GameObject>();

List<GameObject>_go2=newList<GameObject>();

List<GameObject>_go3=newList<GameObject>();

voidStart(){

PrefabPoolSystem_AsSingleton.Prespawn(_prefab1,5);

PrefabPoolSystem_AsSingleton.Prespawn(_prefab2,5);

PrefabPoolSystem_AsSingleton.Prespawn(_prefab3,5);

}

voidUpdate(){

if(Input.GetKeyDown(KeyCode.Alpha1)){SpawnObject(_prefab1,

_go1);}

if(Input.GetKeyDown(KeyCode.Alpha2)){SpawnObject(_prefab2,

_go2);}

if(Input.GetKeyDown(KeyCode.Alpha3)){SpawnObject(_prefab3,

_go3);}

if(Input.GetKeyDown(KeyCode.Q)){DespawnRandomObject(_go1);}

if(Input.GetKeyDown(KeyCode.W)){DespawnRandomObject(_go2);}

if(Input.GetKeyDown(KeyCode.E)){DespawnRandomObject(_go3);}

}

voidSpawnObject(GameObjectprefab,List<GameObject>list){

GameObjectobj=PrefabPoolingSystem.Spawn(prefab,

Random.insideUnitSphere*8f,Quaternion.identity);

list.Add(obj);

}

voidDespawnRandomObject(List<GameObject>list){

if(list.Count==0){

//Nothingtodespawn

return;

}

inti=Random.Range(0,list.Count);

PrefabPoolingSystem.Despawn(list[i]);

list.RemoveAt(i);

}

}

OncewespawnmorethanfiveinstancesofanyofthePrefabs,itwillneedtoinstantiatea

http://freepdf-books.com

Page 351: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

newoneinmemory,costingussomememoryallocation.But,ifweobservetheMemoryAreaintheProfiler,whileweonlyspawnanddespawninstancesthatalreadyexist,thenwewillnoticethatabsolutelynonewallocationstakeplace.

http://freepdf-books.com

Page 352: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PrefabpoolingandSceneloadingThereisonesubtlecaveattothissystemthathasnotyetbeenmentioned:thePrefabPoolingSystemclasswilloutlastScenelifetimesinceitisastaticclass.Thismeansthat,whenanewSceneisloaded,thepoolingsystem’sdictionarieswillattempttomaintainreferencestoanypooledinstancesfromthepreviousScene,butUnityforciblydestroystheseobjectsregardlessofthefactthatwearestillkeepingreferencestothem(unlesstheyweresettoDontDestroyOnLoad()!),andsothedictionarieswillbefullofnullreferences.ThiswouldcausesomeseriousproblemsforthenextScene.

WeshouldthereforecreateamethodinPrefabPoolingSystemthatresetsthepoolingsysteminpreparationforthislikelyevent.ThefollowingmethodshouldbecalledbeforeanewSceneisloaded,sothatitisreadyforanyearlycallstoPrespawn()inthenextScene:

publicstaticvoidReset(){

_prefabToPoolMap.Clear();

_goToPoolMap.Clear();

}

Notethat,ifwealsoinvokeagarbagecollectionduringScenetransitions,there’snoneedtoexplicitlyemptythePrefabPoolsthesedictionarieswerereferencing.SincetheseweretheonlyreferencestothePrefabPoolobjects,theywillbedeallocatedduringthenextgarbagecollection.Ifwearen’tinvokinggarbagecollectionbetweenScenes,thenthePrefabPoolandPooledPrefabDataobjectswillremaininmemoryuntilthattime.

http://freepdf-books.com

Page 353: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PrefabpoolingsummaryWehavefinallysolvedtheproblemofruntimememoryallocationsforGameObjectsandPrefabsbut,asaquickreminder,weneedtobeawareofthefollowingcaveats:

Weneedtobecarefulaboutproperlyresettingimportantdatainrespawnedobjects(suchasRigidbodyvelocity)Wemustensurewedon’tprespawntoofew,ortoomany,instancesofaPrefabWeshouldbecarefuloftheorderofexecutionofSpawned()andDespawned()methodsonIPoolableComponentsWemustcallReset()onPrefabPoolingSystembeforeSceneloading

Thereareseveralotherfeatureswecouldimplement.Thesewillbeleftasacademicexercisesifwewishtoextendthissysteminthefuture:

AnyIPoolableComponentsaddedtotheGameObjectafterinitializationwillnotbeinvoked.WecouldfixthisbychangingPrefabPooltokeepacquiringIPoolableComponentseverytimeSpawned()andDespawned()areinvoked,atthecostofadditionaloverheadduringspawning/despawning.IPoolableComponentsattachedtochildrenofthePrefab’srootwillnotbecounted.ThiscouldbefixedbychangingPrefabPooltouseGetComponentsInChildren<T>,atthecostofadditionaloverheadifwe’reusingPrefabswithdeephierarchies.PrefabinstancesthatalreadyexistintheScenewillnotbemanagedbythepoolingsystem.WecouldcreateaComponentthatneedstobeattachedtosuchobjectsandthatnotifiesthePrefabPoolingSystemclassofitsexistenceandpassesthereferenceintothecorrespondingPrefabPool.WecouldimplementawayforIPoolableComponentstosetapriorityduringacquisition,anddirectlycontroltheorderofexecutionfortheirSpawned()andDespawned()methods.WecouldaddcountersthatkeeptrackofhowlongobjectshavebeensittingintheInactivelistrelativetototalScenelifetime,andprintoutthedataduringshutdown.Thiscouldtelluswhetherornotwe’represpawningtoomanyinstancesofagivenPrefab.ThissystemwillnotinteractkindlywithPrefabinstancesthatsetthemselvestoDontDestroyOnLoad().ItmightbewisetoaddaBooleantoeverySpawn()calltosaywhethertheobjectshouldpersistornot,andkeeptheminaseparatedatastructurethatisnotclearedoutduringReset().WecouldchangeSpawn()toacceptanargumentthatallowstherequestortopasscustomdatatotheSpawned()functionofIPoolableObjectforinitializationpurposes.ThiscoulduseasystemsimilartohowcustommessageobjectswerederivedfromtheBaseMessageclassforourMessagingSystembackinChapter2,ScriptingStrategies.

http://freepdf-books.com

Page 354: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 355: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ThefutureofMonoandUnityAsweknow,UnitydoesnotusethelatestandgreatestMonoprojectcodefromhttp://www.mono-project.com,butaninternally-customizedversionwithsomeinternalbugfixes.

NoteTheactualMonotweaksmadebyUnityTechnologiescanbefoundinthefollowingGitHubrepository:

https://github.com/Unity-Technologies/mono/

AsanunfortunateconsequenceofhowvariouscomponentsoftheMonoFrameworkarelicensed,UnityTechnologieshasonlybeenabletoupdateMonoonaninfrequentbasis.TheoccasionsonwhichthistaskwereaccomplishedwaswiththereleaseofUnity4,whentheyupgradedtoMono2.6,andshortlyafterwardsversion2.6.5backinmid-2010,whichsupports.NET2.0/3.5features.But,atthetimeofpublication,thelatestversionofMono,version4.0,wasreleasedinMay2015,andsupports.NET4.5features.ThisputsUnity’simplementationabout5yearsbehindintermsofC#languageand.NETframeworkfeatures,whichhasdrawntheireofmanyUnitydevelopers.

UnityTechnologieshassuggestedtheremightbeaMonoupgradesometimeinthelifecycleofUnity5,butthelastofficialupdateonthissubjectwasbackinAugust2014.TheUnityroadmap(https://unity3d.com/unity/roadmap)placesitinthe“LongandUncertain”timeline,andUnityv5.2wasreleasedinearlySeptember2015,whichdidnotincludethisupgrade.So,itisdifficulttosaywhenMonowillbereceivingitsmuch-neededupgrade.UnityTechnologieshasalsobeenworkingwithMicrosofttobringreplacementstosomeMonoComponents(suchasupgradedversionsofthestatic,JIT,andAOTcompilers,aswellastheCLR).

NoteMicrosoft’sannouncementonthefutureof.NET:

http://blogs.msdn.com/b/dotnet/archive/2014/04/03/the-next-generation-of-net.aspx

Meanwhile,UnityTechnologieshasbeenworkingontheproblemoflong-termindependencefromthesethird-partydependenciesforawhile.WiththereleaseofUnity5theyunveiledanewapproachforscriptcodecompilation,whichstartedasawaytoprovideimprovedscriptingsupportforWebGL-basedUnityapplications,buthasalsobeenadoptedasthemainsolutiontothesewoes:IL2CPP.

NoteUnityTechnologies’IL2CPPannouncement:

http://blogs.unity3d.com/2014/05/20/the-future-of-scripting-in-unity/

IL2CPPisshorthandforIntermediateLanguageToC++,andcomeswithitsown.NETruntimethatcanberolledouttomultipleplatforms.ThebasicideaisthatC#scriptcode

http://freepdf-books.com

Page 356: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

willbeconvertedintoanintermediatelanguageandthenconvertedagaintoC++duringthebuildprocess.TheresultingC++willbepushedthroughoneofseveralavailableplatform-specificcompilerstosupportcross-platformcapability,takingawaytheburdenofhavingtocreateandmanagetheirowncompilers.

Thisprocesswillbemostlydisguisedfromtheuser,andnaturallytherewillbealossofcontrolasthecodeispushedthroughmultiple“codefilters”withvaryinglevelsofoptimizations.Itremainstobeseeniftheyallowsomehookstocontrolthecompilationprocessforadvanceddevelopers.TheEditorisstillexpectedtorunontheC#.NETruntimeforfasterdevelopmentiteration.

Thesuggestedbenefitsofthisapproachincludeperformanceenhancements(sinceevennear-nativecodegeneratedbytheJITcompilerstillpalesincomparisontostatically-compilednativeC++),fasterportingandfeaturedevelopmentfortheUnityEngine,andimprovedgarbagecollection.ThefirstplatformtogettheIL2CPPtreatmentinUnity5isWebGL,andwilleventuallybepushedtootherplatformsasthesystemmatures,andbecomesmorereliable.

NoteFormoreinformationonIL2CPPcheckoutthevariousblogpostsfromUnityTechnologiesonthesubject.Thefollowingpostcontainslotsofinformation,aswellasfurtherlinksonimportanttopics:

http://blogs.unity3d.com/2015/05/06/an-introduction-to-ilcpp-internals/

Whydoesn’tUnityTechnologiesjustprovideaC++APIforUnity?Onecanonlyspeculate,butit’saprettysafeassumptionthatUnitysupportsaverylargeuserbaseofdeveloperswhowouldbeuncomfortableworkinginC++directly.LosingtheaccessibilityofC#andUnityScriptwouldresultinaverydifferentproduct.Long-term,itwouldlikelysplitthecustomerbaseintotwocamps,whichrarelybodeswellsincewhicheveronebringsinthemostrevenuewillbecometheonethatissupportedtoagreaterdegree,leavingtheothertorot(asaninterestinganalogy,gamestypicallysufferfromthesameproblem,asexpansionsandmappackstendtosegregatethemultiplayeruserbase).

Inaddition,therearemany.NETlanguagesthatsharethesameintermediatecodeaftercompilation(CIL),andtheyhaveacommonbinaryinterface,whichmakesitordersofmagnitudeeasiertosupportcross-platformdevelopmentandmultiplelibrariesthanwithC++.Presumably,IL2CPPisacompromisefortheseconcerns.

So,tomakealongstoryshort,thereareagreatmanychangesgoingonwiththeunderlyingUnityEngineandit’stooearlytosaywhethertheIL2CPPapproachwillworksufficientlywellonallplatformstokeepfeatureparityandeaseofdeployment.Onethingisforsure;thenextcoupleofyearsofUnitydevelopmentwillbringsomeinterestingtransitions!

http://freepdf-books.com

Page 357: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 358: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryWe’vecoveredahumungousamountoftheoryandlanguageconceptsinthischapter,whichhavehopefullyshedsomelightonhowtheinternalsoftheUnityEngineandC#languagework.Thesetoolstrytheirbesttospareusfromtheburdenofcomplexmemorymanagement,butthereisstillawholehostofconcernsweneedtokeepinmindaswedevelopourgame.Betweenthecompilationprocesses,multiplememorydomains,thecomplexitiesofValuetypesversusReferencetypes,passingbyvalueversuspassingbyreference,boxing,objectpooling,andvariousquirkswithintheUnityAPI,wehavealotofthingstoworryabout.But,withenoughpractice,wewilllearntoovercomethemwithoutneedingtokeepreferringtogianttomessuchasthis!

Thischaptereffectivelyconcludesallofthetechniqueswecanbestowthatexplicitlyaimtoimproveapplicationperformance.Workflowoptimizationsarealwaysusefulthingstokeepinmind,however,astherearealotofneatlittlenuancestotheUnityEnginethataren’twellknownorclearlydocumented,andthatonlybecomeapparentthroughexperienceandcommunityinvolvement.Assuch,thenextchapterwillbefullofhintsandtipsforimprovinghowtomanageourprojectandScenesmoreeffectively,howtomakethemostoftheEditor,andhopefullysaveourselvesenoughdevelopmenttimetoactuallyimplementalloftheoptimizationtechniqueswe’vetalkedaboutthroughthisentirebook.

http://freepdf-books.com

Page 359: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 360: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Chapter8.TacticalTipsandTricksTherearealotoflittlenuancestousingtheUnityEnginethatcanhelpimproveourprojectworkflow.However,quitealotoftheEditor’sfunctionalityisnotwelldocumented,wellknown,orjustnotsomethingwethinkaboutuntilafterthefactthatitcouldhavebeenappliedperfectlytosolveaparticularproblemwewerehaving6monthsago.

TheInternetiscrammedfullofblogsandforumpoststhattrytohelpotherUnitydeveloperslearnabouttheseusefulfeatures,buttheyonlytendtofocusonahandfuloftipsatatime.Theredon’tseemtobeanyonlineresourcesthatgrouptogethermanyoftheminoneplace.Asaresult,intermediateandadvancedusersprobablyhavebookmarkedmanagersburstingattheseamswithlinkstothesetipsthattheyrunintoatonepointoranother,butwhichsitandrotuntilitcomestimetodosomespringcleaning.

So,becausethisbookisprimarilyforintermediateandadvancedusers,itfeltlikeitwasworththrowinginashortchaptertobringtonsofthesetipsandtrickstogetherinonelocation.Itworksasareferencelistinthehopeofsavingusalotoffuturedevelopmenteffort.

http://freepdf-books.com

Page 361: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

EditorhotkeytipsTheEditorisrifewithhotkeysthatcanaidrapiddevelopment.It’sworthcheckingoutthedocumentation.Butlet’sbehonest,nobodyreadsthemanualuntiltheyneedsomethingfromit.Herearesomeofthemostuseful,yetlesser-knownhotkeysavailablewhenplayingwiththeUnityEditor.

NoteInallcases,theWindowshotkeyislisted.IftheOSXhotkeyrequiresadifferentsetofkeystrokes,thenitwillbeshowninparentheses.

http://freepdf-books.com

Page 362: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

GameObjectsGameObjectscanbeduplicatedbyselectingtheminthehierarchyandpressingCtrl+D(Cmd+D).

New,emptyGameObjectscanbecreatedusingCtrl+Shift+N(Cmd+Shift+N).

PressCtrl+Shift+A(Cmd+Shift+A)toquicklyopentheAddComponentmenu.Fromthere,youcantypeinthenameoftheComponentyouwishtoadd.

http://freepdf-books.com

Page 363: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SceneViewPressingShift+Fordouble-tappingtheFkeywillfollowanobjectintheSceneView,whichcanbehelpfulfortrackinghigh-velocityobjectsorfiguringoutwhyobjectsmightbefallingoutofourScene.

HoldingAltandleft-clickdraggingwiththemousewillmaketheSceneViewcameraorbitthecurrentlyselectedobject(asopposedtolookingaroundit).HoldingAltandright-clickdraggingwillzoomthecamerain/out.

HoldingCtrlandleft-clickdraggingwillcausetheselectedobjecttosnaptothegridasitmoves.ThesamecanbedoneforrotationbyholdingCtrlasweadjusttherotationwidgetsaroundtheobject.SelectingEdit|SnapSettings…opensawindowwherewecaneditthegridthatobjectssnaptoonaper-axisbasis.

Wecanforceobjectstosnapbyvertex,holdingtheVkeyaswemovetheobjectaround.Theselectedobjectwillattachitselftothenearestvertex,tothecursorofthenearestobject.Thisisveryusefulforaligninglevelpiecesintoplace,suchasplatformsandothertile-basedsystems,withoutneedingtohand-adjustpositionvectors.

NoteAtonepoint,inUnityversions4.2to4.6,itwaspossibletoholdShiftwithaColliderobjectselectedtoreveallittlehooksthroughwhichwecouldadjusttheColliderthroughtheSceneView.ThiswasremovedinrecentversionsofUnityduetoconflictswithothercontrols.WemustusetheEditColliderbuttonwithintheCollidercomponenttoaccessthisfeaturegoingforward.

http://freepdf-books.com

Page 364: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ArraysWecanduplicatearrayelementsthathavebeenexposedintheInspectorViewbyselectingthemandpressingCtrl+D(Cmd+D).Thiswillcopytheelementandinsertitintothearrayimmediatelyafterthecurrentselection.

Wecanremoveentriesfromanarrayofreferences(forexample,anarrayofGameObjects)bypressingShift+Delete(Cmd+Delete).Thiswillstripawaytheelementandcondensethearray.Notethatthefirstpresswillclearthereferencesettingittonull,butthesecondpresswillremovetheelement.Removingelementsinarraysofprimitivetypes(ints,floats,andsoforth)canbeaccomplishedbysimplypressingDeletewithouttheShiftkey(Cmd)modifier.

WecanusetheW,A,S,Dkeyswhileright-clickdraggingontheSceneViewtoflyaroundwiththecamera,inatypicalfirst-personcameracontrolstyle.TheQandEkeyscanbeusedtotranslatethecameraontheverticalaxis,respectively.

http://freepdf-books.com

Page 365: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

InterfaceWecanholdAltandclickonanyhierarchyarrow(thesmallgreyarrowtotheleftofanyparentobjectname)toexpandtheobject’sfullhierarchyandnotjustthenextlayer.ThisworksonGameObjectsintheHierarchyView,foldersandPrefabswithintheProjectView,listsintheInspectorView,andsoon.

WecansaveandrestoreselectionsfromobjectsintheHierarchyorProjectViewsintypicalRTSgamestyle!MaketheselectionandpressCtrl+Alt+<0-9>(Cmd+Alt+<0-9>)tosavetheselection.PressCtrl+Shift+<0-9>(Cmd+Shift+<0-9>)torestoreit.Thisisexceptionallyusefulifwefindourselvesselectingthesamehandfulofobjectsoverandoveragainwhilewemakeadjustments.

PressingShift+SpacebarwillexpandthecurrentwindowtofilltheentireEditorscreen.Pressingitagainwillshrinkthewindowandrestoreittoitspreviouslocation.

PressingCtrl+Shift+P(Cmd+Shift+P)willtogglethePausebuttonwhileinPlayMode.

http://freepdf-books.com

Page 366: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

OtherWecanquicklyaccessthedocumentationofanyUnitykeywordorclass,byhighlightingitinMonoDevelopandpressingCtrl+‘(Cmd+‘).ThiswillopenthedefaultbrowserandperformasearchontheUnitydocumentationforthegivenkeywordorclass.

TipNotethatuserswithEuropeankeyboardsmayalsoneedtoholddowntheShiftkey.

WiththerecentreleaseofVisualStudioToolsforUnity(VSTU),itispossibletoaccessthedocumentationinthesamewaythroughVisualStudiobypressingCtrl+Alt+M,followedbyCtrl+H(noequivalentOSXhotkey,obviously).

http://freepdf-books.com

Page 367: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 368: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

EditorinterfacetipsThefollowingcollectionoftipsrelatestotheEditoranditsinterfacecontrols.

http://freepdf-books.com

Page 369: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

GeneralWecanprioritizewhichScriptswillhavetheirUpdateandFixedUpdatemethodscalledbeforeothers,bynavigatingtoEdit|ProjectSettings|ScriptExecutionOrder.Withtheexceptionofsometime-sensitivesystems,suchasaudioprocessing,ifwefindourselvestryingtosolvecomplexproblemsusingthisfeature,itimpliesthatwe’vegotsomefragileandtightcouplingbetweenourComponents.Fromasoftwaredesignperspective,thiscanbeawarningsignthatwemightneedtoapproachtheproblemfromanotherangle.However,itcanbehelpfultohaveparticularobjectsgettheirUpdate()andLateUpdate()functionscalledbeforeotherobjects,inordertodosomebookkeeping.

IntegratingUnityprojectswithaSourceControlsolutioncanbealittletricky.Thefirststepistoforcetheprojecttogenerate.metafilesforassets;ifwedon’tdothis,thenanyonepullingdataintotheirlocalUnityprojectmustregeneratetheirownmetadatafiles.Thiscaneasilycauseconflicts,soitisessentialthateveryoneusesthesameversions.VisiblemetadatafilescanbeenabledbynavigatingtoEdit|ProjectSettings|Editor|VersionControl|Mode|VisibleMetaFiles.Allofthe.metafileswillnowbevisiblewithinthefilestructureandavailableforuploadintoSourceControl.

ItcanalsobehelpfultoconvertcertainassetdataintoaText-onlyformat,ratherthanbinarydata,toallowmanualeditingofdatafiles.Thisturnsmanydatafilesintothemuchmorehuman-readableYAMLformat.Forinstance,ifwe’reusingScriptableObjectstostorecustomdata,wecanuseatexteditortosearchandeditthesefileswithouthavingtodoitallthroughtheUnityEditorandserializationsystem.Thiscansavealotoftime,especiallywhenhuntingforaparticulardatavalueorwhenmultieditingacrossdifferentderivedtypes.ThisoptioncanbeenabledbynavigatingtoEdit|ProjectSettings|Editor|AssetSerialization|Mode|ForceText.

TheEditorhasalogfile,whichcanbeaccessedbyopeningtheConsolewindow(wherelogmessagesareprintedoutto),clickingonthe“hamburgericon”(madefromthreehorizontallines)atthetop-right,andselectingOpenEditorLog.Ifwerecentlybuiltourproject,itwillcontainabreakdownofcompressedfilesizesofallassetsthatwerepackedintotheexecutableandorderedbysize.Thisisanextremelyhelpfulwayoffiguringoutwhichassetsareconsumingthemajorityofourapplicationfootprint(hint:it’salmostalwaysTexturefiles),andwhichfilesaretakingupmorespacethanwewouldexpect.

http://freepdf-books.com

Page 370: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AdditionalwindowscanbeaddedtotheEditorbyright-clickingonthetitleofanexistingwindowandselectingAddTab.Thisalsoallowsustoaddduplicatewindows,suchashavingmorethanoneInspectorViewopenatatime:

Havingduplicateviewscanbekindofredundant,unlessweusethe“lockicon”tolockthegivenviewtoitscurrentselection.Whenweselectanobject,allInspectorViewswillupdatetoshowtheobject’sdata,exceptforanylockedInspectorViews,whichcontinuetoshowthedataoftheobjecttheywerelockedto.

Commontricksthatmakeuseofwindowlockingincludethefollowing:

UsingtwoofthesameView(Inspector,Animation,andsoforth)tocomparetwoobjectsside-by-sideoreasilycopydatafromonetoanother

http://freepdf-books.com

Page 371: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UsingaduplicateProjectViewtomovelargedatasetsaroundTestingwhathappenstoanydependentobjectsifanobjectistweakedduringruntimeSelectingmultipleobjectsintheProjectView,thendragging-and-droppingthemintoaserializedarrayintheInspectorViewwithoutlosingtheoriginalselection

http://freepdf-books.com

Page 372: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheInspectorViewWecanentercalculationsintonumericinspectorfields.Forexample,typing4*128intoanintfieldwillresolvethevalueto512,sparingusfromhavingtopulloutacalculatorordothemathinourhead.

Arrayelementscanbeduplicatedanddeletedfromalist(inthesamefashionasthehotkeysmentionedpreviously)byright-clickingontherootelementandselectingDuplicateArrayElementorDeleteArrayElement.

AComponent’scontextmenucanbeaccessedthroughboththesmallcogiconintheupper-rightorbyright-clickingonthenameoftheComponent.EveryComponent’scontextmenucontainsaResetoption,whichresetsallvaluesbacktotheirdefault,sparingusfromhavingtoresetvaluesmanually.ThisisusefulwhenworkingwithTransformComponents,asthisoptionwillsettheobject’spositionandrotationto(0,0,0)anditsscaleto(1,1,1).

It’scommonlyknownthat,ifaGameObjectwasspawnedfromaPrefab,thentheentireobjectcanberevertedbacktoitsinitialPrefabstateusingtheRevertbuttonatthetopoftheInspectorView.However,it’slesswellknownthatindividualvaluescanberevertedbyright-clickingonthenameofthevalueandselectingRevertValuetoPrefab.Thisrestorestheselectedvalue,leavingtherestuntouched.

TheInspectorViewhasadebugmodethatcanbeaccessedbyclickingonthehamburgericonnexttothelockiconandselectingDebug.ThiswilldisableallcustomInspectordrawingandrevealallrawdatawithinthegivenGameObjectanditscomponents,evenprivatedatafields.Privatefieldsaregrayed-outandcannotbemodifiedthroughtheInspectorView,butthisgivesusausefulwayofexaminingprivatedataandotherhiddenvaluesduringPlayMode.TheDebugviewalsorevealsinternalObjectIDs,whichcanbeusefulifwe’redoing“interesting”thingswithUnity’sserializationsystemandwanttoresolveconflicts.

IfwehaveanarrayofdataelementsserializedintheInspectorView,thentheyaretypicallylabeledElement<N>where<N>isthearrayindex.Thiscanmakeittrickytofindaspecificelementifourarrayelementsareaseriesofserializedclassesorstructs,whichtendtohavemultiplechildrenthemselves.However,iftheveryfirstfieldintheobjectisastring,thentheelementswillbenamedafterthevalueofthestringfield.

Whenameshobjectisselected,thePreviewwindowatthebottomoftheInspectorViewisoftenfairlysmall,makingithardtoseedetailsinthemeshandhowitwilllookwhenit

http://freepdf-books.com

Page 373: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

appearsinourScene.But,ifweright-clickonthetopbarofthePreviewwindow,itwillbedetachedandenlarged,makingitmucheasiertoseeourmesh.Wedon’thavetoworryaboutsettingthedetachedwindowbacktoitsoriginalhomebecause,ifthedetachedwindowisclosed,thenthePreviewwindowwillreturntothebottomoftheInspectorView.

http://freepdf-books.com

Page 374: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheProjectViewTheProjectView’ssearchbarallowsustofilterforobjectsofaparticulartypebyclickingonthesmallicontotherightofthesearchbar.Thisprovidesalistofdifferenttypeswecanfilterby,revealingallobjectsofthattypewithintheentireproject.However,selectingtheseoptionssimplyfillsthesearchbarwithastringofthet:<type>format,whichappliestheappropriatefilter.

Thus,wecansimplytypetheequivalentstringsintothesearchbarforthesakeofspeed.Forinstance,typingt:prefabwillfilterforallPrefabs,nomatterwheretheycanbefoundinthehierarchy;t:texturewillrevealtextures,t:scenewillrevealScenes,andsoon.Addingmultiplesearchfiltersinthesearchbarwillincludeobjectsofalltypes(itdoesnotrevealobjectswhichonlysatisfybothfilters).Thesefiltersaremodifiersinadditiontoname-basedfiltering,soaddingaplaintextstringwillcauseaname-basedsearchthroughthefilteredobjects.Forexample,t:texturenormalmapwillfindalltexturefilesthatincludethewordnormalmapintheirname.

Ifwe’remakinguseofAssetBundlesandthebuilt-inlabelingsystem,theProjectView’ssearchbaralsoallowsustohuntdownbundledobjectsbytheirlabelusingl:<labeltype>.

IfaMonoBehaviourscriptcontainsserializedreferences(using[SerializeField]orpublic)toUnityAssets,suchasMeshesandTextures,thenwecanassigndefaultvaluesdirectlyintothescriptitself.SelectthescriptfileintheProjectViewandtheInspectorViewshouldcontainafieldfortheassetforustodrag-and-dropthedefaultassignmentinto.

http://freepdf-books.com

Page 375: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Bydefault,theProjectViewsplitsfilesandfoldersintotwocolumnsandtreatsthemseparately.IfweprefertheProjectViewtohaveatypicalhierarchyfolderandfilestructure,thenwecansetittoOneColumnLayoutinitscontextmenu(thehamburgericonatthetopright).ThiscanbeagreatspacesaverinsomeEditorlayouts.

Right-clickingonanyobjectintheProjectViewandselectingSelectDependencieswillrevealallobjectsuponwhichthisassetreliesinordertoexist,suchasTextures,Meshes,MonoBehaviourscriptfiles,andsoon.ForScenefiles,itwilllistallentitiesreferencedwithinthatScene.Thisishelpfulifwe’retryingtoperformsomeassetcleanup.

http://freepdf-books.com

Page 376: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheHierarchyViewAlesser-knownfeatureoftheHierarchyViewistheabilitytoperformcomponent-basedfilteringwithinthecurrentlyactiveScene.Confusingly,itusesthesamesyntaxasperformingtype-basedfilteringintheProjectViewandcanthereforebeaccomplishedbytypingt:<componentname>.Forexample,typingt:lightintotheHierarchyViewsearchbarwillrevealallobjectsintheScenethatcontainaLightcomponent.

Upper-orlower-casecharactersareunimportant,butthestringmustmatchthefullcomponentnameinorderforthesearchtocomplete.Componentsthatderivefromthegiventypewillalsoberevealed,sotypingt:rendererwillrevealallobjectswithderivedcomponentssuchasMeshRenderers,SkinnedMeshRenderers,andsoon.

http://freepdf-books.com

Page 377: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

TheSceneandGameViewsTheSceneViewcameraisnotvisiblefromtheGameView,butitisgenerallyaloteasiertomovearoundandplacethroughtheuseofthehotkeysmentionedpreviously.TheEditorallowsustoaligntheselectedobjecttothesamepositionandrotationoftheScenecamerabynavigatingtoGameObject|AlignwithView(Ctrl+Shift+F/Cmd+Shift+F).ThismeansthatwecanusethecameracontrolstoplacetheScenecamerawherewewouldlikeourobjecttobe,andplacetheobjecttherebyaligningittothecamera.

Similarly,wecanaligntheSceneviewtotheselectedobjectbynavigatingtotheGameObject|AlignViewtoSelectedoption.Thisisusefulforcheckingifthegivenobjectispointingintherightdirection.

Wecanperformsimilarcomponent-basedfilteringontheSceneView,aswecanwiththeHierarchyView,usingthet:<component>syntaxwithinitssearchbar.

AttheverytoprightoftheUnityEditorisadropdownlabeledLayers.ThiscontainsaLayer-basedfilteringandlockingsystemfortheSceneView.Togglingonthe“eye”iconwillshow/hideallobjectsofthatLayerwithintheSceneView.Togglingthelockiconwillalloworpreventobjectsofthegivenlayerfrombeingselected.Thisishelpfulforthingssuchaspreventingsomeonefromaccidentallyselectingandmovingbackgroundobjectsthathavealreadybeensituatedintheperfectlocation.

AcommonlyknownandusefulfeatureoftheEditoristhatGameObjectscanbegivenspecialiconsorlabelstomakethemeasiertofindintheSceneView.Thisisparticularlyhelpfulforobjectswithnorendererbutthatwewishtofindeasily.Forinstance,objectssuchasLightsandCamerashavebuilt-iniconsthatidentifytheminourSceneViewmoreeasily.

However,thesamegizmoscanberevealedwithintheGameViewbyclickingontheGizmosbuttonatthetoprightoftheGameView.Thedropdownforthisoptiondetermineswhatgizmoswillbevisiblewhenthisoptionisenabled.

http://freepdf-books.com

Page 378: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

PlayModeSincePlayModechangesarenotautomaticallysaved,itiswisetomodifythetintcolorappliedduringPlayModetomakeitblatantlyobviouswhichmodewe’recurrentworkingwith.ThisvaluecanbesetbynavigatingtoEdit|Preferences|Colors|Playmodetint.

ChangescanbesavedfromPlayModebysimplyusingtheclipboard.Ifwe’retweakinganobjectinPlayModeandwe’rehappywithitssettings,thenwecancopytheobjectintotheclipboardusingCtrl+C(Cmd+C),andpasteitbackintotheSceneoncePlayModeendswithCtrl+V(Cmd+V).Allsettingsontheobjectatthetimeofthecopywillbekept.ThesamecanbedonewithindividualvaluesorentirecomponentsusingtheCopyComponentandPasteComponentoptionsinthecomponent’scontextmenu.However,theclipboardcanonlycontaindataforoneobject,component,orvalue,atatime.

Anotherapproach,whichallowsustosavethedataofmultipleobjectsduringPlayMode,istocreatePrefabsfromthembydragginganddroppingthemintotheProjectWindowatruntime,oncewe’rehappywiththesettings.IftheoriginalobjectwasderivedfromaPrefab,andwewishtoupdateitacrossallinstances,thenweonlyneedtooverwritetheoldPrefabwiththenewonewecreatedbydragginganddroppingthecopyontopoftheoriginal.NotethatthisalsoworksduringPlayModeruntime,butitcanbedangeroussincethereisnodialogpop-uptoconfirmtheoverwrite.BeverycarefulnottooverwritethewrongPrefab.

WecanusetheFrameSkipbutton(thebuttontotherightofthePausebuttonintheEditor)toiterateoneframeatatime.Thiscanbeusefulforwatchingframe-by-framephysicsorgameplaybehavior.KeepinmindthatthiscausesbothoneFixedUpdateandoneUpdatetobecalledeachstep,inequalcounts,whichmaynotexactlyreflectactualruntimebehaviorwherewetendtohaveunequalcallstothesemethods.

IfthePausebuttonisenabledwhenPlayModebegins,thenthegamewillbepausedjustaftertheveryfirstframe,givingusachancetoobserveanyanomaliesthatoccurredfrominitializationofourScene.

http://freepdf-books.com

Page 379: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 380: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ScriptingtipsThefollowingtipsareusefulfeaturestoknowwhenscripting.

http://freepdf-books.com

Page 381: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

GeneralWecanmodifyvarioustemplatesofnewScript,Shader,andComputeShaderfiles.ThiscanbehelpfultoremovetheemptyUpdatestubswhich,aswelearned,cancauseunnecessaryruntimeoverhead.Thesefilescanbefoundinthefollowinglocations:

Windows:<Unityinstall>\Editor\Data\Resources\ScriptTemplates\OSX:/Applications/Unity/Editor/Data/Resources/ScriptTemplates/

TherecentreleaseofUnityVersion5.1introducedtheAssertclassandallowsforassert-baseddebugging,whichsomedevelopersaremorecomfortablewithasopposedtoexception-baseddebugging.ChecktheUnitydocumentationformoreinformationonAsserts:http://docs.unity3d.com/ScriptReference/Assertions.Assert.html

CallingDebug.Break()isfunctionallyequivalenttopausingtheEditorduringPlayMode,whichcanbeusefulforcatchingawkwardgraphicalbehavior,orasamoreconvenientalternativetotheabsurdhotkeyrequiredtopausetheScene(Ctrl+Shift+P).

http://freepdf-books.com

Page 382: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

AttributesAttributesareveryusefulmeta-leveltagsthatcanbegiventoalmostanytargetinC#.Theyaremostcommonlyusedonmemberdata(fields)andclasses,allowingustoflagthemwithspecialpropertiessothattheycanbeprocesseddifferently.IntermediateandadvancedUnitydeveloperswillfinditworthwhiletoreadtheC#documentationonattributesandusetheirimaginationtocomeupwiththeirownattributesthathelpacceleratetheirworkflow.TherearequiteafewattributesbuiltintotheUnityenginethatcanbeexceptionallyusefulwhenusedintherightplace.

NoteAdvanceduserswillnotethatattributescanalsobegiventoenums,delegates,methods,parameters,events,modules,andevenassemblies.

VariableattributesPublicvariablesarefairlydangerousthingstoaddtoourcomponents,asanythingcancomealongandchangethevalueatruntime,makingithardtotracebugs,aswellasrequiringspecialhandholdingtopreventthevariablefrombeinggivenaninvalidvalue.However,publicvariablesareusuallythefirstwaythatUnitydeveloperslearntoexposevariablesintheInspectorView.Insomecases,thepublicvariableisabsolutelyintendedtobepublic,butwedon’twishittobeseenintheInspector.Insuchacase,the[HideInInspector]attributecanbeusedtohidethevariablefromtheInspector,whenevernecessary.

However,thepreferredapproachistomakeourvariablesprivateorprotectedandallowEditor-baseddevelopmentbyexposingvaluesthroughthe[SerializeField]attribute.ThisattributeallowsprivateandprotectedvariablestoberevealedintheInspectorfordesignerstomanipulate,withoutriskingothercomponentsaccidentallychangingthevariableatruntime.

The[Range]attributecanbeaddedtoanintegerorfloating-pointfieldtoconvertitintoasliderintheInspectorView.Wecangiveminimumandmaximumvalues,limitingtherangethatthevaluecancontain.

Normally,ifavariableisrenamed,evenifwedoarefactorthroughourIDE(whetheritsMonoDeveloporVisualStudio)thenthevaluesarelostassoonasUnityrecompilestheMonoBehaviourandmakestheappropriatechangestoanyinstancesofthecomponent.However,the[FormerlySerializedAs]attributeisincrediblyhelpfulifwewishtorenameavariablethathasbeenpreviouslyserialized,asitwillcopythedatafromthevariablenamedwithintheattributeintothegivenvariableduringcompilationtime.Nomorelostdataduetorenamingstuff!

Notethatitisnotsafetoremovethe[FormerlySerializedAs]attributeaftertheconversioniscompleted,unlessthevariablehasbeenmanuallychangedandresavedsincecompletion.The“.prefab”datafilewillstillcontaintheoldvariablename,andsoitstillneedsthe[FormerlySerializedField]attributetofigureoutwheretoplacethedatathenexttimethefileisloaded(forexample,whentheEditorisclosedandreopened).Thus,

http://freepdf-books.com

Page 383: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

thisisahelpfulattribute,butextendedusedoestendtoclutterupourcodebasealot.

ClassattributesThe[SelectionBase]attributewillmarkanyGameObjectthecomponentisattachedtoastherootofselectionfortheSceneView.Thisisespeciallyusefulifwehavemeshesthatarechildrenofotherobjects,aswemightwanttheparentobjecttobeselectedwiththefirstclick,insteadoftheobjectwiththeMeshRenderercomponent.

Wecanusethe[RequireComponent]attributetoforcedesignerstoattachvitalcomponentstothesameGameObjectiftheyattempttoattachthiscomponent.Thisensuresanydependenciesthatourcodebasereliesonwillbesatisfiedbydesigners,withouthavingtowriteoutawholebunchofdocumentationforthem.

The[ExecuteInEditMode]attributewillforcetheobject’sUpdate(),OnGUI(),andOnRenderObject()methodstobecalledevenduringEditMode.However,therearecaveats:

TheUpdate()methodisonlycalledifsomethingchangesintheSceneOnGUI()isonlycalledduringGameViewevents,notforotherviewssuchastheSceneViewOnRenderObject()iscalledduringanyrepainteventfortheSceneandGameViews

However,thisgivessuchobjectsadifferentsetofeventhooksandentrypointscomparedtotypicalEditorscripts,sothisattributestillhasitsuses.

http://freepdf-books.com

Page 384: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LoggingWecanaddrichtexttagstodebugstrings.Tagssuchas<size>,<b>(bold),<i>(italics),and<color>allworkondebugstrings.Thiscanbehelpfulfordifferentiatingthedifferentkindsoflogmessagesandhighlightingspecificelements.

Debug.Log("<color=red>[ERROR]</color>Thisisa<i>very</i><size=14>

<b>specific</b></size>kindoflogmessage");

TheMonoBehaviourclasshasaprint()methodforconvenience,whichdoesthesamethingasDebug.Log().

Itcanhelptocreateacustomloggerclass,whichautomaticallyappends\n\ntotheendofeverylogmessage.ThiswillpushandhideawaytheunnecessaryUnityEngine.Debug:Log(Object)clutterthattendstofilltheConsolewindow.

http://freepdf-books.com

Page 385: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UsefullinksUnitytechnologiesprovidemanyusefultutorialsontheusageofvariousscriptingfeatures,whichareprimarilytargetedatbeginnerandintermediate-leveldevelopers.Thetutorialscanbefoundathttps://unity3d.com/learn/tutorials/topics/scripting.

There’sahelpfulpostonUnityAnswers,whichprovidesareferencelistthatcoversmanyofthedifferentscriptingandcompilationerrorswemightrunacrossduringdevelopment,whichcanbefoundathttp://answers.unity3d.com/questions/723845/what-are-the-c-error-messages.html.

ScriptableObjectsareveryusefulobjectsandanexcellentwayofstoringgamedatainaformthatdoesnotneedtobeinstantiatedatruntime.Theyworklikeanyotherclassinthattheycancontainmethodsandvariables,canbeserialized,allowpolymorphism,andsoon.Theonlytrickypartistheycanonlybecreatedthroughscripting,andmustbeloadedintomemoryatanytimeusingResources.Load().ButthisallowsustocontrolwhichScriptableObjectsarepresentinmemoryatanygiventime,givingusmorecontroloverruntimememoryconsumption.ExplainingthenuancesofScriptableObjectsherewouldtaketoomuchspace,butUnitytechnologieshaveprovidedagoodintroductoryexaminationofScriptableObjectsinthefollowingtutorialvideo:

https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/scriptable-objects

NoteNotethat,despitethecategoryoftheScriptableObjectvideo,it’sgenerallyconsideredmoreofanintermediate-leveltopic.BeginnerswouldbebestservedbyfocusingonbecomingcomfortablewithPrefabs,beforeturningthingsontheirheadthroughScriptableObjectsandtheimportantserializationtopicsthatneedtobeunderstood.

NestedCoroutinesareanotherinterestingandusefulareaofscriptingthatisnotwelldocumented.But,thefollowingthird-partyblogpost,whichcoversalotoftheinterestingdetails,shouldbeconsideredwhenworkingwithNestedCoroutines:

http://www.zingweb.com/blog/2013/02/05/unity-coroutine-wrapper

WecanfigureoutwhenaparticularfeaturewasaddedtotheUnityAPIbycheckingtheAPIhistorypageathttp://docs.unity3d.com/ScriptReference/40_history.html.

http://freepdf-books.com

Page 386: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 387: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Customeditors/menustipsWecansetcustomhotkeysforMenuItems.Forexample,wecanmaketheKkeytriggerourMenuitemmethod,bydefiningtheMenuItemattributeasfollows:

[MenuItem("MyMenu/MenuItem_k")]

WecanalsoincludemodifierkeyssuchasCtrl(Cmd),Shift,andAltusingthe%,#,and&characters,respectively.

MenuItemsalsohavetwooverloads,whichallowsustosettwoadditionalparameters:aBooleanthatdetermineswhetherthemenuitemrequiresavalidationmethod,andanintegerthatdeterminesthemenuitem’spriorityinthehierarchy.

CheckthedocumentationforMenuItemsforacompletelistofavailablehotkeymodifiers,specialkeys,andhowtocreatevalidationmethods:

http://docs.unity3d.com/ScriptReference/MenuItem.html

Itispossibleto“ping”anobjectintheHierarchy,similartowhathappenswhenweclickonaGameObjectreferenceintheInspectorView,bycallingEditorGUIUtility.PingObject().

TheoriginalimplementationoftheEditorclass,andthewaythatmostpeoplelearnedhowtowriteEditorscripts,originallyinvolvedwritingalllogicandcontentdrawinginthesameclass.However,PropertyDrawersareaneffectivewayofdelegatingInspectordrawingtoadifferentclassfromthemainEditorclass.Thiseffectivelyseparatesinputandvalidationbehaviorfromdisplaybehavior,allowingmorefine-tunedcontrolofrenderingonaper-fieldbasisandmoreeffectivereuseofcode.WecanevenusePropertyDrawerstooverridedefaultUnitydrawingforbuilt-inobjects,suchasVectorsandQuaternions.

PropertyDrawersmakeuseofSerializedPropertiestoaccomplishserializationofindividualfields,andtheyshouldbepreferredwhenwritingeditorscripts,sincetheymakeuseofbuilt-inundo,redo,andmultieditfunctionality.Datavalidationcanbealittleproblematic,andthebestsolutionistouseOnValidate()callsonsetterpropertiesforfields.AsessionatUnite2013byUnityTechnologiesdeveloperTimCooper,whichexplainsthebenefitsandpitfallsofvariousserializationandvalidationapproachesingreatdetailathttps://www.youtube.com/watch?v=Ozc_hXzp_KU.

WecanaddentriestoComponentcontextmenusandeventhecontextmenusofindividualfieldswiththe[ContextMenu]and[ContextMenuItem]attributes.ThisallowsaneasywaytocustomizeInspectorbehaviorforourComponentswithoutneedingtowritebroadEditorclassesorcustomInspectors.

AdvancedusersmayfinditusefultostorecustomdatawithinUnitymetadatafilesthroughtheAssetImporter.userDatavariable.TherearealsoamultitudeofopportunitiestomakeuseofReflectionoftheUnitycodebase.RyanHipple’ssessionatUnite2014outlinesahugenumberofneatlittlehacksandtricksoneachievewithReflectionintheUnityEditor:

http://freepdf-books.com

Page 388: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

https://www.youtube.com/watch?v=SyR4OYZpVqQ

AnundocumentedfeaturewasintroducedinUnityv4.5,ReorderableLists.TheseallowustohaveanInspectorViewofagenericList<T>,whichcanbeeasilyreorderedbydragginganddroppingtheelementsaround.However,thisfeatureappearstobeunfinished,asitrequiresacustomEditorclasstomakeuseofthemproperly.ThefollowingpostonUnityAnswersexplainshowtouseReorderableListsfairlysuccinctly:

http://answers.unity3d.com/questions/826062/re-orderable-object-lists-in-inspector.html

http://freepdf-books.com

Page 389: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 390: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ExternaltipsThefollowingtipsandtricksrelatetotopicsoutsidetheUnityEditoritselfthatcanhelpUnitydevelopmentworkflowenormously.

GooglingUnity-relatedproblemsorconcernscangoalotfasterifwestartthesearchwith“site:unity3d.com“.

IftheUnityEditorcrashes,forwhateverreason,thenwecanpotentiallyrestoreourScenebyrenamingthefollowingfiletoincludethe.unityextension(forScenefiles),andcopyingitintoourAssetsfolder:

\<projectfolder>\Temp\_EditModeScene

Ifwe’redevelopingonWindows,thenthere’sverylittlereasonnottouseVisualStudioatthispoint.MonoDevelophasbeendraggedalongkickingandscreamingformanyyears,andmanydevelopershavebeenswitchingovertothemorefeature-richVisualStudioCommunityeditionformostoftheirdevelopmentworkflowneeds,particularlywithincrediblyhelpfulpluginssuchasResharper.

Forsomedevelopers,theonlyreasontobootupMonoDevelophasbeenforruntimedebuggingofcode,butwiththerecentreleaseofVisualStudioToolsforUnity(VSTU),VisualStudionowoffersbetterintegrationwiththeUnityEditor.ItevenallowsourC#codetoberuntime-debuggedthroughVisualStudioitself.Unlesswehaveparticularhangupsabouttheinterfaceorthefactthatit’smadebythebig,badMicrosoft,weshouldwanttogiveVisualStudioCommunityatryasitaccelerateourscriptcodedevelopmentinwayswehadn’texpected.

CheckoutthefollowingvideoformoreinformationonVisualStudioanditsintegrationwithUnitythroughVSTU:

https://channel9.msdn.com/Events/Visual-Studio/Visual-Studio-2015-Final-Release-Event/Building-Unity-games-in-Visual-Studio

Thereisagreatresourceforgameprogrammingpatterns(orrather,typicalprogrammingpatternsexplainedinawaythatispertinenttogamedevelopment)anditiscompletelyfreeandavailableonline:

http://gameprogrammingpatterns.com/contents.html

KeepaneyeonanysessionvideosthatcomefromUniteconferences,whenevertheyhappen(orbetteryet,trytoattendthem).There’susuallyacoupleofpanelsateachconferenceheldbyexperienceddeveloperssharinglotsofcoolandinterestingthingsthey’vebeenabletoaccomplishwiththeEngineandEditor.Inadditiontothis,makesuretokeepinvolvedintheUnitycommunity,eitherthroughtheforumsonunity3d.com,Twitter,reddit,StackOverflowandUnityAnswers,oratwhateversocialgatheringplacespopoutofthewoodworkinthecomingyears.

Everysingletipthatwasincludedinthisbookstartedoutasanideaortidbitofknowledgethatsomeonesharedsomewhereatsomepoint.So,thebestwaytokeepup-to-dateonthe

http://freepdf-books.com

Page 391: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

besttips,tricks,andtechniquesistokeepourfingersonthepulseofwhereUnityisheadingbystayinginvolvedinitscommunity.

http://freepdf-books.com

Page 392: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

OthertipsFinally,thefollowingsectioncontainstipsthatdidn’tquitefitintoothercategories.

It’salwaysagoodideatoorganizeourScenesusingemptyGameObjectsandnamethemsomethingsensible.Theonlydrawbacktothismethodisthattheemptyobject’sTransformisincludedduringpositionorrotationchangesandgetsincludedduringrecalculations.Properobjectreferencing,Transformchangecaching,and/oruseoflocalPosition/localRotationsolvestheproblemadequately.Inalmostallcases,thebenefitstoworkflowfromSceneorganizationaresignificantlymorevaluablethansuchtrivialperformancelosses.

AnimatorOverrideControllerswereintroducedwaybackinUnityv4.3,buttendtobeforgottenorrarelymentioned.TheyareanalternativetostandardAnimationControllersthatallowustoreferenceanexistingAnimationController,andthenoverridespecificstatestousedifferentanimationfiles.Thisallowsformuchfasterworkflowssincewedon’tneedtoduplicateandtweakAnimationControllersmultipletimes;weonlyneedtochangeahandfulofanimationstates.

WhenUnity5islaunched,itautomaticallyopenstheProjectWizard,allowingustoopenarecentproject.However,ifwepreferthedefaultbehaviorfromUnity4,whichistoautomaticallyopenthepreviousproject,wecaneditthisbehaviorbynavigatingtoEdit|Preferences|General|LoadPreviousProjectonstartup.NotethatthissettinghasadifferentnameunderUnity4andworksintheoppositefashion.YoucanseethisbynavigatingtoEdit|Preferences|General|AlwaysShowProjectWizard.NotethatiftheProjectWizardisenabled,wecanalsoopenmultipleinstancesofUnityEditorsimultaneously.

TheamazingcustomizabilityoftheUnityEditoranditsever-growingfeaturesetmeansthereareabsolutelytonsoflittleopportunitiestoimproveworkflowsandmorearebeingdiscoveredorinventedeverysingleday.TheAssetStoremarketplaceisabsolutelyrifewithassets,whichtrytosolvesomekindofproblemthatmoderndevelopersarehavingtroublewith,whichmakesitagreatplacetobrowseifwe’relookingforideasor,ifwe’rewilling,dropsomemoneytosaveusatonofhassle.Becausetheseassetstendtoselltoabroadaudience,thistendstokeeppriceslow,andwecanpickupsomeamazinglyusefultoolsandscriptsforsurprisinglylittlecost.Inalmostallcases,itwouldtakeusasignificantnumberofhourstodevelopthesamesolutionourselves.Ifweconsiderourtimeasvaluable,thenscanningtheAssetStoreonoccasioncanbeaverycost-effectiveapproachtodevelopment.

http://freepdf-books.com

Page 393: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

http://freepdf-books.com

Page 394: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

SummaryThisbringsustothebook’sconclusion,andhopefullyyouenjoyedtheride.Toreiterateperhapsthemostimportanttipinthisbook,alwaysmakesuretoverifythesourceoftheperformancebottleneckviaprofilingbeforemakingasinglechange.Thelastthingwewanttowastetimeonischasingghostsinthecodebase,whenfiveminutesofprofilertestingcansaveusanentiredayofwork.Also,inalotofcases,thesolutionrequiresacost-benefittinganalysistodetermineifwe’renotsacrificingtoomuchinanyotherareaattheriskofaddingfurtherbottlenecks.Makesuretohaveareasonableunderstandingoftherootcauseofthebottleneck,toavoidputtingotherperformancemetricsatrisk.

Performanceenhancementcanbealotoffunsince,duetothecomplexityofmoderncomputerhardware,smalltweakscanyieldbigrewards.Therearemanytechniquesthatcanbeimplementedtoimproveapplicationperformanceorspeedupourworkflows.Someofthesearehardtofullyrealizewithouttheexperienceandskillsnecessarytospendareasonableamountoftimeimplementingthem.Inmostcasesthefixesarerelativelysimple,oncewefindthesourceoftheproblem.So,goforthanduseyourrepositoryofknowledgetomakeyourgamesthebesttheycanbe!

http://freepdf-books.com

Page 395: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

IndexA

Ahead-Of-Time(AOT)/ThecompilationprocessAndroidDebugBridge(ADB)tool/RemoteconnectiontoanAndroiddeviceanimationfiles

about/MeshandanimationfilesAPIhistorypage

URL/Usefullinksapproaches,performanceanalysis

about/Bestapproachestoperformanceanalysisscriptpresence,verifying/Verifyingscriptpresencescriptcount,verifying/Verifyingscriptcountongoingcodechanges,minimizing/Minimizingongoingcodechangesinternaldistractions,minimizing/Minimizinginternaldistractionsexternaldistractions,minimizing/Minimizingexternaldistractions

artefacts/Manageresolutiondownscalingexternallyattributes

variableattributes/Variableattributesclassattributes/Classattributes

audioabout/Audiofiles,loading/Loadingaudiofilesprofiling/Profilingaudioformats,encoding/Encodingformatsandqualitylevelsqualitylevels,encoding/Encodingformatsandqualitylevelsperformanceenhancements/Audioperformanceenhancements

AudioClips/TheAudioAreaaudiofiles

loading/Loadingaudiofilesadditionalloadingoptions/Additionalloadingoptions

AudioMixersURL/ApplyFiltereffectsthroughMixergroupstoreduceduplication

audioperformanceenhancementsabout/AudioperformanceenhancementsactiveAudioSourcecount,minimizing/MinimizeactiveAudioSourcecountAudioClipreferences,minimizing/MinimizeAudioClipreferencesforce,enablingtoMonofor3Dsounds/EnableForcetoMonofor3Dsoundslowerfrequencies,resampling/Resampletolowerfrequenciesencodingformats,considering/Considerallencodingformatsstreaming,preventing/Bewareofstreamingfiltereffects,applying/ApplyFiltereffectsthroughMixergroupstoreduceduplication

http://freepdf-books.com

Page 396: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

WWW.audioClip,using/Use“WWW.audioClip”responsiblyAudioModulefiles,consideringforbackgroundmusic/ConsiderAudioModulefilesforbackgroundmusic

AudioSources/TheAudioArea

http://freepdf-books.com

Page 397: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Bbackendbottlenecks

about/Backendbottlenecksfillrate/Fillratememorybandwidth/MemorybandwidthVRAMlimits/VRAMlimits

boxing/Boxingbruteforcetesting/Bruteforcetesting

http://freepdf-books.com

Page 398: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Ccachecomponent

references/CacheComponentreferencesobtaining,withfastestmethod/ObtainingComponentsusingthefastestmethod

caveats,StaticBatchingabout/StaticBatchingcaveatsEditModedebugging/EditModedebuggingofStaticBatchingstaticmeshesinstantiationatruntime,avoiding/Avoidinginstantiatingstaticmeshesatruntimerendering/Visibilityandrenderingvisibility/Visibilityandrendering

CgstandardlibraryfunctionsURL/UseGPU-optimizedhelperfunctions

Closures/Closurescodesegments,targetedprofiling

about/TargetedprofilingofcodesegmentsProfilerscriptcontrol/ProfilerscriptcontrolcustomCPUProfiling/CustomCPUProfiling

CollisionMatrix/TheCollisionMatrixCommandBuffer

URL/MultithreadedrenderingCommonIntermediateLanguage(CIL)/TheMonoplatformCommonLanguageRuntime(CLR)/TheMonoplatformcompilationprocess,Monoplatform

about/ThecompilationprocessmanualJITcompilation/ManualJITcompilation

complexMeshCollidersavoiding/AvoidcomplexMeshColliderssimplerprimitives,using/UsesimplerprimitivessimplerMeshColliders,using/UsesimplerMeshCollidersragdolls,optimizing/OptimizingragdollsJointsandcolliders,reducing/ReduceJointsandCollidersinter-ragdollcollisions,avoiding/Avoidinter-ragdollcollisionsinactiveragdolls,disabling/Disableorremoveinactiveragdollsinactiveragdolls,removing/Disableorremoveinactiveragdolls

controls,UnityProfilerwindowabout/Controls,CPUAreaAddProfiler/ControlsRecord/ControlsDeepProfile/ControlsProfileEditor/ControlsActiveProfiler/ControlsClear/Controls

http://freepdf-books.com

Page 399: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

FrameSelection/ControlsTimelineView/ControlsCPUArea/CPUAreaGPUArea/TheGPUAreaRenderingArea/TheRenderingAreaMemoryArea/TheMemoryAreaMemoryArea,simplemode/TheMemoryAreaMemoryArea,detailedmode/TheMemoryAreaAudioArea/TheAudioAreaPhysics3D/2DArea/ThePhysics3D/2DArea

coroutineabout/SavingProfilerdataURL/SavingProfilerdatausing/Update,Coroutines,andInvokeRepeating

Coroutines/CoroutinesCPU-boundapplication

about/CPU-boundmultithreadedrendering/MultithreadedrenderingGPUSkinning/GPUSkinning

CustomEditors/Menustips/Customeditors/menustips

http://freepdf-books.com

Page 400: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

D2DColliders

circle/CollidertypesPolygon/Collidertypesbox/Collidertypes

3DCollidersMeshColliders/CollidertypesCapsule/CollidertypesCylinder/CollidertypesBox/Collidertypes

DeferredShadingURL/DeferredShading

Dispose()method/CustomCPUProfilingdistance-squared

considering,overdistance/Considerusingdistance-squaredoverdistanceDrawCall

about/DrawCallsRenderState,modifying/DrawCalls

DynamicBatchingabout/DynamicBatchingrequirements,URL/DynamicBatchingvertexattributes/Vertexattributesuniformscaling/Uniformscalingsummary/DynamicBatchingsummaryapplying/DynamicBatchingsummary

DynamicCollidersabout/StaticandDynamicColliders

http://freepdf-books.com

Page 401: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

EEditor

hotkeytips/Editorhotkeytipsabout/Editorhotkeytipsinterfacetips/Editorinterfacetips

emptycallbackdeclarationsremoving/Removingemptycallbackdeclarations

ExecutionOrderURL/SavingProfilerdata

externaltipsabout/Externaltipsothertips/Othertips

http://freepdf-books.com

Page 402: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Ffillrate,backendbottlenecks

about/Fillrateoverdraw/OverdrawOcclusionCulling/OcclusionCullingshaderoptimization/ShaderoptimizationShadersintendedformobileplatforms,using/ConsiderusingShadersintendedformobileplatforms

Find()methodavoiding,atruntime/AvoidingtheFind()andSendMessage()methodsatruntime

FirstInFirstOut(FIFO)queue/DrawCallsFixedUpdate()method/MaximumAllowedTimestepFixedUpdateTimestep/Physicsandtimeforeachloops/TheforeachloopsForwardRendering

URL/ForwardRenderingfragmentShader/ProfilingrenderingissuesFrameDebugger/TheFrameDebuggerfront-endbottlenecks

about/FrontendbottlenecksLevelOfDetail(LOD)/LevelOfDetailGPUSkinning,disabling/DisableGPUSkinningtessellation,reducing/Reducetessellation

http://freepdf-books.com

Page 403: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

GGameObjectnullreferencecheck

performing/FasterGameObjectnullreferencechecksgameprogrammingpatterns

URL/Externaltipsgarbagecollection,managedmemory

about/Garbagecollectionmemoryfragmentation/Memoryfragmentationatruntime/GarbagecollectionatruntimethreadedGarbagecollection/Threadedgarbagecollectiontactics/Garbagecollectiontactics

GarbageCollectormainthread/Threadedgarbagecollectionfinalizerthread/Threadedgarbagecollection

globalmessagingsystemabout/Aglobalmessagingsystemgloballyaccessibleobject/Agloballyaccessibleobjectregistration/Registrationmessageprocessing/Messageprocessingimplementing/Implementingthemessagingsystemmessage,queuing/Messagequeuingandprocessingmessage,processing/Messagequeuingandprocessingcustommessage,implementing/Implementingacustommessagemessageregistration/Messageregistrationmessage,sending/Messagesendingmessagecleanup/Messagecleanupwrappingup/Wrappingupthemessagingsystem

GPUProfiling/GPUprofilinggreedymethods/CPUArea

http://freepdf-books.com

Page 404: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Hheap/Managedmemoryhotkeytips,Editor

about/EditorhotkeytipsGameObjects/GameObjectsSceneView/SceneViewarrays/Arraysinterface/InterfaceUnitykeyword,accessing/Other

http://freepdf-books.com

Page 405: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

IimmutableReferencetypes

strings/StringsareimmutableReferencetypesabout/StringsareimmutableReferencetypesstringconcatenation/Stringconcatenation

inter-objectcommunicationissuestaticclassapproach/StaticclassesSingletonComponents/SingletonComponentsreferences,assigningtopre-existingobjects/Assigningreferencestopre-existingobjectsglobalmessagingsystem/Aglobalmessagingsystem

interfacetips,Editorabout/Editorinterfacetipsgeneral/GeneralInspectorView/TheInspectorViewProjectView/TheProjectViewHierarchyView/TheHierarchyViewSceneView/TheSceneandGameViewsGameView/TheSceneandGameViewsPlayMode/PlayMode

IntermediateLanguageToC++(IL2CPP)about/ThefutureofMonoandUnityURL/ThefutureofMonoandUnity

InvokeRepeatingusing/Update,Coroutines,andInvokeRepeating

IsAliveproperty/Messagecleanupissue

focusingon/Focusingontheissue

http://freepdf-books.com

Page 406: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

JJust-In-Time(JIT)/Thecompilationprocess

http://freepdf-books.com

Page 407: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

LLevelOfDetail(LOD)

about/LevelOfDetailURL/LevelOfDetail

LightingandShadowingabout/LightingandShadowingURL/LightingandShadowingForwardRendering/ForwardRenderingDeferredShading/DeferredShadingVertexLitShading(legacy)/VertexLitShading(legacy)real-timeShadows/Real-timeShadows

lightingoptimizationabout/LightingoptimizationappropriateShadingMode,using/UsetheappropriateShadingModeCullingMasks,using/UseCullingMaskslightmapping,using/UseBakedLightmapsshadows,optimizing/OptimizeShadows

http://freepdf-books.com

Page 408: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

MManagedDomain/UnitymemorydomainsManagedHeap/Managedmemorymassvalues

URL/MassMaterials

about/MaterialsandShadersMaximumAllowedTimestep/MaximumAllowedTimestep

adjusting/AdjusttheMaximumAllowedTimestepmeaninglessdata(noise)

reducing/Reducingnoisememorybandwidth,backendbottlenecks

about/Memorybandwidthlesstexturedata,using/UselesstexturedataGPUTextureCompressionformats,testing/TestdifferentGPUTextureCompressionformatstexturesampling,minimizing/Minimizetexturesamplingassetsorganization,forreducingtextureswaps/Organizeassetstoreducetextureswaps

memoryusageoptimizationabout/MemoryusageoptimizationUnitymemorydomains/Unitymemorydomainsvaluetypes/ValuetypesandReferencetypesreferencetypes/ValuetypesandReferencetypespassingbyvalue/Passbyvalueandpassbyreferencedatalayout/TheimportanceofdatalayoutUnityAPI/TheUnityAPIforeachloops/TheforeachloopsCoroutines/CoroutinesClosures/Closures.NETlibraryfunctions/.NETlibraryfunctionstemporaryworkbuffers/Temporaryworkbuffersobjectpooling/Objectpooling

meshabout/Meshandanimationfiles

MeshColliderconcave/Collidertypesconvex/Collidertypes

mobilegraphicsoptimizationabout/OptimizinggraphicsformobileDrawCalls,minimizing/MinimizeDrawCallsMaterialCount,minimizing/MinimizetheMaterialcounttexturesize,minimizing/MinimizetexturesizeandMaterialcount

http://freepdf-books.com

Page 409: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

power-of-2,creating/Maketexturessquareandpowerof2Texturessquare,creating/Maketexturessquareandpowerof2lowestpossibleprecisionformats,usinginShaders/UsethelowestpossibleprecisionformatsinShadersAlphaTesting,allowing/AvoidAlphaTesting

Monoabout/TheMonoplatformfuture/ThefutureofMonoandUnityURL/ThefutureofMonoandUnity

MonoBehaviourUnitydocumentationURL/Removingemptycallbackdeclarations

Monoplatformabout/TheMonoplatformcompilationprocess/Thecompilationprocess

http://freepdf-books.com

Page 410: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

N.NET

URL/ThefutureofMonoandUnity.NETlibraryfunctions/.NETlibraryfunctionsnameproperty

retrieving,avoiding/AvoidretrievingstringpropertiesfromGameObjectsNativeDomain/UnitymemorydomainsNestedCoroutines

URL/Usefullinks

http://freepdf-books.com

Page 411: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

OOnGUI()method/LoadingProfilerdataOperatingSystem(OS)/TheMonoplatformOrderofExecution

URL/Physicsandtimeoverdraw/Fillrate

http://freepdf-books.com

Page 412: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Ppassbyreference/Passbyvalueandpassbyreferencepassingbyvalue/Passbyvalueandpassbyreferenceperformance-enhancingtechniques

polygoncount,reducing/Reducingpolygoncountnecessarydata,importing/Import/calculateonlywhat’sneedednecessarydata,calculating/Import/calculateonlywhat’sneededbakedanimations,considering/ConsiderbakedanimationsOptimizeMeshesoption/LetUnityoptimizemeshesmeshes,combining/Combinemeshes

performanceanalysisapproaches/Bestapproachestoperformanceanalysis

PhysicsEngineinternals/Physicsandtimeabout/PhysicsEngineinternalstime/Physicsandtimephysics/PhysicsandtimeFixedUpdateloop/TheFixedUpdateloopMaximumAllowedTimestep/MaximumAllowedTimestepphysicsupdates/Physicsupdatesandruntimechangesruntimechanges/PhysicsupdatesandruntimechangesDynamicColliders/StaticandDynamicCollidersStaticColliders/StaticandDynamicColliderscollisiondetection/CollisiondetectionCollidertypes/CollidertypesCollisionMatrix/TheCollisionMatrixRigidbodyactivestate/RigidbodyactiveandsleepingstatesRigidbodysleepingstates/Rigidbodyactiveandsleepingstatesraycasting/Rayandobjectcastingobjectcasting/Rayandobjectcasting

physicsperformanceoptimizationsabout/Physicsperformanceoptimizationsscenesetup/ScenesetupStaticColliders,using/UseStaticCollidersappropriatelyCollisionMatrix,optimizing/OptimizetheCollisionMatrixdiscretecollisiondetection,preferring/PreferdiscretecollisiondetectionFixedUpdatefrequency,modifying/ModifytheFixedUpdatefrequencyMaximumAllowedTimestep,adjusting/AdjusttheMaximumAllowedTimestepcastandbounding-volumechecks,minimizing/Minimizecastandbounding-volumecheckscomplexMeshColliders,avoiding/AvoidcomplexMeshCollidersphysicsobjects,allowingtosleep/LetphysicsobjectssleepSolverIterationCount,modifying/ModifySolverIterationCount

http://freepdf-books.com

Page 413: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

ragdolls,optimizing/Optimizingragdollsphysics,using/Knowwhentousephysicsupgrading,toUnity5/ConsiderupgradingtoUnity5

polygoncountreducing/ReducingpolygoncountTweakMeshCompression/TweakingMeshCompressionRead-WriteEnabledflag,using/UseRead-WriteEnabledappropriately

prefabpoolingabout/Prefabpooling,PrefabpoolsPoolableComponent/PoolableComponentssystemrequirements/ThePrefabpoolingsystemobjectspawning/Objectspawninginstanceprespawning/Instanceprespawningobjectdespawning/Objectdespawningtesting/Prefabpooltestingandsceneloading/PrefabpoolingandSceneloadingsummary/Prefabpoolingsummary

ProceduralMaterialsabout/ProceduralMaterialsURL/ProceduralMaterials

Profiler.enableBinaryLogmethod/SavingandloadingProfilerdataProfiler.enabledmethod/SavingandloadingProfilerdataProfiler.logFilemethod/SavingandloadingProfilerdataProfilingandAnalysis

about/FinalthoughtsonProfilingandAnalysis

http://freepdf-books.com

Page 414: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

RReferencetypes

about/ValuetypesandReferencetypesarrays/ArraysareReferencetypes

reflection/ManualJITcompilationrenderingissues

profiling/Profilingrenderingissuesrenderingissues,profiling

GPUProfiling/GPUprofilingFrameDebugger/TheFrameDebuggerbruteforcetesting/BruteforcetestingCPU-bound/CPU-bound

ReorderableListsabout/Customeditors/menustipsURL/Customeditors/menustips

rigidbodyproperty/ObtainingComponentsusingthefastestmethodRuntimeHelpers.PrepareMethod()method/ManualJITcompilation

http://freepdf-books.com

Page 415: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Sscenesetup

about/Scenesetupscaling/Scalingpositioning/Positioningmassvalues/Mass

ScriptableObjectsURL/Usefullinks

scriptingtipsabout/Scriptingtipsgeneral/Generalattributes/Attributeslogging/Loggingusefullinks/Usefullinks

SendMessage()methodavoiding,atruntime/AvoidingtheFind()andSendMessage()methodsatruntime

Shaderabout/MaterialsandShaders

Shaders,intendedformobileplatformsusing/ConsiderusingShadersintendedformobileplatformssmalldatatypes,using/Usesmalldatatypeschangingprecision,avoiding/Avoidchangingprecisionwhileswizzlingswizzling/AvoidchangingprecisionwhileswizzlingGPU-optimizedhelperfunctions,using/UseGPU-optimizedhelperfunctionsunnecessaryfeatures,disabling/Disableunnecessaryfeaturesunnecessaryinputdata,removing/Removeunnecessaryinputdatanecessaryvariables,exposing/Onlyexposenecessaryvariablesmathematicalcomplexity,reducing/Reducemathematicalcomplexity,Reducetexturelookupsconditionalstatements,avoiding/Avoidconditionalstatementsdatadependencies,reducing/ReducedatadependenciesSurfaceShaders/SurfaceShadersShader-basedLOD,using/UseShader-basedLOD

ShadowCascadesfeatureURL/OptimizeShadows

skinning/GPUSkinningSparseTexturing

about/SparseTexturesURL/SparseTextures

sphericalharmonics/ForwardRenderingstack/ManagedmemoryStaticBatching

http://freepdf-books.com

Page 416: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

about/StaticBatchingrequirements/StaticBatchingStaticflag/TheStaticflagmemoryrequirements/MemoryrequirementsMaterialreferences/Materialreferencescaveats/StaticBatchingcaveatssummary/StaticBatchingsummary

StaticCollidersabout/StaticandDynamicCollidersusing/UseStaticCollidersappropriately

http://freepdf-books.com

Page 417: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Ttagproperty

retrieving,avoiding/AvoidretrievingstringpropertiesfromGameObjectstemporaryworkbuffers/TemporaryworkbuffersTexture/Texturefilestexturefiles

about/Texturefilescompressionformats/Compressionformatsperformanceenhancements/Textureperformanceenhancements

textureperformanceenhancementsabout/Textureperformanceenhancementsfilesize,reducing/ReduceTexturefilesizeMipMaps,using/UseMipMapswiselyresolutiondownscaling,managing/ManageresolutiondownscalingexternallyAnisotropicFilteringlevels,adjusting/AdjustAnisotropicFilteringlevelsatlasing,considering/ConsiderAtlasingcompressionratesfornon-squaretextures,adjusting/Adjustcompressionratesfornon-squareTexturesSparseTexturing/SparseTexturesProceduralMaterials/ProceduralMaterials

theMSDNC#ProgrammingGuideURL/Registration

TotalAllocatedblock/ThreadedgarbagecollectionTransformchanges

caching/ConsidercachingTransformchanges

http://freepdf-books.com

Page 418: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

UUnity

URL/SavingProfilerdata,ThefutureofMonoandUnityfuture/ThefutureofMonoandUnity

Unity3D/TheUnityProfilerUnity5.0/TheUnityProfilerUnityAPI/TheUnityAPIUnitydocumentation

URL/ConsiderAtlasingUnityEditor

profiling/Editorprofilingreflection,URL/Customeditors/menustips

UnityEditor;about/TheUnityProfilerUnitymemorydomains

about/Unitymemorydomainsnativememory/Nativememorymanagedmemory/Managedmemory

UnityProfilerabout/TheUnityProfiler,UnderstandingtheProfilerlaunching/LaunchingtheProfilerUnityEditor/EditororstandaloneinstancesStandaloneInstances/EditororstandaloneinstancesUnityWebplayerconnection,connecting/TheUnityWebplayerconnectionconnecting,toiOSdevice/RemoteconnectiontoaniOSdeviceconnecting,toAndroiddevice/RemoteconnectiontoanAndroiddevicewindow/TheProfilerwindow

UnityProfilerdatasaving/SavingandloadingProfilerdata,SavingProfilerdataloading/SavingandloadingProfilerdata,LoadingProfilerdata

UnityProfilerwindowabout/TheProfilerwindowcontrols/Controls

UnityroadmapURL/ThefutureofMonoandUnity

UnityWebplayer/LaunchingtheProfilerUnloadAudioData()method/Additionalloadingoptionsunusedscriptsandobjects

disabling/Disablingunusedscriptsandobjectsdisabling,byvisibility/Disablingobjectsbyvisibilitydisabling,bydistance/Disablingobjectsbydistance

http://freepdf-books.com

Page 419: Unity 5 Game Optimization - smactech.in · There are further alternatives that we can explore, such as making use of Unity’s built-in bridge between script code and the Inspector

Vvaluetypes

about/ValuetypesandReferencetypesstructs/StructsareValuetypes

VerticalSync(VSync)/MinimizinginternaldistractionsVisualStudio

URL/ExternaltipsVisualStudioToolsforUnity(VSTU)/OtherVRAMlimits,backendbottlenecks

about/VRAMlimitstexturepreloading/Texturepreloadingtexturethrashing/Texturethrashing

http://freepdf-books.com