Professional Documents
Culture Documents
noobtutsUnity2DSnakeTutorial
Tutorials
Articles
Premium
About
Unity2DSnakeTutorial
Foreword
ThisTutorialwillexplainhowtomakeasimple2DSnakeGamein
Unity.Snakeisanarcadegamethatwascreatedbackinthe1970s.And
likemostarcadegamesitsstillawholelotoffunandeasytodevelop,
whichmakesitagreatgameforaTutorial.
Requirements
Knowledge
OurTutorialdoesnotrequireanyspecialskillsexceptsomeknowledge
abouttheUnitybasicslikeGameObjectsandTransforms.Evenifyou
dontknowthoseconceptsyet,theTutorialshouldstillbedoable.
FeelfreetoreadoureasierUnityTutorialslikeUnity2DPongGameto
getusedtothisamazinggameengine.
UnityVersion
OurSnakeTutorialwilluseUnity5.0.0f4.Newerversionsshouldwork
http://noobtuts.com/unity/2dsnakegame
1/21
12/06/2015
noobtutsUnity2DSnakeTutorial
neaswell,olderversionsmayormaynotwork.Thefreeversionof
Unity5nowcomeswithalltheenginefeatures,whichmakesitthe
recommendedversion.
ProjectSetup
Letsgettoit.WewillstartUnityandselectNewProject:
Wewillnameitsnake,selectanylocationlikeC:\,select2Dandclick
CreateProject:
IfweselecttheMainCameraintheHierarchythenwecansetthe
BackgroundColortoblack,adjusttheSizeandthePositionlikeshown
http://noobtuts.com/unity/2dsnakegame
2/21
12/06/2015
noobtutsUnity2DSnakeTutorial
inthefollowingimage:
Note:Sizeispre ymuchthezoomfactor.
AddingBorders
Wewilluseonehorizontalandoneverticalwhitelineimageforour
borders:
border_horizontal.png
border_vertical.png
Note:rightclickeachlink,selectSaveAs...andsavetheimagesinthe
projectsAssetsfolder.
OncewehavetheminourProjectsAssetsfolder,wecanselectthemin
UnitysProjectArea:
AfterwardswecanchangetheirImportSe ingsintheInspectorto
makethemappearintherightsizewiththerightlooks:
http://noobtuts.com/unity/2dsnakegame
3/21
12/06/2015
noobtutsUnity2DSnakeTutorial
Note:PixelsPerUnitistheratiobetweenonepixelintheimageandoneunit
intheworld.TheSnakewillhaveasizeof1x1pixel,whichshouldbe1unitin
thegameworld.ThisiswhywewilluseaPixelsPerUnitvalueof1forallour
textures.
Nowwecandrageachborderimageintothescenetwiceandposition
themsotheyformonerectangularborder:
Note:thehorizontalborderimageisusedforthetopandbo omborders.The
verticalborderimageisusedfortheleftandrightborders.
LetsrenametheborderstoBorderTop,BorderBo om,BorderLeftand
BorderRight.WewillselectoneafteranotherintheHierarchyandthen
eitherpressF2orrightclickitandselectRename.Hereistheresult:
http://noobtuts.com/unity/2dsnakegame
4/21
12/06/2015
noobtutsUnity2DSnakeTutorial
Rightnowthebordersarejustimagesinthegame.Theymaylooklike
borders,buttheyarenotpartofthephysicalworldjustyet.Ifwewant
theSnaketocollidewiththeborders,thenwehavetoaddCollidersto
them.WecandosobyrstselectingallthebordersintheHierarchy:
Rightnowthebordersarejustimages,theyarentreallyborders.The
snakecouldwalkrightthroughthembecausetheyarenotpartofthe
physicsworldyet.LetstakealookattheInspectorandselectAdd
Component>Physics2D>BoxCollider2D.Andsincewehaveall
bordersselectedrightnow,thiswilladdaBoxCollider2Dtoeachof
them:
Andthatsallthereistoit.Wejustcreatedthebordersforourgame
http://noobtuts.com/unity/2dsnakegame
5/21
12/06/2015
noobtutsUnity2DSnakeTutorial
withoutwritingasinglelineofcode,thankstothispowerfulgame
engine.
CreatingtheFoodPrefab
Wedontwantoursnaketogethungry,soletsrandomlyspawnsome
foodinthegame.Asusualwewillstartwithafoodimage,inourcasea
coloredpixel:
food.png
Note:rightclickonthelink,selectSaveAs...andsaveitintheprojects
Assetsfolder.
WewillusethefollowingImportSe ingsforthefoodimage:
Alright,letsdragthefoodimageintotheScenetocreateaGameObject:
http://noobtuts.com/unity/2dsnakegame
6/21
12/06/2015
noobtutsUnity2DSnakeTutorial
TheSnakeshouldreceivesomekindofinformationwheneveritcollides
withfood.Thismeansthatthefoodhastobepartofthephysicsworld,
whichcanbedonewithaCollider.
AGameObjectwithoutaColliderisjustavisualthing,itsnotpartofthe
physicsworld.AGameObjectwithaColliderispartofthephysics
world,justlikeawall.Itwillcauseotherthingstocollidewithit,andit
willtriggertheOnCollisionEnter2Devent.AGameObjectwitha
ColliderthathasIsTriggercheckedwillnotcauseotherthingsto
collidewithit,butitwillstilltriggertheOnTriggerEnter2Devent.
TheSnakeshouldgetnotiedwhenitwalksthroughfood,butitsnot
supposedtocollidewithitlikeifthefoodwasawall.Soletsselectthe
foodintheHierarchyandthenchooseAddComponent>Physics2D
>BoxCollider2DintheInspectorandenableIsTrigger:
Okay,nowwedontwantthefoodtobeintheScenefromthe
beginning.InsteadwewantaPrefabsothatwecanInstantiateit
wheneverweneedit.InordertocreateaPrefab,allwehavetodois
renamethefoodtoFoodPrefabandthendragitfromtheSceneintothe
ProjectArea:
http://noobtuts.com/unity/2dsnakegame
7/21
12/06/2015
noobtutsUnity2DSnakeTutorial
NowwecandeletetheFoodPrefabGameObjectfromtheHierarchy,
becausewedontwantittobeinthegameworldjustyet.
SpawningFood
Letsspawnnewfoodatsomerandompositioneveryfewseconds.This
kindofbehaviorcanbeimplementedwithaScript,soletscreatea
SpawnFoodScript.TheScriptshouldbeintheSceneallthetime,sowe
willkeepitsimpleandaddittotheMainCamera(becauseitwillbeinthe
Sceneallthetime,too).LetsselecttheMainCameraintheHierarchyand
thenclickonAddComponent>NewScript,nameitSpawnFoodand
selectCSharpforthelanguage:
AfterwardswewilldoubleclickitintheProjectAreatoopenit:
http://noobtuts.com/unity/2dsnakegame
8/21
12/06/2015
noobtutsUnity2DSnakeTutorial
usingUnityEngine;
usingSystem.Collections;
publicclassSpawnFood:MonoBehaviour{
//Usethisforinitialization
voidStart(){
//Updateiscalledonceperframe
voidUpdate(){
}
}
WewontneedtheUpdatefunction,soletsremoveit:
usingUnityEngine;
usingSystem.Collections;
publicclassSpawnFood:MonoBehaviour{
//Usethisforinitialization
voidStart(){
}
}
OurScriptneedstoknowwherethefoodPrefabis.Wewilladdapublic
variableoftypeGameObject:
usingUnityEngine;
usingSystem.Collections;
publicclassSpawnFood:MonoBehaviour{
//FoodPrefab
publicGameObjectfoodPrefab;
//Usethisforinitialization
voidStart(){
}
}
Thefoodshouldbespawnedwithintheborders,notoutside.Sowewill
alsoneedavariableforeachoftheborderssothatourScriptknows
theirpositions:
usingUnityEngine;
usingSystem.Collections;
publicclassSpawnFood:MonoBehaviour{
//FoodPrefab
publicGameObjectfoodPrefab;
//Borders
publicTransformborderTop;
publicTransformborderBottom;
publicTransformborderLeft;
publicTransformborderRight;
//Usethisforinitialization
voidStart(){
http://noobtuts.com/unity/2dsnakegame
9/21
12/06/2015
noobtutsUnity2DSnakeTutorial
}
}
Note:theyarealreadyoftypeTransformsowedonthavetowrite
borderTop.transform.positionallthetime.Insteadwewillbeabletoaccess
theirpositionslikeborderTop.position.
LetscreatetheSpawnfunctionthatspawnsonepieceoffoodwithinthe
borders.Atrstwewillchoosethexpositionsomewhererandomly
betweentheleftandrightborder.Thenwewillchoosetheyposition
randomlybetweenthetopandbo omborder.Afterwardswewill
instantiatethefoodPrefabatthatposition:
//Spawnonepieceoffood
voidSpawn(){
//xpositionbetweenleft&rightborder
intx=(int)Random.Range(borderLeft.position.x,
borderRight.position.x);
//ypositionbetweentop&bottomborder
inty=(int)Random.Range(borderBottom.position.y,
borderTop.position.y);
//Instantiatethefoodat(x,y)
Instantiate(foodPrefab,
newVector2(x,y),
Quaternion.identity);//defaultrotation
}
Note:xandyareroundedvia(int)tomakesurethatthefoodisalways
spawnedatapositionlike(1,2)butneveratsomethinglike(1.234,2.74565).
NowletsmakesurethatourScriptcallstheSpawnfunctioneveryfew
seconds.WecandosobyusingInvokeRepeating:
//Usethisforinitialization
voidStart(){
//Spawnfoodevery4seconds,startingin3
InvokeRepeating("Spawn",3,4);
}
Hereisourfullscript:
usingUnityEngine;
usingSystem.Collections;
publicclassSpawnFood:MonoBehaviour{
//FoodPrefab
publicGameObjectfoodPrefab;
//Borders
publicTransformborderTop;
publicTransformborderBottom;
publicTransformborderLeft;
publicTransformborderRight;
//Usethisforinitialization
voidStart(){
//Spawnfoodevery4seconds,startingin3
InvokeRepeating("Spawn",3,4);
http://noobtuts.com/unity/2dsnakegame
10/21
12/06/2015
noobtutsUnity2DSnakeTutorial
}
//Spawnonepieceoffood
voidSpawn(){
//xpositionbetweenleft&rightborder
intx=(int)Random.Range(borderLeft.position.x,
borderRight.position.x);
//ypositionbetweentop&bottomborder
inty=(int)Random.Range(borderBottom.position.y,
borderTop.position.y);
//Instantiatethefoodat(x,y)
Instantiate(foodPrefab,
newVector2(x,y),
Quaternion.identity);//defaultrotation
}
}
IfwesavetheScriptandselecttheMainCamerathenwecanseethatall
ourpublicvariablesarenowshownintheInspector.Theyarestill
None,soletsdragtheFoodPrefabfromtheProjectAreaintotheFood
PrefabvariableandtheBordersfromtheHierarchyintotheir
correspondingslots:
Note:wecandragsomethingintoaScriptsvariablebyliterallydraggingit
withthemousefromtheHierarchyorProjectAreaintothoseslotthingsthat
canbeseenintheabovepicture.
Alright,nowitstimetopressPlayandwaitafewseconds.Weshould
beabletoseesomenewfoodspawninbetweentheborders:
http://noobtuts.com/unity/2dsnakegame
11/21
12/06/2015
noobtutsUnity2DSnakeTutorial
CreatingtheSnake
Letsnishthemainpartoftheourgame:theSnake.Asusualwewill
startbydrawingthesnakeimage,whichisjusta1x1pixeltexture:
snake.png
Note:rightclickonthelink,selectSaveAs...andsaveitintheprojects
Assetsfolder.
WewillusethefollowingImportSe ingsforit:
NowwecandragthesnakeimageintothemiddleoftheScene:
SofaritsjusttheSnakeshead,soletsrenameittoHeadtokeepthings
clean:
http://noobtuts.com/unity/2dsnakegame
12/21
12/06/2015
noobtutsUnity2DSnakeTutorial
Thesnakeshouldbepartofthephysicsworld,whichmeansthatwe
needtoaddaCollidertoitagain,soletsselectAddComponent
>Physics2D>BoxCollider2D:
Note:theColliderhasthesize(0.7,0.7)insteadof(1,1)sothatitdoesnt
collidewithotherpartsofthesnakethatarerightnexttoit.Wesimplywantto
giveUnitysomespace.
Nowthesnakeisalsosupposedtomovearound.Asaruleofthumb,
everythinginthephysicsworldthatissupposedtomove,needsa
Rigidbody.ARigidbodytakescareofthingslikegravity,velocityand
movementforces.WecanaddonebyselectingAddComponent
>Physics2D>Rigidbody2D.Wewillusethefollowingse ingsforit:
Notes:
TheRigidbodysGravityScaleis0becausewedontwantthesnake
tofalltowardsthebo omofthescreenallthetime.
TheIsKinematicoptiondisablesthephysicalbehaviorofthe
Rigidbody,soitdoesntreacttogravityorcollisions.Weonlyneed
toknowifthesnakecollidedwithsomething.WedontneedUnitys
physicstopushthingsaroundincaseofcollisions.Moreinfo:
Rigidbody2DUnityDocs.
Thenalsnakewillconsistofmanyli leelements.Therewillalwaysbe
theHeadatthefrontandthentherewillbeseveralTailelementslike
here:
http://noobtuts.com/unity/2dsnakegame
13/21
12/06/2015
noobtutsUnity2DSnakeTutorial
ooooox
TheonlydierencebetweentheTailelementsandtheHeadisthatthe
headdoesallthethinking.WewilladdaScripttoitlater.
LetsdragthesnakeHeadfromtheHierarchyintotheProjectAreato
createaPrefabandthennameitTailPrefabsowecanloaditwhenever
thesnakegrows:
Note:someUnityversionswillautomaticallyrenameGameObjectinthe
Hierarchytoo,somakesurethattheoneintheHierarchyisstillnamedHead.
Alright,letsselectthesnakeHeadintheHierarchyagainandclickon
AddComponent>NewScript,nameitSnakeandselectCSharpasthe
language:
WecanopentheScriptbydoubleclickingitintheProjectArea:
usingUnityEngine;
usingSystem.Collections;
publicclassSnake:MonoBehaviour{
//Usethisforinitialization
voidStart(){
//Updateiscalledonceperframe
voidUpdate(){
}
}
LetsmodifythetopoftheScripttoincludesomeListfunctionalitythat
wewillneedlateron:
usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingSystem.Linq;
publicclassSnake:MonoBehaviour{
//Usethisforinitialization
voidStart(){
http://noobtuts.com/unity/2dsnakegame
14/21
12/06/2015
noobtutsUnity2DSnakeTutorial
//Updateiscalledonceperframe
voidUpdate(){
}
}
TheSnakeshouldalwaysmoveexactlyoneunitintowhateverdirection
itwantstomove.NowifwewouldallowittomoveineveryUpdate
call,thenitwouldbereallyfast.Insteadwewillonlyallowmovement
every300millisecondsbyusingUnitysInvokeRepeatingfunction.Its
likewecreateourownUpdatemethodthatonlygetscalledevery300
msinsteadofeveryframe:
usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingSystem.Linq;
publicclassSnake:MonoBehaviour{
//Usethisforinitialization
voidStart(){
//MovetheSnakeevery300ms
InvokeRepeating("Move",0.3f,0.3f);
}
//Updateiscalledonceperframe
voidUpdate(){
voidMove(){
//DoMovementStuff..
}
}
TheSnakeshouldalwaysbemovingintosomedirection,itshould
neverstandstill.Soletsdeneadirectionvariableanduseittomove
thesnakeintheMovefunction:
usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
usingSystem.Linq;
publicclassSnake:MonoBehaviour{
//CurrentMovementDirection
//(bydefaultitmovestotheright)
Vector2dir=Vector2.right;
//Usethisforinitialization
voidStart(){
//MovetheSnakeevery300ms
InvokeRepeating("Move",0.3f,0.3f);
}
//Updateiscalledonceperframe
voidUpdate(){
http://noobtuts.com/unity/2dsnakegame
15/21
12/06/2015
noobtutsUnity2DSnakeTutorial
voidMove(){
//Moveheadintonewdirection
transform.Translate(dir);
}
}
Note:transform.Translatemeansaddthisvectortomyposition.
ThedirectionvariableisoftypeVector2,whichmeansthatithasanx
andyvalue.Thefollowingimageshowsdierentdirectionsfora
Vector2:
IfwepressplaythenwecanalreadyseetheSnakemovetotheright:
Theusershouldbeabletochangethemovementdirectionbypressing
oneofthearrowkeys.Nowwecouldjustcheckforkeypressesinour
Movefunction,butthatwouldmakethegamefeellaggybecausethen
wewouldonlydetectkeypressesevery300ms.Insteadwewillusethe
Updatefunctiontodetectkeypressesallthetime:
//UpdateiscalledonceperFrame
voidUpdate(){
//MoveinanewDirection?
if(Input.GetKey(KeyCode.RightArrow))
http://noobtuts.com/unity/2dsnakegame
16/21
12/06/2015
noobtutsUnity2DSnakeTutorial
dir=Vector2.right;
elseif(Input.GetKey(KeyCode.DownArrow))
dir=Vector2.up;//'up'means'down'
elseif(Input.GetKey(KeyCode.LeftArrow))
dir=Vector2.right;//'right'means'left'
elseif(Input.GetKey(KeyCode.UpArrow))
dir=Vector2.up;
}
Note:ifyouarenotsurewhyweusedUpdateandMoveinsteadofjust
UpdateorjustMove,feelfreetoputthecodefromMoveintoUpdateorthe
codefromUpdateintoMove,thenyouwillseethatthesnakemovesrapidly
fastorthatthekeypressesaredetectedonlyrarely.
IfwepressplaythenwecannowmovetheSnakewiththearrowkeys:
TheSnakesTail
LetsthinkabouthowtheSnakestailwillwork.Firstofall,letsassume
wehaveasnakewithoneheadandthreetailelements:
ooox
Nowassoonastheheadmovestotheright,theobviousthingwouldbe
tomoveeverytailelementtowhereitsprevioustailelementwas,like
this:
step1:ooox//snakedidn'tmoveyet
step2:ooox//headmovedtotheright
step3:ooox//firsttailfollows
step4:ooox//secondtailfollows
step5:ooox//thirdtailfollows
Thiswouldwork,butitwouldalsobesomecomplicatedcode.Letsuse
aneatli letricktomakeourliveseasier.Insteadofmovingonetail
elementafteranother,wewillsimplymovethelasttailelementintothe
gaplikehere:
step1:ooox//snakedidn'tmoveyet
step2:ooox//headmovedtotheright
step3:ooox//lasttailelementmovedintothegap
http://noobtuts.com/unity/2dsnakegame
17/21
12/06/2015
noobtutsUnity2DSnakeTutorial
Nowthatsoundslikeaneasyalgorithm.Ineverymovementcall,allwe
havetodoismovethelasttailelementtowheretheheadwasbefore.
Atrstwewillneedsomekindofdatastructuretokeeptrackofallthe
tailelementsthatwewilladdlateron:
//KeepTrackofTail
List<Transform>tail=newList<Transform>();
Note:itsreallyimportanttoaddusingSystem.Collections.Generic;and
usingSystem.Linq;tothetopinorderforliststowork.
Letsgettothecodethattakesthelasttailelement,removesitfromthe
backandputsitintothegapmentionedabove:
voidMove(){
//Savecurrentposition(gapwillbehere)
Vector2v=transform.position;
//Moveheadintonewdirection(nowthereisagap)
transform.Translate(dir);
//DowehaveaTail?
if(tail.Count>0){
//MovelastTailElementtowheretheHeadwas
tail.Last().position=v;
//Addtofrontoflist,removefromtheback
tail.Insert(0,tail.Last());
tail.RemoveAt(tail.Count1);
}
}
Note:Translatesimplymeansaddthisvectortomyposition.Afterwardswe
checkifthereisanythinginthetaillist,inwhichcasewechangethelasttail
elementspositiontothegapposition(wheretheheadwasbefore).Wealsohave
tokeepourlistorder,hencetheInsertandRemoveAtcallsattheend.They
makesurethatthelasttailelementisnowtherstelementinthelist,too.
AndthatwastheonlyslightlycomplicatedpartofourUnity2DSnake
Tutorial.Nowwearealmostdone.
FeedingtheSnake
WewillusetheOnTriggerEnter2Dfunctiontoreceivecollision
information(whichwillhappenwheneverthesnakewalksintofoodorintoa
border).
Wheneveritrunsintofood,wewillusetheexactsamemechanicsthat
weusedforourmovementabove,exceptthatthistimeinsteadof
removingthelasttailelementandmovingitintothegap,wewillonly
Instantiateanewelementintothegap:
ooox//gap
oooox//gapfilledwithnewelement
ItsimportanttounderstandthatwewillnotmaketheSnakelonger
http://noobtuts.com/unity/2dsnakegame
18/21
12/06/2015
noobtutsUnity2DSnakeTutorial
immediatelyafteriteatssomething.Justlikewithourarrowkey
presses,wewillwaituntilitactuallymoves.Thereforewewillneeda
newvariablethatwewillsettotruewhenevertheSnakeatesomething:
//Didthesnakeeatsomething?
boolate=false;
WewillalsoneedapublicvariablethatletsusassigntheTailPrefab
lateron:
//Didthesnakeeatsomething?
boolate=false;
//TailPrefab
publicGameObjecttailPrefab;
Note:thetwovariablesaredenedatthetopofourSnakescript.
NowletsgettotheOnTriggerEnter2Dfunction.Thisonewillbe
straightforwardagain.WewillndoutiftheSnakecollidedwithfood,
inwhichcasewesettheatevariabletotrueanddestroythefood.Ifit
didntcollidewithfood,theniteithercollidedwithitselforwitha
border:
voidOnTriggerEnter2D(Collider2Dcoll){
//Food?
if(coll.name.StartsWith("FoodPrefab")){
//GetlongerinnextMovecall
ate=true;
//RemovetheFood
Destroy(coll.gameObject);
}
//CollidedwithTailorBorder
else{
//ToDo'Youlose'screen
}
}
Note:weusecoll.name.StartsWithbecausethefoodiscalled
FoodPrefab(Clone)afterinstantiatingit.Themoreelegantwaytondoutif
collisfoodornotwouldbebyusingaTag,butforthesakeofsimplicitywe
willusestringcomparisoninthisTutorial.
Alright,letsmodifyourMovefunctionsoitmakestheSnakelonger
wheneverateistrue:
voidMove(){
//Savecurrentposition(gapwillbehere)
Vector2v=transform.position;
//Moveheadintonewdirection(nowthereisagap)
transform.Translate(dir);
//Atesomething?TheninsertnewElementintogap
if(ate){
//LoadPrefabintotheworld
GameObjectg=(GameObject)Instantiate(tailPrefab,
v,
Quaternion.identity);
http://noobtuts.com/unity/2dsnakegame
19/21
12/06/2015
noobtutsUnity2DSnakeTutorial
//Keeptrackofitinourtaillist
tail.Insert(0,g.transform);
//Resettheflag
ate=false;
}
//DowehaveaTail?
elseif(tail.Count>0){
//MovelastTailElementtowheretheHeadwas
tail.Last().position=v;
//Addtofrontoflist,removefromtheback
tail.Insert(0,tail.Last());
tail.RemoveAt(tail.Count1);
}
}
Note:allwedidwascheckifateistrue,thenInstantiatethetailprefabatthe
positionvwiththedefaultrotation(Quaternion.identity).Afterwardsweadd
ittothetaillistandresettheateag.Therestofthecodewasalreadythere.
NowwecanselectthesnakeHeadintheHierarchy,takealookatthe
InspectoranddragtheTailPrefabfromtheProjectAreaintotheScript:
IfwepressPlaythenwecannowplayaniceroundofSnake:
Summary
SnakeisoneawesomegameforaUnityTutorial.Thereisalotofvalue
inunderstandinghowtodopixelexactgameslikethisandhowtoadd
movementwithInvokeRepeating.Yetagainwesawhowamazingly
easy2DgamesarewithUnitys2Dfeaturesthatwereintroducednot
verylongago.
http://noobtuts.com/unity/2dsnakegame
20/21
12/06/2015
noobtutsUnity2DSnakeTutorial
Nowitsuptothereadertomakethegamefun!Therearetonsof
improvementstobemadelikeawin/losescreen,abe erlookingsnake
texture,multiplelevels,powerups,increasingspeed,highscores,
multiplayerandsoon.
DownloadSourceCode&ProjectFiles
TheUnity2DSnakeTutorialsourcecode&projectlescanbe
downloadedbyPremiummembers.
AllTutorials.AllSourceCodes&ProjectFiles.OnetimePayment.
GetPremiumtoday!
20122015noobtuts.com
http://noobtuts.com/unity/2dsnakegame
21/21