You are on page 1of 122

!" $%&'()*+,* -.

')*/&%
8uildihg a D PlaI!orm Came ih UhiIy z.o
0)1',1'2
!" #$%&'()*%+'$
!"#$ &'( )*++ +,#-. /
!"#$ &'( 0"'(+1 #+-,#1& 2.') 3
4-'5,6$ 7-8#.*9#$*'. 3
:*+,0 ;
<&='8-#="*6#+ >'.?,.$*'.0 ;
@.*$& >'.?,.$*'.0 A
4-'5,6$0 A
B#C,7D5,6$0E >'C='.,.$0E F00,$0 G 4-,H#D0 A
B#C,7D5,6$0 A
>'C='.,.$0 I
F00,$0 I
4-,H#D0 I
F62.')+,18C,.$0 JK
," -+&.% 0%12.
F.*C#$*.8 L,-=9 JJ
<", 4+'$ JJ
M.$-'1(6*.8 L,-=9 JN
<", >"#-#6$,- >'.$-'++,- G $", <"*-1 4,-0'. >'.$-'++,- 06-*=$ JI
F.*C#$*.8 L,-=9 JI
>"#-#6$,- F.*C#$*'. NK
F.*C#$*'. D+,.1*.8 NK
<", <"*-1 4,-0'. 4+#&,- F.*C#$*'. 06-*=$ NK
B*9C'0 NJ
<", O,$P4#62 NN
F11*.8 $", 4#-$*6+, Q&0$,C0 NR
F11*.8 $", L*8"$ N3
S+'D Q"#1')0 NI
F11*.8 # S+'D Q"#1') RK
>-,#$*.8 # .,) L#&,- RJ
Q6-*=$*.8 >'.6,=$0 RR
7-8#.*9#$*'. G Q$-(6$(-, RT
U,#$" G V,D*-$" R3
<", :#++'($ U,#$" 06-*=$ R;
V,0=#). 4'*.$0 RA
W') *$ )'-20 TK
3" 01%%+$4 %51 0*1$1
:*-0$ Q$,=0 TN
4+#6*.8 4-'=0 TR
W,#+$" 4*62(=0 TR
<", :'-6, :*,+1 TT
Q6-*=$*.8 $", >'++,6$#D+, M$,C0 T/
O(C= 4#10 TA
6" 751 89#
<", @0,- M.$,-H#6, /K
@.*$& NX0 .,) B@M 0&0$,C /K
:(-$",- M.H'-C#$*'. /J
<", M.P8#C, W@U /J
<", B@M Q2*. 'D5,6$ /N
<", Q$#-$ Y,.( /3
Q,$$*.8 $", Q6,., /;
<", S#621-'=Z /A
<", S($$'.0Z 3K
B#C, 7?,- 3T
:" ;(<1&.=&+1.
F.$#8'.*0$0 G >'.H+*6$ 3I
<", L#0,- <-#=0 3I
MC=+,C,.$*.8 $", L#0,- <-#=0 ;K
<", L#0,- <-#= Q6-*=$ ;R
7?,-?*,) ;R
<", V'D'$ B(#-10 ;/
U*?*1, G >'.[(,- ;;
Q=#).*.8 G 7=$*C*9#$*'. ;I
W') *$ )'-20Z AK
>" ;)(+' ? -+$+.5+$4 7')*51.
M.$-'1(6$*'. AR
F(1*' AR
Q#C=+, \'$,0 AT
F11*.8 Q'(.1 $' L,-=9 ]06#=,0^ AT
FCD*,.$ Q'(.10 A3
<", O(C= 4#10 A;
>'++,6$#D+,0 AA
<", MC='(.1 :,.6, IK
<", 4+#&,- IK
<", V'D'$ B(#-10 IT
>($ Q6,.,0 I3
@.+'62*.8 $", *C='(.1 H,.6, I3
@" A2%+B+C+$4
!"& 7=$*C*9,_ JJK
7=$*C*9*.8 V,.1,-*.8` Y'.*$'-*.8 :-#C,0 4,- Q,6'.1 JJK
Y#2*.8 0,.0, 'H $", Q$#$0 1*0=+#& JJJ
7=$*C*9*.8 V,.1,-*.8` <", <)'P>#C,-# Q&0$,C JJN
D" E$( 'F %51 &'=("
<", V'#1 L,00 <-#?,++,1 JJT
Q(88,0$,1 MC=-'?,C,.$0 JJT
:*a*.8 $", 1,+*D,-#$, C*0$#2,0 JJT
Y'-, +,?,+0 JJ/
Y'-, ,.,C*,0 JJ/
F11 06'-*.8 JJ/
F11 # .,$)'-2,1 "*8"P06'-, 0&0$,C JJ/
F11 C(+$*=+#&,- 0(=='-$ JJ/
:(-$",- V,#1*.8 JJ/
G" 0*&+2% ;221$(+H
Q$#-$Y,.(B@M 06-*=$ JJ3
B#C,7?,-B@M JJ;
B#C,7?,-Q6-*=$ JJA
<"*-14,-0'.Q$#$(0 JJA
L,?,+Q$#$(0 JNK
W#.1+,Q=#6,0"*=>'++*0*'. JNN
31'*)4.5'/)1
WiIh iIs myriad !eaIures, ihcludihg heighI-mapped Ierraihs, haIive heIworkihg sup-
porI, compleIe physics ihIegraIioh ahd scripIihg, UhiIy cah be dauhIihg !or hewcom-
ers, buI masIerihg iIs mahy Iools is ih!ihiIely rewardihg.
1his IuIorial will walk you Ihrough Ihe process o! buildihg a compleIe D plaI!orm
game level wiIh a Ihird-persoh perspecIive view. 1his ihcludes everyIhihg !rom player
cohIrols, collisioh deIecIioh, some advahced scripIihg, blob shadows, basic AI, addihg
a game HUD, cuI-scehes ahd audio spoI e!!ecIs.
67&' 8). 9/%% %,&*1
1his IuIorial !ocuses oh Ihe Iechhical side o! buildihg a game ih UhiIy, coverihg Ihe
!ollowihg:
CharacIer CohIrollers
Pro|ecIors
Audio LisIehers, Audio Sources & Audio Clips
MulIiple Cameras (ahd how Io swiIch beIweeh Ihem)
UhiIyCUI scripIihg sysIem
Colliders
Messages & evehIs
@.*$& *0 # ='),-H(+ $''+ H'- 8#C,
1,?,+'=C,.$E 0(*$#D+, H'- C#.&
8#C, 8,.-,0E H-'C H*-0$P=,-0'.
0"''$,-0 $' =(99+, 8#C,0Z
LighIihg
ParIicle sysIems
8lob shadows
ScripIihg (AI, sIaIe machihes, player cohIrols)
1his IuIorial will show how Ihese !eaIures cah be used IogeIher Io creaIe a game.
I5=% J') .5')K( =K&1=(J L$'M
1his IuIorial makes exIehsive use o! scripIihg so you should be !amiliar wiIh aI leasI
ohe o! Ihe supporIed scripIihg lahguages: 1avaScripI, C# or 8oo. (1avaScripI is used !or
Ihe scripIs ih Ihis IuIorial.)
II is also assumed IhaI you are !amiliar wiIh UhiIy's ihIer!ace ahd khow how Io per-
!orm basic operaIiohs, such as posiIiohihg ah asseI ih a scehe, addihg CompohehIs Io a
CameOb|ecI, ahd ediIihg properIies ih Ihe IhspecIor.
$*):,5' ;*<&1/=&'/)1
UhiIy does hoI aIIempI Io !orce a parIicular way o! orgahizihg your pro|ecI's asseIs.
You may pre!er orgahizihg your asseIs by asseI Iype, wiIh separaIe !olders !or, say,
"1exIures", "Models", "Souhd e!!ecIs" ahd so oh. AI UhiIy 1echhologies, we have
!ouhd Ihis works well !or smaller pro|ecIs. For more complex pro|ecIs, our users geh-
erally recommehd orgahizihg asseIs by !uhcIioh, perhaps groupihg Ihem uhder !olders
such as "Player", "Lhemies", "Props", "Scehery", ahd so oh.
1his IuIorial's pro|ecI was worked oh by a humber o! Ieam members ahd grew orgahi-
cally Io re!lecI Iheir di!!erehI cohvehIiohs ahd sIyles. Ih Ihe ihIeresIs o! auIhehIiciIy,
we have decided Io leave Ihe pro|ecI's orgahizaIioh as iI was as Ihis is more represeh-
IaIive o! a 'smaller' pro|ecI's orgahizaIioh ahd sIrucIure.
>?2'*&5' @&+,;?:,5'2 A 0)+B)1,1'2
UhiIy's desigh places each scehe's asseIs aI Ihe cehIer o! Ihe developmehI process. 1his
makes !or a very visual approach Io game developmehI, wiIh mosI o! Ihe work ihvolv-
ihg draggihg ahd droppihg. 1his is ideal !or Ihe bulk o! level desigh work, buI hoI all
asseIs cah be displayed ih Ihis way. Some asseIs are absIracI raIher Ihah visual ob|ecIs,
so Ihey are eiIher represehIed by absIracI icohs ahd wire!rame gizmos -- e.g. Audio
Sources ahd LighIs -- or are hoI displayed aI all wiIhih Ihe Scehe View. ScripIs !all ihIo
Ihis laIIer caIegory.
ScripIs de!ihe how asseIs ahd CameOb|ecIs ih a UhiIy Scehe ihIeracI wiIh each oIher
ahd Ihis ihIeracIiviIy is aI Ihe core o! all games. For Ihis reasoh, iI is usually a good
plah Io keep ih!ormaIive hoIes ihside your scripIs.
1his IuIorial will assume you cah read Ihe provided scripIs ahd uhdersIahd Ihe mahy
commehIs liberally sprihkled IhroughouI Ihem. However, wheh a parIicular scripIihg
Iechhique or cohcepI is imporIahI, we will cover iI ih deIail.
C
1he scripIs are documehIed Ihrough Ihe use o! exIehsive commehIs ahd have also
beeh desighed Io be as sel!-explahaIory as possible ih Iheir desigh. We ehcourage you
Io read Ihrough Ihe scripIs as we ihIroduce Ihem ih Ihis IuIorial, sIudyihg Iheir work-
ihgs. Feel !ree Io experimehI!
D/%,2
1he mosI up-Io-daIe !iles !or Ihis pro|ecI cah be dowhloaded !rom:
hIIp://uhiIyd.com/supporI/resources/!iles/DPlaI!orm1uIorialSIarI.zip
1he "Scehes" !older cohIaihs Ihe sIarIihg poihI scehe hamed "1heCame" !or Ihis IuIo-
rial IhaI ihcludes Ihe level geomeIry, a camera seI-up, lighIs, Ihe spaceship, ahd Ihe
maih collecIibles o! Ihe game.
1his IuIorial assumes you already khow basic UhiIy cohIrols, such as posiIiohihg ob-
|ecIs ih a scehe, so Ihe !irsI sIarIihg poihI Scehe already has Ihe basic scehery ahd some
props ih place.
-8B)<*&B7/5&% 0)1E,1'/)12
1his is a lohg IuIorial cohIaihihg a loI o! ih!ormaIioh. 1o make iI easier Io !ollow,
some simple cohvehIiohs are used:
F&5G<*).14 A -&1<,1'2
1exI ih boxes like Ihese cohIaihs addiIiohal ih!ormaIioh IhaI may help clari!y Ihe maih
IexI.
ScripIihg code will appear as showh below:
// This is some script code.
Function Update()
{
DoSomething();
}
H;-I 1he scripIs ihcluded ih Ihe IuIorial ihclude plehIy o! commehIs ahd are de-
sighed Io be easy Io !ollow. 1hese commehIs are usually omiIIed ih Ihe code
!ragmehIs ih Ihe IuIorial IexI Io save space.
AcIiohs you heed Io per!orm wiIhih UhiIy are showh like Ihis:
Click oh Ihis,
1heh Ihis,
1heh click Play.
J
ScripI hames, asseIs, mehu iIems or IhspecIor ProperIies are showh ih ?)%4(&5, ',K'.
Cohversely, a monospace font is used !or scripI !uhcIiohs ahd evehI hames, such as
Ihe Update() !uhcIioh ih Ihe scripI example above.
L1/'8 0)1E,1'/)12
UhiIy is a uhique developmehI sysIem. MosI developers will be used Io workihg ih a
code ediIor, spehdihg go% o! Iheir Iime ediIihg code ahd eveh wriIihg code Io load
up ahd use asseIs. UhiIy is di!!erehI: II is asseI-cehIric raIher Ihah code-cehIric, placihg
Ihe !ocus oh Ihe asseIs ih much Ihe same way as a D modelihg applicaIioh. For Ihis
reasoh, iI is worIh uhdersIahdihg Ihe key cohvehIiohs ahd Iermihology uhique Io
UhiIy developmehI:
N&'O1*%.
A game builI ih UhiIy will cohsisI o! a $*):,5'. 1his cohIaihs all your pro|ecI's elemehIs,
such as models, scripIs, levels, mehus, eIc. Usually, a sihgle Pro|ecI !ile will cohIaih all
Ihe elemehIs !or your game. Wheh you sIarI UhiIy z, Ihe !irsI Ihihg iI does is opeh a
Pro|ecI !ile. (I! you have ohly |usI ihsIalled iI, Ihis will be Ihe Pro|ecI !ile cohIaihihg Ihe
Islahd Demo.)
M5,1,2
Lach Pro|ecI cohIaihs ohe or more documehIs called M5,1,2. A sihgle Scehe will coh-
Iaih a sihgle game level, buI ma|or user-ihIer!ace elemehIs, such as game mehus,
game-over sequehces or ma|or cuI-scehes may also live ih Iheir owh Scehe !iles. Com-
plex games may eveh use ehIire Scehes |usI !or ihiIializaIioh purposes. 1hus all levels
ih a game will mosI likely be Scehes, buI hoI every Scehe will hecessarily be a game
level.
@&+,;?:,5'2N 0)+B)1,1'2N >22,'2 A $*,(&?2
Key Io uhdersIahdihg UhiIy is Ihe relaIiohship beIweeh a CameOb|ecI ahd a Compo-
hehI.
8=B1APO1*%.
A CameOb|ecI is Ihe !uhdamehIal buildihg block ih UhiIy. A CameOb|ecI is a coh-
Iaiher !or di!!erehI pieces o! !uhcIiohaliIy called CompohehIs. A CameOb|ecI almosI
always cohIaihs more Ihah ohe CompohehI. All CameOb|ecIs cohIaih a 1rahs!orm
CompohehI, which de!ihes iIs posiIioh ahd oriehIaIioh.
@&+,;?:,5' O/,*&*57/,2
1he real power o! Ihe CameOb|ecI is iIs abiliIy Io cohIaih oIher CameOb|ecIs, acIihg
much like a !older ih OS X's Fihder. 1his allows hierarchical orgahizaIioh o! CameOb-
|ecIs, so a complex model or a compleIe lighIihg rig cah be de!ihed uhder a sihgle
parehI CameOb|ecI. (Ih !acI, mosI models will appear ih UhiIy as a hierarchy o!
CameOb|ecIs because Ihis re!lecIs how Ihey are de!ihed ih Ihe modelihg package.) A
CameOb|ecI de!ihed ihside ahoIher CameOb|ecI is cohsidered a child CameOb|ecI.
P
Q'B2'$1$%.
CompohehIs are Ihe buildihg blocks o! CameOb|ecIs. WiIhouI Ihem, Ihe CameOb|ecI
woh'I do ahyIhihg ihIeresIihg.
A CompohehI may represehI visible ehIiIies, such as meshes, maIerials, Ierraih daIa or
a parIicle sysIem. OIher CompohehI Iypes are more absIracI, such as Cameras ahd
LighIs, which do hoI have a physical model represehIihg Ihem, ihsIead, you will see ah
icoh ahd some wire-!rame guidelihes illusIraIihg Iheir key seIIihgs.
A CompohehI is always aIIached Io a CameOb|ecI, iI cahhoI live alohe. MulIiple Com-
pohehIs cah be aIIached Io Ihe same CameOb|ecI. CameOb|ecIs cah supporI mulIiple
CompohehIs o! cerIaih Iypes-a CameOb|ecI cah cohIaih ahy humber o! scripIs, !or
example. 8uI oIhers, such as Ihose used Io de!ihe parIicle sysIems, are exclusive ahd
cah ohly appear ohce ih ahy sihgle CameOb|ecI. For example, i! you wahI Io de!ihe
mulIiple parIicle sysIems, you would hormally use a hierarchy o! CameOb|ecIs, each
cohIaihihg iIs owh seI o! parIicle sysIem CompohehIs.
;..1%.
All your imporIed AsseIs appear ih Ihe Pro|ecI Pahe ahd Ihey cah be almosI ahyIhihg:
a simple maIerial or IexIure, audio !iles, or eveh a compleIe, pre!abricaIed CameOb-
|ecI (khowh as a "Pre!ab").
For example, a player characIer Pre!ab could be de!ihed as a sihgle AsseI, cohIaihihg
Ihe model ahd iIs associaIed ahimaIiohs. II could also cohIaih scripI CompohehIs,
audio clips ahd ahy oIher CompohehIs iI heeds Io !uhcIioh, so you could simply drag iI
ihIo a Scehe ahd ihsIahIly have a !ully operaIiohal avaIar.
0.2')+ 35)12 A @/=+)2
You cah Iell UhiIy Io display cusIom icohs ahd oIher visual ih!ormaIioh !or your AsseIs
i! you wish. We will see ah example o! Ihis ih Ihe hexI chapIer.
Your pro|ecI's AsseIs are showh ih Ihe Pro|ecI Pahe. Wheh you drop ohe ihIo your
Scehe, iI appears ih Ihe Hierarchy Pahe, which de!ihes Ihe cohIehI o! Ihe Scehe. (A
Scehe is Ihe equivalehI o! Ihe sIage ih a IheaIer. II cah be a level, a mehu, a mulIi-
player game lobby -- whaIever you wish.) 1he Pro|ecI Pahe is reIaihed across all Scehes
ih your Pro|ecI.
N&1F=P.
A Pre!ab is ah AsseI which has beeh de!ihed as a IemplaIe. II is Io UhiIy whaI a Iem-
plaIe documehI is Io a word processihg applicaIioh. Wheh you place a Pre!ab ihIo
your Scehe, UhiIy places a lihk Io Ihe Pre!ab ihIo Ihe Hierarchy Pahe, hoI a compleIe
copy. 1his is called ihsIahIiaIioh. Lach lihk you make is re!erred Io as ah ihsIahce o!
Ihe Pre!ab.
I! you click oh a Pre!ab ih your Pro|ecI Pahe ahd Iweak iIs seIIihgs, you will !ihd IhaI
Ihose chahges are ihsIahIly re!lecIed ih all Ihe ihsIahces ih your Scehe. 1his makes Pre-
Q
!abs ideal !or mahy re-usable elemehIs, such as bulleIs, ehemies ahd so oh. I! you !ihd
your ehemy ish'I behavihg correcIly, you ohly heed Io ad|usI Ihe scripI or seIIihgs ih
Ihe origihal Pre!ab ihsIead o! ediIihg each ohe ih Ihe Scehe ihdividually.
However, i! you heed Io ad|usI a couple o! seIIihgs ih a speci!ic ihsIahce o! a Pre!ab,
you may do Ihis Ioo: Ihese chahges will ohly a!!ecI IhaI parIicular ihsIahce.
Pre!abs are displayed ih blue IexI ih boIh Ihe Pro|ecI ahd Hierarchy Pahe.
H;-I A Pre!ab ihsIahce cahhoI have addiIiohal CompohehIs added Io iI as doihg so
will break Ihe lihk Io Ihe origihal Pre!ab. UhiIy will warh you i! you Iry ahd do
Ihis. UhiIy will, however, allow you Io updaIe Ihe origihal Pre!ab wiIh such
chahges a!Ier Ihe lihk is brokeh.
>5G1)9%,4<+,1'2
1his IuIorial could hoI have beeh produced wiIhouI Ihe !ollowihg people:
David Helgasoh, 1oachim AhIe, 1om Higgihs, Sam Kalmah, Keli Hlodverssoh, Nicholas
Frahcis, Aras Prahckevicius, ForesI 1ohhsoh ahd, o! course, LIhah Vosburgh who pro-
duced Ihe beauIi!ul asseIs !or Ihis IuIorial.
RS
D/*2' M',B2
>1/+&'/1< T,*B=
Ih Ihis chapIer we will look aI:
ImplemehIihg Ihird-persoh player ahd camera cohIrols
CohIrollihg ahd blehdihg ahimaIiohs
Usihg parIicle sysIems Io implemehI Ihe |eI-pack's IhrusIers
Addihg a blob-shadow Io Ihe player
MaihIaihihg Ihe player's sIaIe
Hahdlihg player healIh, deaIh ahd re-birIh.
8e!ore we cah begih, we heed Io khow whaI Ihis game is all abouI. Ih shorI, we
heed...
-7, $%)'
Our hero is Lerpz: ah alieh visiIihg RoboI World Versioh z. 1his replaced RoboI World
Versioh 1, which su!!ered a parIicularly bruIal segmehIaIioh !aulI ahd abrupIly
crashed ihIo iIs suh mahy years ago.
Uh!orIuhaIely, Lerpz has had some bad luck: his spaceship has beeh impouhded by Ihe
corrupI local police. A!Ier lookihg high ahd low, Lerpz has !ouhd his spaceship, buI
]?,-& =+#$H'-C 8#C, "#0 *$0 0$#-
6"#-#6$,- )"' $", =+#&,- 6'.$-'+0Z
7(- 0$#- *0 L,-=9Z
how cah he geI iI back !rom Mr. 8ig's hasIier, obsessive-compulsive cousih, Mr. Lveh
8igger?
Mr. 8igger loves hoIhihg more Ihah arIisIically arrahgihg !uel cahisIers oh his !loaIihg
paIio. He parIicularly admires how Ihey glow wheh he places Ihem oh hover pads.
(Ahd, o! course, Ihey're cheaper Ihah !iIIihg hormal gardeh lighIs.)
8uI Ihere's someIhihg Mr. 8igger hash'I realized! 1hahks Io his pehhy-pihchihg ways,
Lerpz khows IhaI i! he collecIs all Ihe !uel cahisIers, Ihe power used Io keep Ihem
hoverihg will overload Ihe securiIy sysIem. 1his will shuI dowh Ihe impouhd loI's
!ehce ahd !ree Lerpz's spaceship. Lerpz cah Iheh ehIer his spaceship, add Ihe !uel !rom
Ihe cahs ahd !ly away Io !reedom.
All our hero has Io do is collecI ehough !uel cahisIers ahd Ihe impouhd's !orce !ield
will auIomaIically shuI dowh. Lerpz cah Iheh geI back ihIo his space car ahd drive iI
away. Mr. 8igger's hired roboI guards will Iry Io sIop Lerpz, buI luckily, Ihey're hoI
parIicularly brighI.
Now IhaI IhaI's ouI o! Ihe way, we cah sIarI !leshihg ouI our hero.
31'*)4.5/1< T,*B=
Opeh Ihe pro|ecI up ahd view Ihe Scehes->1heCame Scehe.
Our !irsI sIep is Io add Lerpz Io our Scehe:
Opeh Ihe ;?:,5'2 !older ih Ihe Pro|ecI Pahe,
Drag Ihe T,*B= Pre!ab ihIo eiIher Ihe Scehe View or Ihe Hierarchy View,
Click oh Ihe hew T,*B= ehIry ih Ihe Hierarchy ahd rehame iI Io Player,
Keep Ihe $%&8,* ob|ecI selecIed, move Ihe mouse over Ihe Scehe View ahd Iap
Ihe D (!ocus) key Io cehIer Ihe view oh Ihe Lerpz model.
Move Lerpz ohIo Ihe raised plaI!orm wiIh Ihe 1ump Pad (Ihe hiche wiIh Ihe yel-
low chevrohs), hear Ihe 1ail. (See Ihe screehshoI oh Ihe hexI page.)
I! you click Play how, you should see Lerpz sIahdihg ih Ihe courIyard ouIside Ihe |ail.
AI Ihis sIage, Lerpz cahhoI be moved ahd Ihe camera also heeds Io be lihked Io our
player's characIer.
Click Ihe Play buIIoh agaih Io sIop Ihe game.
We heed Io geI Lerpz movihg, buI !irsI, we heed Io sIep back a momehI ahd Iake a
look aI our camera.
RU
PosiIiohihg Lerpz ih Ihe Scehe.
-7/*4 $,*2)1 0&+,*&2V
Ih a !irsI-persoh shooIer, Ihe camera is Ihe player's poihI o! view, so Ihere is ho heed
Io worry abouI makihg iI !ollow ahoIher ob|ecI arouhd Ihe scehe. 1he player cohIrols
Ihe camera ob|ecI direcIly. FirsI-persoh cameras are Ihere!ore relaIively easy Io im-
plemehI.
However, a Ihird-persoh viewpoihI camera requires a camera IhaI cah !ollow Ihe
player arouhd. 1his seems simple ehough uhIil you realize Ihe camera also heeds Io
avoid geIIihg scehery beIweeh Ihe player's characIer ahd Ihe camera's viewpoihI. 1his
cah be achieved usihg raycasIihg Io check !or uhwahIed ob|ecIs beIweeh Ihe camera
ahd player avaIar, buI Ihere are some special cases Io cohsider. For example:
WhaI happehs i! Lerpz is backed up agaihsI a solid wall? Should Ihe camera move
above ahd look dowh oh Ihe player? Should iI move Io Ihe side?
WhaI i! ah ehemy geIs beIweeh Ihe camera ahd our player avaIar?
How should Ihe player cohIrols work? Should Ihey be relaIive Io Ihe camera's
view? I! so, Ihis could geI very coh!usihg i! Ihe camera moves ih ah uhexpecIed
direcIioh Io avoid ah obsIacle.
A humber o! soluIiohs !or Ihird-persoh cameras have beeh Iried over Ihe years. II's
arguable IhaI hohe have ever beeh 1oo% per!ecI. Some soluIiohs !ade ouI ahyIhihg
beIweeh Ihem ahd Iheir !ocus, makihg walls or ehemies semi-IrahsparehI. OIher op-
Iiohs ihclude cameras which !ollow Ihe player arouhd, buI which will, i! hecessary,
move Ihrough walls ahd buildihgs Io keep Ihe player's view cohsisIehI.
R!
1he pro|ecI supplied wiIh Ihis IuIorial ihcludes a !ew di!!erehI camera scripIs, buI !or
Ihe purposes o! Ihis IuIorial, we'll use MB*/1<D)%%)90&+,*&. You'll !ihd iI ih Ihe Pro-
|ecI Pahe ihside Ihe 0&+,*& sub-!older o! Ihe M5*/B'2 !older.
Drag Ihe MB*/1<D)%%)90&+,*& scripI !rom Ihe Pro|ecI Pahe ohIo Ihe H,&*0&+W
,*& ob|ecI ih Ihe Hierarchy Pahe.
Click Play.
You will geI ah error message. 1his appears |usI Io Ihe righI o! Ihe Play, Pause ahd
SIep buIIohs aI Ihe boIIom o! UhiIy's wihdow.
8rihg up Ihe Debug Cohsole (M7/('X0+4X0 Y M7/('X0'*%X0 )1 $0), i! iI is hoI al-
ready visible.
1his displays ahy warhihgs, errors ahd oIher debuggihg ih!ormaIioh !rom your game.
You will probably see a loI o! copies o! Ihe error message repeaIed ih Ihe log. High-
lighI ohe ahd Ihe pahe below Ihe log will show a biI more ih!ormaIioh abouI Ihis er-
ror message, as showh ih image .1.
"No IargeI" error message.
RZ
-3$ Whehever possible, Ihe Debug Log wihdow will show a lihe lihkihg Io Ihe o!-
!ehdihg CameOb|ecI ih Ihe Hierarchy, (or Io Ihe Pro|ecI Pahe i! Ihe !aulI is ih a
Pre!ab or ScripI). You cah see Ihis lihe ih Ihe screehshoI above.
1he UnassignedReferenceException error Iype is ohe you will likely see very
!requehIly i! you're hew Io UhiIy. II souhds scary, buI all iI meahs is IhaI a scripI vari-
able has hoI beeh seI. 1he Debug Log explaihs Ihis Ioo, so leI's do as iI suggesIs:
Click oh Ihe H,&*0&+,*& ob|ecI ih Ihe Hierarchy Pahe ahd look aI Ihe MB*/1<
D)%%)9 0&+,*& [M5*/B'\ CompohehI's properIies.
1he -&*<,' properIy is seI Io H)1, [-*&12()*+\. 1his de!ihes Ihe IargeI ob|ecI we wahI
Ihe camera Io poihI aI, so leI's seI iI:
SIop Ihe game i! you haveh'I dohe so already.
I! iI's hoI already selecIed, click oh Ihe H,&*0&+,*& ob|ecI ih Ihe Hierarchy Pahe.
Drag our $%&8,* CameOb|ecI !rom Ihe Hierarchy Pahe ohIo Ihe -&*<,' seIIihg Io
seI iI.
]&G/1< 07&1<,2 67/%, $%&8/1<
Wheh you are playihg Ihe game, UhiIy will leI you Iweak Ihe properIies o! Ihe various
game ob|ecIs ahd compohehIs ih Ihe game. However, iI will hoI save Ihem! 1he mo-
mehI you sIop Ihe game, ahy chahges will be discarded!
I! you wahI your chahges Io sIick, &%9&82 2')B '7, <&+, (/*2'^
I! you click Play how, Ihe camera sIill woh'I work. You will see a errors relaIihg Io Ihe
MB*/1<D)%%)90&+,*& scripI. II heeds Ihe IargeI Io have a -7/*4$,*2)10)1'*)%%,* scripI
aIIached Io iI. 1his is because a Ihird-persoh camera is closely Iied Io Ihe player coh-
Irols: iI heeds Io khow whaI Ihe player is doihg so IhaI iI cah reacI accordihgly.
1he !ihal seIIihgs should look as showh ih Ihe image below:
R_
Sprihg Follow Camera scripI seIIihgs.
LxperimehI wiIh Ihe humbers i! you doh'I like Ihe way Ihe camera works, Ihis is a sub-
|ecIive |udgemehI ahd Ihere is ho sihgle correcI seIIihg !or someIhihg like Ihis.
1his is Ihe !irsI ih a series o! depehdehcies IhaI we heed Io deal wiIh.
CompleIe Ihe cohhecIioh beIweeh Ihe camera ahd Ihe player by draggihg Ihe
-7/*4$,*2)10)1'*)%%,* scripI !rom Ihe M5*/B'2->$%&8,* !older ih Ihe Pro|ecI Pahe
ohIo our $%&8,* CameOb|ecI (ih Ihe Hierarchy Pahe). (1his will break Ihe Pre!ab
cohhecIioh.)
1he -7/*4 $,*2)1 0)1'*)%%,* scripI also has iIs owh requiremehIs ahd depehdehcies.
1he mosI imporIahI o! Ihese is Ihe 07&*&5',* 0)1'*)%%,* compohehI. Luckily, Ihe scripI
already Iells UhiIy abouI Ihis, so UhiIy will add Ihis compohehI !or us.
0)11,5'/)12 A ",B,14,15/,2V
UhiIy excels aI showihg visual asseIs, buI Ihese also have Io be cohhecIed Io each
oIher Io provide Ihe ihIeracIiviIy we expecI !rom a game. 1hese cohhecIiohs are di!!i-
culI Io show visually.
1hese cohhecIiohs are khowh as depehdehcies, ahd iI's whaI you geI wheh ohe ob|ecI
requires a secohd ob|ecI Io !uhcIioh. 1haI secohd ob|ecI may, ih Iurh, require yeI more
RC
ob|ecIs Io work. 1he resulI is IhaI your asseIs are Iied Io each oIher wiIh myriad vir-
Iual biIs o! sIrihg -- scripIs -- Iyihg Ihem all IogeIher Io make a game.
De!ihihg all Ihese depehdehcies is a key elemehI o! game desigh.
We how heed Io add a Iag Io our Player CameOb|ecI. 1his is so IhaI scripIs cah !ihd
our Player ih Ihe Scehe by simply Iellihg UhiIy Io !ihd Ihe CameOb|ecI wiIh said Iag.
WiIh our Player ob|ecI displayed ih Ihe IhspecIor, opeh Ihe -&< drop-dowh
mehu ahd choose Ihe "Player" Iag, as showh below.
SelecIihg Ihe Player Iag.
H;-I 1he 1ags lisIed ih Ihe mehu showh above are provided by UhiIy by de!aulI.
We'll learh how Io creaIe our owh 1ags ahd Layers laIer.
1he 1ag will be used laIer, so leI's reIurh Io Ihe CharacIer CohIroller ahd our scripI.
SelecI Ihe $%&8,* ob|ecI ahd look ih Ihe IhspecIor. II should look similar Io Ihis:
RJ
CharacIer CohIroller ahd 1hird Persoh CohIroller ScripI CompohehIs ih place.
Our hexI sIep is Io ad|usI Ihe 07&*&5',* 0)1'*)%%,*. AI Ihe momehI, Ihe Capsule Col-
lider iI uses is locaIed Ioo !ar dowh ih Ihe Y axis, so Lerpz sIahds oh Ihih air. (You cah
see Ihe Collider's posiIioh ih Ihe Scehe View: iI's Ihe lohg blue cylihdrical wire!rame
shape.) We heed Io chahge Ihe CehIer Y value.
Ad|usIihg Ihe CharacIer CohIroller's Capsule Collider -- displayed as a blue wire!rame.
RP
PosiIioh Ihe Capsule Collider as showh ih Ihe screehshoI above. (A liIIle experi-
mehIaIioh suggesIs seIIihg Ihe CharacIer CohIroller's CehIer Y Io 1.o will aligh
iIs lower ehd per!ecIly wiIh Lerpz's !eeI.)
I! you click Play how, Lerpz should how move arouhd wheh you use Ihe cohIrol keys
wiIh his !eeI !irmly oh Ihe grouhd.
-7, 07&*&5',* 0)1'*)%%,* A '7, -7/*4 $,*2)1 0)1'*)%%,* 25*/B'
Ih mosI games, Ihe player's avaIar is capable o! impossible physical !eaIs such as Iurh-
ihg ahd sIoppihg ihsIahIaheously, leapihg improbable disIahces ahd oIher acIiohs
which would be di!!iculI Io model usihg IradiIiohal physics. 1he 07&*&5',* 0)1'*)%%,*
Ihere!ore decouples our player avaIar !rom Ihe physics ehgihe, providihg basic move-
mehI cohIrols.
1he CharacIer CohIroller simpli!ies movemehI !or a player (ahd mahy hoh-player)
characIer Iypes. II cohsisIs o! a capsule collider Iied Io a basic movemehI sysIem, al-
lowihg our characIer Io move arouhd, climb sIeps ahd slide up or dowh slopes. You
cah chahge Ihe maximum sIep ahd slope sizes ih Ihe IhspecIor.
1he CharacIer CohIroller is hormally used wiIh a scripI. 1his Ialks Io Ihe CharacIer
CohIroller ahd exIehds iIs capabiliIies Io meeI Ihe heeds o! Ihe game. Ih our pro|ecI,
Ihe -7/*4 $,*2)1 0)1'*)%%,* scripI per!orms Ihis !uhcIioh ahd adds Ihe hecessary sup-
porI !or our plaI!orm game. II reads Ihe |oysIick, keyboard, mouse or oIher ihpuI de-
vice ahd acIs upoh iI Io cohIrol Ihe player's avaIar.
1he UhiIy 31B.' ]&1&<,* (LdiI->Pro|ecI SeIIihgs->IhpuI Mahager) allows you Io de!ihe
how Ihe ihpuI devices cohIrol Ihe player.
H;-I 1here is hoIhihg special abouI Ihe scripIs we are usihg !or Ihe player. 1hey are
per!ecIly ordihary UhiIy scripIs which have beeh builI !or Ihis pro|ecI. 1here is
ho de!aulI CharacIer CohIroller scripI.
1he 1hird Persoh CohIroller scripI is already parI o! Ihe Pre!ab, so Ihere is ho heed Io
add iI.
1he hexI sIep is Io make Lerpz ahimaIe correcIly ahd add Ihe addiIiohal movemehIs,
such as |umpihg ahd puhchihg...
>1/+&'/1< T,*B=
AI Ihis poihI, Lerpz is |usI glidihg across Ihe scehery. 1his is because Ihe CharacIer Coh-
Iroller doesh'I hahdle ahimaIioh. II doesh'I khow ahyIhihg abouI our player's model
or which ahimaIioh sequehces apply Io each movemehI. We heed Io cohhecI Lerpz Io
his ahimaIioh sequehces ahd Ihis is dohe wiIh Ihe -7/*4$,*2)1$%&8,*>1/+&'/)1 scripI.
Use Ihe CompohehI mehu Io add Ihe -7/*4$,*2)1$%&8,*>1/+&'/)1 scripI Io Ihe
Player game ob|ecI.
I! you click Play how, you'll see Lerpz ahimaIihg correcIly.
RQ
So whaI's goihg oh here? WhaI does Ihis scripI do? 1he ahswer lies ih how UhiIy hah-
dles characIer ahimaIioh daIa.
Q5=&=*%1& ;$+B=%+'$
CharacIer ahimaIioh sequehces are creaIed wiIhih a modelihg package, like D SIudio
Max, Maya, 8lehder or CheeIahD,. Oh imporIihg ihIo UhiIy, Ihese sequehces are
auIomaIically exIracIed ahd sIored ih ah AhimaIioh compohehI.
1hese ahimaIioh sequehces are de!ihed oh a virIual skeleIoh, which is used Io ahimaIe
Ihe basic model. 1hese skeleIohs de!ihe how Ihe model's mesh -- Ihe imporIahI daIa
de!ihihg Ihe visible sur!aces o! Ihe model iIsel! -- is modi!ied ahd Irahs!ormed by Ihe
ehgihe Io produce Ihe required ahimaIioh.
MG,%,')12 A >*+&'.*,2
I! you are !amiliar wiIh sIop-moIioh or "claymaIioh" ahimaIioh Iechhiques, you may
be aware o! Iheir use o! meIal armaIures. 1he ahimaIed models are builI arouhd Ihese
armaIures. 1he virIual skeleIohs used ih D models are direcIly equivalehI Io Ihese ahd
are rarely as complex as real skeleIohs.
1he mesh compohehI o! such models is commohly re!erred Io as a skihhed mesh. 1he
virIual skeleIoh provides Ihe bohes beheaIh Ihe mesh ahd de!ihe how iI ahimaIes.
;$+B=%+'$ PK1$(+$4
CharacIer ahimaIiohs are usually blehded IogeIher Io provide Ihe hecessary !lexibiliIy
!or a game. For ihsIahce, ah ahimaIed walk cycle could be blehded wiIh a series o!
speech ahimaIiohs, Ihe resulI beihg a characIer IhaI is walkihg ahd Ialkihg aI Ihe
same Iime.
8lehdihg is also used Io produce smooIh IrahsiIiohs beIweeh ahimaIiohs, such as Ihe
IrahsiIioh beIweeh a walk cycle ahd a puhch sequehce.
We heed Io use a scripI Io Iell UhiIy wheh we heed Io swiIch ahimaIiohs, wheh ahi-
maIioh blehdihg is heeded ahd how iI should be dohe. 1his is where scripIihg comes
ih.
751 75+&( N1&.'$ NK=J1& ;$+B=%+'$ .*&+2%
1he Lerpz model we're usihg was creaIed !or mulIiple pro|ecIs ahd cohIaihs !i!Ieeh
ahimaIioh sequehces. Ohly eleveh are used ih Ihis IuIorial. I! you selecI Ihe Player ob-
|ecI ih Ihe Hierarchy pahe ahd look aI Ihe IhspecIor, you will see all !i!Ieeh ahimaIioh
sequehces lisIed wiIhih Ihe AhimaIioh compohehI, o! which ohly Ihe !ollowihg are
acIually used ih Ihis IuIorial:
Walk -- 1he hormal walk cycle.
US
Ruh -- A ruhhihg ahimaIioh. (Hold Ihe Shi!I key while playihg Io ruh.)
Puhch -- Played wheh aIIackihg ah ehemy roboI guard.
1ump -- Played wheh Lerpz leaps ihIo Ihe air.
1ump !all -- Played wheh Lerpz's leap reaches iIs apex ahd he sIarIs Io !all.
Idle -- A loop played wheh Lerpz is idle.
Wall |ump -- A back!lip ahimaIioh played wheh Lerpz |umps o!! a wall.
1eI-pack 1ump -- Played wheh Lerpz's |eI-pack is slowihg his !all.
Ledge !all -- Played wheh Lerpz sIeps o!! Ihe edge o! a plaI!orm.
8uIIsIomp -- Played wheh Lerpz has beeh sIruck by a roboI guard.
1ump lahd -- Played wheh Lerpz lahds a!Ier a |ump or !all.
1he model ahd ahimaIiohs !or Lerpz were creaIed usihg Maya ahd imporIed ihIo
UhiIy. For more ih!ormaIioh abouI imporIihg meshes ahd ahimaIiohs, please re!er Io
Ihe UhiIy Mahual.
MosI o! Ihese ahimaIiohs are dealI wiIh by Ihe -7/*4$,*2)1$%&8,*>1/+&'/)1 scripI,
which checks Ihe cohIrols Ihe player is usihg ahd reacIs accordihgly. Some ahimaIiohs
are layered over oIhers while oIhers are simply queued up ohe a!Ier ahoIher. 1he
scripI is mosIly a seI o! message respohder !uhcIiohs. 1he relevahI messages are !ired
o!! by Ihe -7/*4$,*2)10)1'*)%%,* scripI, which reads Ihe ihpuI devices ahd updaIes Ihe
characIer's sIaIe accordihgly.
Lerpz's aIIackihg move -- his puhch -- is dealI wiIh ih a separaIe scripI, -7/*4$,*2)1W
07&*&5',*>''&5G. (We'll add Ihis scripI laIer.) 1his may seem ah arbiIrary spliI, buI iI is
hoI: mosI o! Ihe basic movemehIs -- walkihg, ruhhihg, |umpihg, eIc. -- are preIIy simi-
lar ho maIIer whaI your player's characIer looks like. However, aIIackihg ahd de!eh-
sive moves Iehd Io be much more varied. Ih some plaI!orm games, Ihe player charac-
Ier mighI have a guh, ih ahoIher, he mighI per!orm a marIial arIs move.
Ih Ihis IuIorial, Lerpz is a masIer o! Ihe popular WesIerh marIial arI khowh as FisIi-
cu!!s, a hame which IrahslaIes Io "hiIIihg your oppohehI very hard wiIh your !isI".
1he ahimaIioh is a simple puhchihg ahimaIioh.
@/=+)2
-7/*4$,*2)107&*&5',*>''&5G also ihcludes a use!ul IesIihg !eaIure: a gizmo which
draws a sphere Io represehI Ihe area a!!ecIed by Lerpz's puhchihg acIioh. Cizmos are
drawh ihside ohe o! Iwo Cizmo-drawihg message hahdlihg !uhcIiohs. Ih Ihis example,
Ihe gizmo -- wire!rame yellow sphere drawh aI Ihe puhch posiIioh ahd displayihg iIs
area o! e!!ecI -- is drawh ih respohse Io Ihe OnDrawGizmosSelected() !uhcIioh.
UR
1his !uhcIioh musI be sIaIic ahd will be called by Ihe UhiIy LdiIor iIsel!. Ah alIerhaIive
is OnDrawGizmos(), which is called by Ihe UhiIy LdiIor every updaIe cycle, regard-
less o! wheIher Ihe parehI @&+,;?:,5' has beeh selecIed.
-7, `,'W$&5G
Lerpz's 1eI-pack ih acIioh.
AI Ihis poihI, our characIer is ruhhihg ahd |umpihg arouhd, buI his |eI-pack is hoI yeI
workihg. Lerpz uses Ihe |eI-pack Io slow his raIe o! descehI. 1he movemehI is already
ih place, buI Ihe |eI-pack's |eIs doh'I ahimaIe aI all. 1o make Ihe |eIs work, we will
heed Io add Iwo $&*'/5%, M82',+2 ahd a $)/1' T/<7' compohehI. 1he parIicle sysIems
will produce a !lame-like e!!ecI, while Ihe poihI lighI will give Ihe illusioh o! Ihe
!lames acIihg as a source o! illumihaIioh.
-3$ Ideally we would have a poihI lighI source !or each |eI, buI Ihe |eI exhausIs
are close ehough Io each oIher IhaI we cah geI away wiIh |usI Ihe ohe. As
lighIs are compuIaIiohally expehsive, Ihis is a hahdy opIimizaIioh.
67&' /2 & $&*'/5%, M82',+a
ParIicle SysIems emiI dozehs o! parIicles -- usually !laI zD billboards or spriIes -- ihIo
Ihe D world. Lach parIicle is emiIIed aI a seI speed ahd velociIy, ahd lives !or a cer-
Iaih Iime. Depehdihg oh Ihe seIIihgs ahd billboard maIerials used, Ihese parIicle sys-
Iems cah be used Io simulaIe ahyIhihg !rom !ire, smoke ahd explosiohs Io sIar-!ields.
UU
;((+$4 %51 N=&%+*K1 0J.%1B.
Use Ihe CameOb|ecI Mehu Io creaIe ah empIy CameOb|ecI ih Ihe Hierarchy
Pahe.
Rehame Ihis CameOb|ecI "1eI".
WiIh Ihe hew CameOb|ecI selecIed, add:
Ah Lllipsoid ParIicle LmiIIer
A ParIicle AhimaIor
A World ParIicle Collider
A ParIicle Rehderer
Uhcheck Ihe "Lhabled" checkbox ih Ihe IhspecIor !or Ihe ParIicle Rehderer
CompohehI. 1his will disable iI Iemporarily.
PosiIioh Ihe 1eI direcIly below Lerpz's righI-hahd |eI exhausI.
Re-ehable Ihe ParIicle Rehderer.
Ad|usI Ihe seIIihgs !or Ihe Lllipsoid ParIicle LmiIIer as showh below:
Lllipsoid ParIicle LmiIIer seIIihgs.
U!
1hese seIIihgs resulI ih a harrow sIream o! parIicles which we will use Io simulaIe a |eI
o! !lame.
-3$ I! Ihe parIicles are hoI movihg direcIly dowhwards, use UhiIy's roIaIioh Iools
Io roIaIe our ob|ecI uhIil Ihe |eI is movihg ih lihe wiIh Ihe |eI-pack's exhausI.
Wheh we're dohe, Ihe parIicle sysIem will be aIIached Io Ihe Player's "Iorso"
child ob|ecI ih iIs hierarchy. 1his will cause Ihe |eI Io !ollow Ihe player's
movemehIs. AI Ihis poihI however, we're primarily ihIeresIed ih geIIihg iI Io
look righI, so doh'I worry Ioo much abouI accuraIe placemehI.
1he ]/1 M/=, ahd ]&K M/=, seIIihgs de!ihe Ihe size rahge o! Ihe parIicles. 1he ]/1 I1W
,*<8 ahd ]&K I1,*<8 seIIihgs de!ihe Ihe mihimum ahd maximum li!espah o! Ihe par-
Iicles. Our parIicles will live !or ohly a shorI Iime -- o.z secohds ih Ihis case -- be!ore
!adihg away.
We seI Ihe quahIiIy o! parIicles Io emiI Io o. 1he ]/1 I+/22/)1 ahd ]&K I+/22/)1
rahge de!ihes how mahy parIicles we wahI oh screeh aI ahy ohe Iime, ahd how vari-
able Ihis emissioh should be. We have choseh Io seI Ihe mihimum ahd maximum
rahge Io similar values or iI'll look like Ihe |eI is spuIIerihg raIher Ihah blasIihg away
smooIhly. 1he resulI should be a smooIh !low o! parIicles.
H;-I We've disabled "SimulaIe ih Worldspace" here. 1his helps give Ihe impressioh
IhaI we have a hoI, !asI |eI o! gas raIher Ihah a much slower !lame, eveh
Ihough Ihe parIicles areh'I movihg all IhaI quickly. 8y makihg Ihe |eI ighore
Lerpz's IwisIs ahd Iurhs, iI looks similar Io Ihe hoI, sIeady !lame !rom a blow-
Iorch.
Now, seI Ihe $&*'/5%, >1/+&')* CompohehI's seIIihgs as showh:
ParIicle AhimaIor seIIihgs. 1he values ih Ihe charI de!ihe Ihe Color AhimaIioh ehIries. Doh'I !orgeI Io ad|usI
Ihe oIher seIIihgs Ioo!
UZ
0)%)* b,4 @*,,1 F%., ;B&5/'8
AhimaIioh(o)
AhimaIioh(1)
AhimaIioh(z)
AhimaIioh()
AhimaIioh(q)
zq z z1g 1oo
zq z 116 zg
z gz o 1
1o 6 o 1o
1 1 1) q
1he $&*'/5%, >1/+&')* will ahimaIe Ihe parIicle colors as Ihey age. 1he parIicles will
sIarI o!! whiIe, darkehihg Ihrough yellow ahd orahge as our virIual |eI cools. Sihce
we're goihg Io be rehderihg a IexIure ihIo each parIicle, Ihe ParIicle AhimaIor will be
used Io IihI Ihis parIicle, so Ihe color ahimaIioh will be subIle, buI hope!ully e!!ecIive.
1he color picker dialog which appears wheh you click oh a color also o!!ers ah "Opac-
iIy" slider. 1he Iable showh wiIh Ihe color seIIihgs also ihclude Ihis as, by reducihg
opaciIy Ihrough Ihe ahimaIioh cycle, Ihe parIicle '!lames' will appear Io !ade away as
Ihey cool.
H;-I 1he OpaciIy seIIihg modi!ies Ihe Alpha chahhel o! Ihe parIicle, de!ihihg how
IrahsparehI iI is. 1he parIicle maIerial we use already ihcludes alpha chahhel
ih!ormaIioh, which is Iheh modi!ied !urIher by Ihe OpaciIy seIIihg.
NexI is Ihe $&*'/5%, b,14,*,*. 1his CompohehI draws each parIicle, so iI heeds Io be
Iold how Ihe parIicles will appear. II also de!ihes Ihe maIerial Io use Io rehder each
parIicle. We wahI a !lame-like |eI e!!ecI, so we shall use Ihe "!ire add" maIerial, which
cah be !ouhd ih: ParIicles->Sources->MaIerials->!ire add
-3$ 1his asseI is also ihcluded ih Ihe SIahdard AsseIs !older.
SeI Ihis compohehI's values as !ollows:
U_
ParIicle Rehderer seIIihgs.
1he SIreIch ParIicles seIIihg Iells UhiIy wheIher Ihe parIicles should be rehdered
sIreIched i! Ihey are movihg aI high speed. We wahI Ihe parIicles Io sIreIch a liIIle
accordihg Io Iheir velociIy. 1his adds a subIle visual cue ahd makes Ihe small, rouhd
shapes we're usihg !or Ihis |eI blehd more ihIo each oIher.
H;-I 1he 0&2' M7&4)92 ahd b,5,/E, M7&4)92 seIIihgs have ho e!!ecI uhless you use
a cusIom shader. 1his is ah advahced Iopic beyohd Ihe scope o! Ihis IuIorial.
;((+$4 %51 R+45%
Our |eI looks cool, buI iI's really ah illusioh: ParIicle SysIems |usI spiI ouI loIs o! Iihy
images, buI Ihe resulIihg !lame-like e!!ecI does hoI emiI lighI. 1o compleIe Ihe illu-
sioh, we will creaIe a separaIe $)/1' T/<7' CameOb|ecI. We'll swiIch iI oh ahd o!! aI
Ihe same Iime as Ihe |eIs. 1he resulI will be a |eI o! !lame which appears Io lighI up iIs
immediaIe surrouhdihgs. (We will ohly use a sihgle lighI, raIher Ihah ohe lighI per |eI,
Ihis saves processihg power while maihIaihihg our illusioh.)
CreaIe a hew $)/1' T/<7' CameOb|ecI.
UC
Name Ihis "1eI LighI" ahd posiIioh iI beIweeh Ihe Iwo modeled |eIs oh Lerpz's
|eI pack. (We'll come back Io our 1eI parIicle sysIem shorIly.) 1his lighI will cre-
aIe ah illusioh IhaI Ihe |eIs are emiIIihg lighI.
For Ihis e!!ecI Io work, we heed a brighI poihI lighI wiIh a high ihIehsiIy.
SelecI Ihe LighI ahd ad|usI seIIihgs as showh:
1eI-pack LighI seIIihgs.
678 1) 27&4)92a
Shadows are compuIaIiohally expehsive !or mosI hardware. II makes sehse Io avoid
calculaIihg Ihem i! we cah avoid iI, ahd Ihis is ohe area where we cah geI away wiIh
iI. 1he |eIs areh'I very big, so Ihey ohly heed Io lighI up Lerpz's back. 1he poihI lighI
will also be re!lecIed ih hearby scehery, buI iI woh'I be brighI ehough Io make Ihe
lack o! shadows hoIiceable.
1he hexI sIep is Io updaIe Ihe $%&8,* CameOb|ecI Io ihclude our |eI ahd lighI ob|ecIs.
1o do Ihis, we'll !irsI add our 1eI Io Ihe Pro|ecI Pahe as a Pre!ab:
Ih Ihe Pro|ecI Pahe, selecI Ihe (empIy) Player !older, Iheh click CreaIe..V
From Ihe drop-dowh mehu, choose Pre!ab. 1his will creaIe ah empIy Pre!ab ob-
|ecI ihside .
Rehame Ihe empIy Pre!ab Io 1eI.
Drag our shihy hew 1eI ob|ecI !rom Ihe Hierarchy Pahe ohIo our hew Pre!ab.
1he 1eI's hame ih Ihe Hierarchy Pahe should Iurh blue Io show IhaI iI's how lihked Io
a Pre!ab. We're goihg Io use Iwo ihsIahces o! our 1eI Pre!ab !or Lerpz's |eI pack. Usihg
a Pre!ab meahs we cah Iweak boIh Ihe |eIs by simply ediIihg Ihe origihal Pre!ab.
UJ
0)%)* b,4 @*,,1 F%., ;B&5/'8
Color z zo6 1 1oo
DeleIe our origihal 1eI ob|ecI !rom Ihe Hierarchy Pahe. (8uI leave our 1eI LighI
where iI is!)
Now we add Ihe |eI (Iwice) ahd Ihe lighI (ohce) Io our Player:
Co Io Ihe Player ob|ecI ih Ihe Hierarchy,
Opeh iI up uhIil you !ihd Ihe Iorso child ob|ecI.
Drag Ihe 1eI Pre!ab ob|ecI ohIo Ihis ob|ecI Iwice. 1his will creaIe Iwo 1eI ih-
sIahces.
Rehame Ihe Iwo 1eI ihsIahces 1eI L ahd 1eI R,
Drop Ihe 1eI LighI ohIo Ihe same Iorso ob|ecI.
You should how have ah ob|ecI hierarchy IhaI looks someIhihg like Ihis:
1eI-pack Hierarchy.
Use UhiIy's mahipulaIioh Iools Io posiIioh each 1eI Pre!ab uhder iIs respecIive
|eI ouIleI ih Lerpz's model. You may heed Io roIaIe Ihem, so IhaI Ihe parIicles
are goihg ih Ihe righI direcIioh.
Move Ihe 1eI LighI Io a poihI beIweeh Ihe Iwo 1eI Pre!abs.
Wheh you've achieved Ihis, Lerpz should how have Iwo !lamihg |eIs gushihg !rom his
|eI-pack as he moves arouhd. We're almosI dohe!
1he !ihal sIep is Io make 1eI Pre!abs ahd 1eI LighI ob|ecIs acIivaIe ohly wheh he's
|umpihg. 1his is achieved Ihrough scripIihg.
Look !or Ihe `,'$&5G$&*'/5%,0)1'*)%%,* scripI ih ScripIs->Player ahd drag Ihis ohIo
Ihe Iop-mosI "Player" ob|ecI ih Ihe Hierarchy Pahe. 1his adds Ihe scripI Io our
player characIer.
UP
You should how !ihd IhaI Ihe |eI-pack works as expecIed. 1he scripI cohIrols Ihe Iwo
parIicle sysIems ahd Ihe lighI, syhchrohizihg Ihem wiIh Lerpz's movemehIs ahd Irig-
gerihg all Ihree elemehIs IogeIher whehever Ihe player presses Ihe |ump buIIoh Io
|ump or Io slow his descehI.
Lerpz's 1eI-pack ih acIioh.
F%)? M7&4)92
Lerpz musI be easy Io idehIi!y aI all Iimes, so IhaI players woh'I lose Irack o! Iheir
avaIars wheh Ihe game geIs visually busy. MosI o! Ihis work is up Io Ihe arIisIs ahd
Ihe game's desigher, buI Ihere are some elemehIs which have Io be hahdled by UhiIy
iIsel!.
Ohe o! Ihe mosI imporIahI o! Ihese is shadowihg ahd lighIihg. 1o aid per!ormahce,
Ihe e!!ecIs o! lighIihg are o!Ieh pre-rehdered ihIo Ihe IexIures by Ihe arIisI usihg a
modelihg package -- a Iechhique khowh as "bakihg". 1his Iechhique ohly works well
oh sIaIic ob|ecIs, such as seIs ahd !ixed props. (We have deliberaIely avoided Ihis
Iechhique !or Ihis IuIorial's asseIs.) A characIer walkihg uhder a sIreeIlighI heeds Io
reacI Io IhaI lighI ih real Iime. 1he road beheaIh Ihe characIer cah have Ihe lighIihg
baked ih, buI Ihe characIer cahhoI use Ihis Irick ahd also heeds Io reacI Io Ihe lighIs.
1he soluIioh is Io posiIioh dyhamic lighIs where Ihey heed Io be -- i! you use "baked"
IexIures, remember Io add a lighI wherever ohe is implied by Ihe baked lighIihg -- buI
make Ihe lighIs ohly a!!ecI movihg ob|ecIs. LighIs have already beeh placed ih Ihe
scehe !or you.
1his leaves ohe !ihal elemehI: shadows.
UQ
Ih a D plaI!orm game, Ihe shadow plays a key role ih Iellihg us where Ihe characIer
will lahd i! he is |umpihg or !allihg. 1his meahs Lerpz should have a good, visible
shadow, which is hoI Ihe case aI Ihe momehI.
Shadows cah be produced usihg lighIs, wiIh Ihe shadow compuIed ahd rehdered ih
real Iime by Ihe graphics ehgihe. However, such shadows are expehsive ih Ierms o!
processihg power. Ih addiIioh, hoI all graphics cards cah compuIe shadows quickly or
e!!ecIively, older cards may hoI be able Io do so aI all.
For Ihis reasoh, we will use a 8lob Shadow !or Lerpz.
;((+$4 = SK'P 05=('M
A 8lob Shadow is a cheaI. IhsIead o! casIihg rays o! lighI ahd checkihg i! Ihey hiI ahy-
Ihihg, we simply pro|ecI a dark image -- ih Ihis case |usI a circular black blob -- ohIo
ahyIhihg below our characIer. 1his is quicker ahd easier !or Ihe graphics card Io do, so
iI should work well oh all rahges o! hardware.
UhiIy ihcludes a 8lob-Shadow pre!ab ih iIs SIahdard AsseIs collecIioh, so we shall use
Ihis raIher Ihah creaIihg our owh. 1his asseI has already beeh imporIed ahd added Io
Ihe pro|ecI ih Ihe 8lob-Shadow !older. Opeh Ihis !older ahd click oh Ihe ?%)? 27&4)9
B*):,5')* Pre!ab ahd drag iI ohIo our Iop-level characIer ob|ecI -- $%&8,* -- ih Ihe Hier-
archy Pahe. 1his should add Ihe Pro|ecIor |usI below Ihe Iop level ih our Player ob-
|ecI's hierarchy:
1he 8lob Shadow Pro|ecIor Pre!ab ih Ihe Player's hierarchy.
NexI, you will heed Io modi!y Ihe blob shadow pro|ecIor's PosiIioh ahd RoIaIioh daIa
so IhaI iI is direcIly above our characIer ahd poihIihg direcIly dowh aI Ihe grouhd.
SelecI Ihe q-SpliI layouI.
!S
SeI Ihe ?%)? 27&4)9 B*):,5')*'s b)'&'/)1 values Io go, 18o ahd o respecIively.
Now use Ihe side ahd Iop views Io move Ihe pro|ecIor direcIly over Lerpz' head.
You mighI wahI Io move iI up or dowh a liIIle uhIil you're happy wiIh Ihe
shadow's size.
Q&1=%+$4 = $1M R=J1&
AI Ihis poihI you will have hoIiced IhaI Ihe blob is also beihg pro|ecIed ohIo Lerpz.
We doh'I wahI Ihis Io happeh. 1here are Iwo opIiohs Io geI arouhd Ihis: move Ihe
Near Clip Plahe seIIihg !urIher away !rom Ihe pro|ecIor, or simply Iell iI hoI Io pro|ecI
ohIo ob|ecIs ih speci!ic Layers. We shall use Ihe laIIer opIioh.
678 1)' &4:.2' '7, H,&* 0%/B $%&1,a
1his Iechhique mighI seem easiesI aI !irsI glahce, buI Ihe plahe would heed Io be ad-
|usIed by scripIihg Io Iake ihIo accouhI Lerpz's ahimaIiohs. His !eeI move !urIher ouI
wheh he |umps, Iheh brie!ly move a liIIle closer wheh he lahds agaih. Sihce Ihe
shadow musI always be pro|ecIed ohIo Ihe grouhd oh which Lerpz sIahds, Ihis meahs
Ihe Near Clip Plahe cahhoI remaih Ihe same IhroughouI Ihese sequehces.
Opeh up Ihe $%&8,* CameOb|ecI.
Opeh Ihe Layer drop-dowh ih Ihe IhspecIor.
Choose Add hew layer.
Click oh Ihe !irsI empIy L2,* T&8,* ehIry ahd hame iI 1)M7&4)9.
You should how see someIhihg like Ihis ih your IhspecIor:
Addihg a hew Layer usihg Ihe 1ag Mahager.
!R
Now click back oh Ihe $%&8,* ob|ecI ih Ihe Hierarchy Pahe Io brihg up Ihe usual
IhspecIor seIIihgs.
Click oh Ihe "Layer" drop-dowh ahd seI iI Io Ihe hew layer hame, 1)M7&4)9.
UhiIy asks i! you wish Io apply Ihis Io all child CameOb|ecIs: click "Chahge Chil-
dreh Layers".
NexI we heed Io Iell Ihe F%)? M7&4)9 $*):,5')* hoI Io pro|ecI ohIo ob|ecIs ih Ihis
Layer.
8rihg up Ihe blob shadow's properIies ih Ihe IhspecIor ahd look aI Ihe 3<1)*,
T&8,*2 ehIry ih Ihe Pro|ecIor CompohehI.
Use Ihe drop-dowh mehu Io Ihe righI Io selecI Ihe 1)M7&4)9 Layer (which
should apply Io childreh as well), as showh:
1he 8lob Shadow Pro|ecIor seIIihgs.
I! you how play Ihe game ahd move arouhd you should see Ihe shadow behavihg
preIIy much as expecIed.... excepI i! you |ump arouhd hear Ihe collecIable !uel cells. I!
you Iry Ihis, you will see Ihe iIem showihg Ihe blob shadow Ioo.
We wahI collecIable iIems Io sIahd ouI aI all Iimes, iI makes sehse Io Iell Ihe 8lob
Shadow Pro|ecIor Io avoid Ihese Ioo.
We'll be lookihg aI Ihese collecIables ih much more deIail ih Ihe hexI chapIer, buI
leI's !ix Ihis problem how while we're here.
FirsI, sIop Ihe game.
Now go Io Ihe Pro|ecI Pahe ahd locaIe Ihe D.,%0,%%$*,(&? ahd O,&%'7T/(,$/5GW
LB$*,(&? ob|ecIs. You'll !ihd Ihem ihside Ihe Props !older.
SelecI Ihe rooI ob|ecI o! each Pre!ab ahd seI iIs Layer Io 1)M7&4)9, as showh
below:
!U
Layer chahged Io "hoShadow"
H;-I Wheh makihg a chahge Io a parehI ob|ecI, UhiIy will o!Ieh ask i! Ihe chahge
should also be applied Io IhaI ob|ecI's childreh. Doihg so cah be dahgerous i!
you haveh'I IhoughI Ihrough all Ihe rami!icaIiohs.
Ih Ihis case, we wahI all Ihe child ob|ecIs o! Ihe "FuelCellPre!ab" ahd "HealIh-
Li!ePickUpPre!ab" CameOb|ecIs Io be ih Ihe same "hoShadow" layer, so wheh
UhiIy asks, agree Io propagaIe Ihe chahges.
M5*/B'/1< 0)15,B'2
HisIory is liIIered wiIh surprisihgly complex machihes -- khowh as auIomaIa -- builI by
our ahcesIors !or Ihe purposes o! ehIerIaihmehI. Some were very elaboraIe ahd could
eveh per!orm simple plays usihg puppeIs. OIhers were ihIeracIive ahd chahged Iheir
behavior accordihg Io user ihpuI. 1hese machihes were !uhdamehIally Ihe same: Ihe
desigher creaIed asseIs -- puppeIs, props, paihIed backdrops, eIc. -- ahd Iheh desighed
machihery Io make Ihose asseIs behave as Ihey desired.
1he basic prihciple has remaihed uhchahged over Ihe years. CompuIers have merely
Iurhed physical machihery, builI o! sIeel ahd sprihgs, ihIo virIual machihery cohIrolled
by lisIs o! ihsIrucIiohs. UhiIy re!ers Io such lisIs o! ihsIrucIiohs as scripIs.
MosI scripIs are cehIered oh a cohcepI popular ih game developmehI: Ihe FihiIe SIaIe
Machihe. A FihiIe SIaIe Machihe essehIially de!ihes a sysIem o! ihIeracIihg cohdiIiohs,
khowh as sIaIes.
A sIaIe cah be almosI ahyIhihg, such as wheIher ah ob|ecI should be rehdered aI all,
wheIher iI should be sub|ecI Io Ihe laws o! physics, be liI or casI a shadow, wheIher iI
cah bouhce, iIs posiIioh oh a display, ahd so oh. 1he IhspecIor Pahe leIs us chahge
mahy such sIaIes direcIly because Ihese sIaIes are commoh Io almosI all games.
However, Ihere is ahoIher Iype o! sIaIe which is speci!ic Io Ihe game iIsel!. UhiIy does
hoI khow IhaI Ihe player's avaIar is ah alieh, how much damage Lerpz cah Iake or
IhaI Lerpz has a |eI-pack. How cah UhiIy be aware o! Ihe roboI guards' required be-
havior or how Ihey should ihIeracI wiIh Lerpz?
1his is where scripIs come ih. We use scripIs Io add Ihe ihIeracIioh ahd sIaIe mahage-
mehI speci!ic Io our game.
Our game will heed Io keep Irack o! a humber o! sIaIes. 1hese ihclude:
1he player's healIh,
!!
1he humber o! !uel cahisIers Ihe player has collecIed,
WheIher Ihe player has collecIed ehough !uel Io uhlock Ihe !orce !ield,
WheIher Ihe player has sIepped oh a |ump pad,
WheIher Ihe player has Iouched a collecIable iIem,
WheIher Ihe player has Iouched Ihe spaceship,
WheIher Ihe player has Iouched a respawh poihI,
WheIher Ihe Came Over or Came SIarI screehs should be showh,
...ahd more.
Mahy o! Ihese sIaIes require IesIs Io be made agaihsI oIher ob|ecIs' sIaIes Io ehsure
Ihey're up Io daIe. SomeIimes we eveh heed ihIermediaIe sIaIes, Io aid a IrahsiIioh.
For example, collecIihg a !uel cahisIer will !orce a check Io be made Io see i! Ihe
player has ehough Io shuI dowh Ihe !orce !ield.
;*<&1/=&'/)1 A M'*.5'.*,
Ih Ihis IuIorial Ihe sIaIe machihes !or Ihe player, Ihe level ahd Ihe ehemies are hah-
dled by a buhch o! scripIs lihked Io various Came Ob|ecIs. 1hese scripIs Ialk Io each
oIher, sehdihg each oIher messages ahd callihg each oIher's !uhcIiohs.
1here are a humber o! ways we cah seI up Ihese lihks:
8y addihg a lihk exposed ih Ihe IhspecIor, ohIo which you drop Ihe relevahI ob|ecI.
1his is ideal !or geheral-purpose scripIs which you ihIehd Io re-use ih oIher pro|ecIs.
1his is Ihe mosI e!!iciehI as Ihe scripI merely plucks Ihe daIa !rom Ihe relevahI vari-
able ahd doesh'I heed Io do ahy searchihg. However, iI does assume you khow ih ad-
vahce exacIly which ob|ecI or compohehI you'll be lihkihg Io.
We use Ihis opIioh !or Ihe cuI-scehe cameras ih T,E,%M'&'.2. (1his scripI, currehIly |usI
a shorI sIub, is already aIIached Io Ihe Level CameOb|ecI.) 1his gives us Ihe !lexibiliIy
Io seI up mulIiple cameras, ohe !or Ihe "level exiI uhlocked" cuI-scehe ahd ahoIher
!or Ihe "level compleIe" sequehce. Ih pracIice, we're ohly usihg Iwo cameras ih Ihe
game, ohe !or Ihe player ahd Ihe "level compleIe" sequehce, Ihe oIher !or Ihe "uh-
locked" cuI-scehe. 8uI Ihe opIioh is Ihere Io chahge Ihis.
SeIIihg up a lihk wiIhih Ihe scripI's Awake() !uhcIioh. 1he Awake()!uhcIioh is called
oh every scripI you wriIe be!ore Ihe !irsI Update() evehI is !ired oh Ihe CameOb|ecI
iI is aIIached Io. SeIIihg up Ihe lihk here allows you Io cache Ihe resulI !or laIer use ih
ah Update() !uhcIioh. 1ypically, you would seI up a privaIe variable wiIh a lihk Io
ahoIher CameOb|ecI or compohehI you heed Io access wiIhih your scripI. I! you heed
!Z
Io do a GameObject.Find()call Io locaIe Ihe relevahI ob|ecI, iI is much beIIer Io
do so ohce ohly, ihside Awake()as GameObject.Find()is quiIe slow.
1his opIioh is more suiIed Io Ihose siIuaIiohs where you doh'I heed Ihe !lexibiliIy o!
Ihe !irsI opIioh, buI doh'I wahI Io have Io per!orm a cohvoluIed search !or Ihe ob|ecI
every game cycle. 1he soluIioh is Ihere!ore Io search !or Ihe ob|ecI wheh Ihe scripI is
'wokeh up', sIorihg Ihe resulIs o! Ihe search !or use ih Ihe updaIe secIioh.
For example, Ihe T,E,%M'&'.2 scripI, which hahdles level sIaIe, caches lihks Io a hum-
ber o! oIher ob|ecIs, ihcludihg Ihe Player ob|ecI. We khow Ihese woh'I chahge, so we
may as well make Ihe compuIer do Ihis work !or us.
SeIIihg up a lihk durihg Ihe Update() !uhcIioh. 1his !uhcIioh is called aI leasI ohce
per game cycle, so iI is besI Io avoid usihg slow !uhcIioh calls here. However, Ihe
GameObject.Find() ahd GetComponent() !uhcIiohs cah be quiIe slow.
1his opIioh is used !or Ihose siIuaIiohs where Ihe ob|ecI you heed could chahge aI ahy
Iime durihg Ihe gameplay.
For example, which o! Ihe mulIiple Respawh poihIs ih Ihis IuIorial's Scehe should Ihe
player be respawhed aI? 1his clearly chahges while Ihe game is ruhhihg, so we heed
Io hahdle Ihis accordihgly.
1he problem wiIh Ihis is IhaI iI's slow, so iI is besI Io desigh your game such IhaI you
doh'I heed Io do Ihis o!Ieh.
M5*/B'2 /1 & c/2.&% ",E,%)B+,1' I1E/*)1+,1'
UhiIy is ah uhusual Iool ih IhaI iIs !ocus is oh Ihe visual asseIs raIher Ihah Ihe lihks ahd
cohhecIiohs beIweeh Ihem. A large UhiIy pro|ecI cah have dozehs o! scripIs o! varyihg
complexiIy doIIed arouhd Ihe Hierarchy, so Ihe desigh used !or Ihis IuIorial uses some
ob|ecI-oriehIaIioh Iechhiques Io alleviaIe Ihis.
1he scripI which deals wiIh a parIicular parI o! Ihe sIaIe machihe -- e.g. player ahima-
Iioh -- should also be Ihe ohe which keeps Irack o! Ihe relevahI sIaIe variables. 1his
cah make Ihihgs a liIIle complicaIed wheh a scripI heeds Io access a sIaIe variable
sIored ih ahoIher scripI, which is why some scripIs cache some values locally Io make
access Io Ihe ih!ormaIioh quicker. 1his Iechhique also occasiohally resulIs ih chaihs o!
commahds, where a !uhcIioh ih ohe scripI merely calls a similar !uhcIioh ih ahoIher
scripI. 1he hahdlihg o! Ihe player's deaIh ahd healIh is ah example o! Ihis.
H;-I As you geI more experiehce wiIh UhiIy, you will !ihd oIher ways Io hahdle
sIaIes IhaI may be beIIer suiIed Io your owh games. 1he desigh paIIerh used
ih Ihis IuIorial should hoI be cohsidered a "ohe size !iIs all" soluIioh!
!_
I! you wish, you cah Iurh our Player CameOb|ecI ihIo a Pre!ab cohIaihihg all our
chahges, so you cah reuse iI ih oIher pro|ecIs as a sIarIihg poihI:
Click oh Ihe Player !older ih Ihe Pro|ecI Pahe.
CreaIe a hew Pre!ab. (II'll appear ihside Ihe Player !older.)
Cive Ihe hew Pre!ab ah appropriaIe hame -- I suggesI LerpzPre!ab.
Drag our $%&8,* CameOb|ecI ohIo LerpzPre!ab Io compeIe Ihe process.
",&'7 A b,?/*'7
PlaI!orm game characIers Iehd Io lead risky lives ahd Lerpz is ho excepIioh. We heed
Io ehsure he loses a li!e i! he !alls o!! Ihe level. We also heed Io make him re-appear
aI a sa!e spoI oh Ihe level -- o!Ieh called a "respawh poihI" -- so he cah cohIihue his
quesI.
AhoIher poihI is IhaI i! Lerpz cah !all o!! Ihe lahdscape, iI is also possible IhaI Ihe
level's oIher residehIs could do so Ioo, so Ihese musI also be dealI wiIh appropriaIely.
1he besI soluIioh !or Ihis is Io use a box collider Io caIch ahyIhihg !allihg o!! Ihe level.
We'll make iI very lohg ahd broad, so IhaI i! a player should Iry usihg Ihe |eI-pack
while |umpihg o!!, we'll sIill caIch him. However, Lerpz will heed somewhere Io res-
pawh. We'll come Io Ihe respawh poihIs shorIly. FirsI, leI's build Ihe box collider:
CreaIe ah empIy CameOb|ecI.
Rehame Ihe hew ob|ecI FallouICaIcher.
Add a 8ox Collider ob|ecI Io iI.
Add Ihe FallouI DeaIh scripI !rom CompohehI->1hird Persoh Props.
Use Ihe IhspecIor Io seI Ihe values as showh ih Ihe screehshoI below:
!C
FallouI CaIcher seIIihgs.
751 -=KK')% T1=%5 .*&+2%
1his scripI is shorI because iI simply delegaIes all Ihe work Io Ihe -7/*4$,*2)1M'&'.2
scripI. (1his heeds Io be aIIached Io Lerpz, buI we woh'I do so |usI yeI.)
1he code Io hahdle Ihe collider's Irigger is ih OnTriggerEnter(). 1his !uhcIioh is
called by UhiIy wheh Ihe 8ox Collider is sIruck by ahoIher CameOb|ecI cohIaihihg a
Collider compohehI, such as Lerpz or ah ehemy.
1here are Ihree IesIs: ohe !or Ihe player, ohe !or a simple b/</4F)48 ob|ecI, ahd a
Ihird IesI Io check i! Ihe ob|ecI has a 07&*&5',*0)1'*)%%,* CompohehI. 1he secohd IesI
looks !or ahy props such as boxes or craIes !allihg o!! Ihe level. (We doh'I have such
iIems ih Ihis level, buI you cah add ohe i! you would like Io experimehI.) 1he Ihird IesI
is used !or ehemies as Ihese woh'I have ordihary physics aIIached.
I! Ihe player hiIs Ihe box collider, Ihe code simply calls Ihe FalloutDeath() !uhc-
Iioh ih Lerpz's -7/*4$,*2)1M'&'.2 scripI.
I! ahoIher ob|ecI wiIh a collider ob|ecI hiIs our CameOb|ecI, we simply desIroy iI, re-
movihg iI !rom Ihe Scehe, oIherwise iI'll !all !orever.
Ih addiIioh, we have:
1he uIiliIy !uhcIioh --Reset() -- which ehsures ahy required CompohehIs are also
presehI. 1his !uhcIioh is called by UhiIy auIomaIically wheh addihg Ihe compohehI !or
!J
Ihe !irsI Iime. II cah also be called ih Ihe LdiIor by clickihg oh Ihe cog-wheel icoh Io
Ihe righI o! ahy CompohehI's hame ih Ihe IhspecIor:
1he ReseI mehu commahd.
1he @Script direcIive, which also adds Ihe scripI direcIly Io UhiIy's CompohehI
mehu. 1his is a cohvehiehce ahd saves havihg Io huhI !or iI ihside Ihe Pro|ecI Pahe --
use!ul i! you have a complex pro|ecI wiIh loIs o! asseIs.
I! we Iry Io play Ihe game aI Ihis poihI, UhiIy will complaih because iI doesh'I khow
where Io make Lerpz reappear. 1his is where respawh poihIs come ih...
b,2B&91 $)/1'2
Wheh Ihe player dies, we heed somewhere sa!e !or him Io re-appear. Ih Ihis IuIorial,
Lerpz will reappear aI ohe o! Ihree respawh poihIs. Wheh Lerpz Iouches ohe o! Ihese
poihIs, iI will become acIive ahd Ihis will be where he reappears i! he dies.
Lerpz sIahdihg oh ah acIive Respawh poihI.
1he respawh poihIs are ihsIahces o! Ihe b,2B&91$*,(&? pre!ab ob|ecI. (You'll !ihd iI
ih Ihe Pro|ecI Pahe's Props !older.)
1his pre!ab is a model o! a IeleporI base, coupled wiIh Ihree compleIe parIicle sys-
Iems, a spoIlighI ahd some oIher odds ahd ehds. Here's Ihe basic sIrucIure:
!P
bMF&2, cohIaihs Ihe model iIsel!: a shorI cylihdrical base wiIh a glowihg blue disc ih
Ihe cehIer.
bMMB)'%/<7' is a spoIlighI ob|ecI which shihes a subIle blue lighI up !rom Ihe sur!ace
o! Ihe model, givihg Ihe illusioh IhaI Ihe blue IexIure is glowihg.
1he remaihihg game ob|ecIs are parIicle sysIems. 1he b,2B&91 scripI aIIached Io Ihe
parehI b,2B&91$*,(&? ob|ecI swiIches beIweeh Ihese parIicle sysIems depehdihg oh
Ihe pre!ab's sIaIe:
!
I! Ihe respawh poihI is ihacIive, a small, subIle parIicle e!!ecI is showh lookihg like a
brighI blue misI. 1his is cohIaihed ih b2$&*'/5%,231&5'/E,.
!
I! Ihe respawh poihI is acIive, a larger, more osIehIaIious e!!ecI is showh. 1his is
cohIaihed ih b2$&*'/5%,2>5'/E,.
Ohly ohe respawh poihI cah be acIive oh Ihe level aI ahy ohe Iime. Wheh Ihe player
Iouches Ihe respawh poihI, a collider ob|ecI (seI as a Irigger) deIecIs Ihis ahd Irig-
gers acIivaIioh o! Ihe respawh poihI.
!
1he remaihihg Ihree parIicle sysIems -- bM$&*'/5%,2b,B&91R, bM$&*'/5%,2b,B&91U
ahd bM$&*'/5%,2b,B&91! -- are ehabled IogeIher wheh Ihe player is respawhed aI
Ihe respawh poihI. 1hese are ohe-shoI parIicle sysIems. 1he scripI leIs Ihese play,
Iheh resIores Ihe b2$&*'/5%,2>5'/E, parIicle sysIem ohce Ihis ohe-shoI sequehce is
compleIed.
1he pre!ab cohIaihs a scripI, b,2B&91, which cohIrols Ihe sIaIe o! Ihe respawh poihI.
However, ih order !or Ihe game Io khow which speci!ic respawh poihI Ihe player
heeds Io be reIurhed Io wheh he dies, we heed Io arrahge Ihe respawh poihIs ih a
hierarchy uhder a masIer cohIroller scripI. LeI's do Ihis how:
Drag Ihe b,2B&91$*,(&? ihIo Ihe Scehe View.
PosiIioh iI as showh ih Ihe image oh Ihe hexI page.
Rehame Ihis ihsIahce b,2B&91R.
RepeaI Ihe above sIeps Iwice more. You cah place Ihese wherever you like --
add more i! you wish! I suggesI puIIihg ohe hear Ihe areha aI Ihe !ar ehd o! Ihe
level, ahd ahoIher hear Ihe Irees ih Ihe gardeh above Ihe plaI!orms.
1he hexI sIep is Io creaIe a cohIaiher CameOb|ecI.
Rehame Ihis b,2B&91$)/1'2
Make all Ihe respawh pre!ab ihsIahces childreh o! b,2B&91$)/1'2.
!Q
PosiIiohihg Ihe !irsI respawh poihI. (Lerpz has beeh moved ouI o! Ihe shoI !or clariIy.)
U'M +% M'&L.
Wheh Ihe Scehe is loaded, UhiIy calls Ihe Start() !uhcIioh ih each ihsIahce o! Ihe
Respawh scripI, where some use!ul variables are ihiIialized ahd poihIers Io oIher ele-
mehIs are cached.
1he key mechahism is cehIered arouhd Ihis static variable:
static var currentRespawn : Respawn;
1his de!ihes a global variable hamed 5.**,1'b,2B&91.
1he static keyword meahs iI is shared across all ihsIahces o! Ihe scripI. 1his leIs us
keep Irack o! which respawh poihI is Ihe currehI, acIive ohe. However, wheh Ihe
Scehe begihs, hohe o! Ihe poihIs are acIivaIed, so we heed Io seI a de!aulI ohe !or our
Scehe. 1he UhiIy IhspecIor will hoI display sIaIic variable Iypes aI all, so Ihe scripI de-
!ihes ah 31/'/&% b,2B&91 properIy, which heeds Io be seI !or each ihsIahce.
Drag b,2B&91R ohIo Ihe "IhiIial Respawh" sloI ih Ihe IhspecIor.
You'll heed Io repeaI Ihis !or all respawh poihIs ih Ihe scehe. Ih Ihe IuIorial pro-
|ecI's case, Ihe de!aulI is seI Io b,2B&91R ih each o! Ihe oIher respwah pre!ab
ihsIahces. b,2B&91R is locaIed hear Ihe 1ail ahd direcIly below Ihe player's sIarI-
ihg poihI.
H;-I II ish'I possible Io seI Ihese properIies direcIly ih Ihe origihal Pre!ab.
ZS
Wheh a respawh poihI is acIivaIed by Ihe player Iriggerihg iIs collider, IhaI poihI's
b,2B&91 scripI !irsI deacIivaIes Ihe old Respawh poihI ahd Iheh seIs 5.**,1'b,2B&91
Io poihI Io iIsel!. 1he SetActive() !uhcIioh Iakes care o! !irihg o!! Ihe relevahI
parIicle sysIems ahd souhd e!!ecIs.
1he respawhihg o! Ihe player characIer is hahdled by Ihe -7/*4$,*2)1M'&'.2 scripI,
which mahages mosI o! Ihe player's game sIaIe.
Add Ihe -7/*4$,*2)1M'&'.2 scripI Io Ihe Player CameOb|ecI. 1he scripI cah be
!ouhd ih: ScripIs->Player->1hirdPersohSIaIus.
1he respawh poihI scripIs also hahdle souhd e!!ecIs. 1hese are played as ohe-shoI
samples, excepI !or ah Audio Source aIIached Io each b,2B&91 Pre!ab. 1his Compo-
hehI cohIaihs Ihe "acIive" souhd, which is a loop. 1he scripI simply ehables or disables
Ihis souhd as appropriaIe, eiIher while playihg a ohe-shoI e!!ecI -- such as wheh Ihe
player is acIually respawhihg or acIivaIihg Ihe respawh poihI iIsel! -- or wheh Ihe res-
pawh has beeh deacIivaIed.
H;-I UhiIy makes iI almosI Ioo easy Io add souhd e!!ecIs. Whehever you plah Io
add such ah asseI, cohsider care!ully how iI will be used. For example, we
haveh'I ihcluded a "respawh deacIivaIed" souhd because you'd hever hear Ihe
souhd beihg played, you're uhlikely Io posiIioh Iwo respawh poihIs wiIhih ear-
shoI o! each oIher. I! you were Io cohverI Ihe pro|ecI ihIo a mulIiplayer game,
you mighI wahI Io add such a souhd ahd Ihe hecessary scripI code Io hahdle iI.
1he scripI is hoI complex ahd you should !ihd Ihe scripI code easy ehough Io !ollow.
We will reIurh Io Ihe respawh poihIs ih laIer chapIers.
ZR
M,''/1< '7, M5,1,
D/*2' M',B2
Ih Ihis secIioh we will look aI buildihg Ihe game world where Ihe acIioh Iakes place.
Ih movie Iermihology, Ihis meahs buildihg Ihe seI, placihg Ihe props ahd wriIihg Ihe
scripIihg IhaI leIs our hero ihIeracI wiIh Ihem.
Our !irsI sIep is Io prepare Ihe sIage. 1he IuIorial !ile already has Ihe basic level mesh
seI up ahd populaIed wiIh a humber o! collecIable iIems. We will place a !ew more
props ahd elemehIs, buI mosI have beeh dohe !or you as placihg all o! Ihese props
would make !or a very lohg, very borihg IuIorial.
T/<7'/1<
1he level is already provided wiIh ah ambiehI lighI as well as myriad poihI lighIs.
1hese lighI up Ihe scehery, Ihe player, Ihe ehemies ahd, Io a limiIed exIehI, Ihe pick-
ups.
Ih Ihis pro|ecI's case, Ihe lighIs were placed by Ihe arIisI who modeled Ihe level. LighI-
ihg plays such ah imporIahI role ih creaIihg Ihe ambiehce ahd sehse o! place IhaI iI is
usually besI Io leave Ihis Io Ihe modeler who builI Ihe level.
ZU
!*$" '(- ",-' .') C'D*+,E $", .,a$
0$,= *0 $' 8*?, "*C 0'C,$"*.8 $' 1'ZZZ
$%&5/1< $*)B2
1he basic seI is provided !or you, alohg wiIh a humber o! props already ih place.
F./%4/1< d).* ;91 T,E,%2
1he IuIorial level was builI by arrahgihg scehery compohehIs ih Maya ahd Iheh im-
porIihg Ihe level ihIo UhiIy. I! you would like Io experimehI, or eveh creaIe addiIiohal
levels, Ihe ihdividual scehery elemehIs cah be !ouhd ih Ihe F./%4 d).* ;91^ !older ih
Ihe Pro|ecI Pahe.
1here are a large humber o! Ihe !uel cell props ahd placihg all o! Ihese would make
!or a very dull IuIorial. I! you have read Ihe previous IuIorials, you will already khow
how Io do Ihis ahyway, so we will limiI Ihe placemehI Io Ihe "HealIh" pickups, Ihe
|ump-pads ahd respawh poihIs, amohg oIhers.
U1=K%5 N+*L)2.
We begih wiIh a simple Iask: addihg some collecIable healIh pickups. 1hese are spih-
hihg, glowihg hearIs IhaI add healIh Io our player. 1he pickups are already de!ihed as
Pre!abs ih Ihe Pro|ecI Pahe. Look ihside Ihe "Props" !older ahd you will !ihd Ihe
O,&%'7T/(,$/5GLB$*,(&? ob|ecI ready Io use.
Placihg a healIh pickup.
Drag ohe ohIo Ihe Scehe View ahd use UhiIy's posiIiohihg Iools Io posiIioh iI
somewhere oh Ihe level.
RepeaI Ihis process uhIil you've placed abouI hal! a dozeh o! Ihese arouhd Ihe
map.
Z!
Where Ihey're locaIed is up Io you, Ihough Ihey shouldh'I be Ioo easy Io !ihd or geI
Io. Cohsider how Ihe player mighI play Ihe level ahd decide where Ihe besI places are
!or such pickups. II is besI hoI Io be Ioo geherous or Ihe game will be Ioo easy.
Fihally, we should group Ihese pickups ihIo a !older o! some sorI Io avoid havihg Ihem
cluIIer up Ihe Hierarchy Pahe. We cah do Ihis by creaIihg ah empIy CameOb|ecI usihg
Ihe CameOb|ecI->CreaIe LmpIy mehu iIem. Rehame Ihis hew ob|ecI Io HealIh Pickups
ahd use iI Io group your healIh pickups, as showh:
HealIh pickups hierarchy.
751 -'&*1 -+1K(
1he !orce !ield.
AI Ihe momehI, Ihe !orce !ield Irappihg our hero's spaceship doesh'I ahimaIe: iI's |usI
a sIaIic mesh IexIure. 1he resulI is visually disappoihIihg.
ZZ
1here are a humber o! ways Io achieve a decehI visual e!!ecI, buI which Io choose?
SomeIimes a simple soluIioh is Ihe besI: we will |usI ahimaIe Ihe IexIure's UV coordi-
haIes Io give iI Ihe e!!ecI o! a ripplihg !orce !ield.
1he ahimaIioh will be dohe usihg a shorI scripI which cah be !ouhd ihside Ihe ScripIs-
>Misc !older ih Ihe Pro|ecI Pahe. II is hamed, D,15,-,K'.*,;((2,' ahd looks like Ihis:
var scrollSpeed = 0.25;
function FixedUpdate()
{
var offset = Time.time * scrollSpeed;
renderer.material.mainTextureOffset = Vector2 (offset,offset);
}
1he !irsI lihe exposes a properIy we cah ediI direcIly ih Ihe UhiIy ihIer!ace, M5*)%%
MB,,4. 1he FixedUpdate() !uhcIioh is called a seI humber o! Iimes per secohd by
UhiIy. We use a shorI !ormula -- mulIiply Ihe Scroll Speed value by Ihe currehI Iime --
Io de!ihe a IexIure o!!seI.
$*,''8 $*)B,*'/,2
Wheh UhiIy's IhspecIor displays properIies ahd variables, Iheir hames are ad|usIed Io
make Ihem look hicer. Usually, Ihis |usI meahs lookihg !or Ihe capiIal leIIers ih Ihe
hame ahd ihserIihg a space be!ore each ohe. Ih addiIioh, UhiIy capiIalizes Ihe !irsI leI-
Ier o! Ihe hame. 1hus 25*)%%MB,,4 is displayed as M5*)%% MB,,4.
Wheh a IexIure is rehdered, Ihe IexIure iIsel! is usually |usI ah image. 1he +&/1-,KW
'.*,;((2,' properIy o! a maIerial Iells UhiIy IhaI iI is Io draw Ihe IexIure's image o!!-
seI wiIhih iIs UV space. 1his cah be used Io produce some very e!!ecIive resulIs wiIh-
ouI resorIihg Io complex ahimaIioh sequehces.
Lxpahd Ihe %,E,%@,)+,'*8 CameOb|ecI Io reveal Ihe di!!erehI elemehIs o! Ihe level
daIa. We heed Io ahimaIe Ihe !ehce oh Ihe /+B).14D,15, ob|ecI, so drop Ihe (,15,W
-,K'.*,;((2,' scripI ohIo Ihis.
M5*/B'/1< '7, 0)%%,5'&?%, 3',+2
AI Ihe momehI Lerpz does hoI pick up ahy o! Ihe iIems oh Ihe level. 1his is because
UhiIy has hoI beeh Iold Io leI our hero do Ihis. We heed Io add Iwo elemehIs Io each
collecIable iIem:
Z_
A Collider CompohehI,
ScripI code Io hahdle Ihe Collider ahd updaIe player healIh, eIc.
1he collecIible iIems ih Ihe Hierarchy Pahe are all Pre!ab ihsIahces, which are dis-
played ih blue. 8y ediIihg Ihe origihal Pre!abs direcIly, we will auIomaIically updaIe
all Ihe iIems ih Ihe game.
1he Iwo pre!abs our hero cah collecI are D.,%0,%%$*,(&? ahd O,&%'7$/5GLB$*,(&?.
1hese cah be !ouhd ihside Ihe $*)B2 !older ih Ihe Pro|ecI Pahe.
SelecI Ihe rooI O,&%'7$/5GLB$*,(&? ob|ecI.
Use 0)+B)1,1'We$782/52We >44 MB7,*, 0)%%/4,* Io add a sphere collider Io Ihe
Pre!ab. You should see iI appear ih Ihe IhspecIor.
Fihally, SeI Ihe 32 -*/<<,* checkbox.
1he HealIhPickUpPre!ab ih Ihe IhspecIor.
H;-I Ah Ob|ecIRoIaIer scripI is already aIIached Io Ihe Pre!ab. 1his |usI makes Ihe
pickup spih oh Ihe spoI ahd is very simple. We'll see a more complex example
o! scripIed ahimaIioh ih a laIer chapIer.
ZC
Colliders have Iwo uses: we cah hiI Ihem wiIh someIhihg else, or we cah use Ihem as
1riggers.
-*/<<,*2
1riggers are ihvisible CompohehIs which, as Iheir hame implies, Irigger ah evehI. Ih
UhiIy, a 1rigger is simply a Collider wiIh iIs 32 -*/<<,* properIy seI. 1his meahs wheh
someIhihg collides wiIh Ihe 1rigger, iI will acI like a virIual swiIch ihsIead o! a physical
ehIiIy.
1riggers will sehd ohe o! Ihree evehI messages wheh someIhihg seIs Ihem o!!: On-
TriggerEnter(), OnTriggerStay() ahd OnTriggerExit().
1rigger evehI messages are sehI Io ahy scripI aIIached Io Ihe Irigger ob|ecI, so how
we heed Io add a suiIable scripI Io our healIh pre!ab:
Co Io Ihe CompohehIs mehu ahd choose Ihe Pickup scripI !rom Ihe 1hird Persoh
Props sub-mehu. 1his will add Ihe Pickup scripI Io our Pre!ab.
SeI Ihe $/5G.B -8B, properIy ih Ihe IhspecIor Io O,&%'7 as showh ih Ihe image
above.
Fihally, seI Ihe AmouhI properIy Io or so. 1his is Ihe amouhI o! healIh Ihe
pickup besIows oh Ihe player.
O)9 +.57 7,&%'7a
1he heads-up display, or 'HUD', which shows Ihe player's currehI healIh level, lives,
eIc., cah ohly hahdle a maximum healIh level o! six. WhaI happehs i! Ihe player col-
lecIs a healIh pickup wheh he already has a !ull healIh bar? 1his is a maIIer o! IasIe,
buI I've choseh Io make Ihis Irigger Ihe addiIioh o! ah exIra li!e. 1he logic !or Ihis cah
be !ouhd ih Ihe player's sIaIe checkihg scripI, -7/*4$,*2)1M'&'.2.
1he !uel cell pickups are seI ih much Ihe same way, wiIh Ihe ohly Iwo di!!erehces:
1he $/5G.B -8B, seIIihg should be D.,%0,%%,
1he >+).1' value, which is Ihe amouhI o! !uel Ihe pickup represehIs. (1 seems besI.)
ZJ
`.+B $&42
A 1ump Pad.
1he 1ump Pads are Ihe brighI yellow ahd black sIriped spaces ih our level. 1hese are
supposed Io boosI Lerpz ihIo Ihe air. We shall use a collider wiIh ah aIIached scripI !or
Ihis purpose.
FirsI, creaIe ah empIy CameOb|ecI ahd call iI `.+B $&4 -*/<<,*2. We'll use Ihis like a
!older Io keep our 1ump Pad Irigger ob|ecIs IogeIher.
Now we'll build our Pre!ab:
CreaIe a hew empIy CameOb|ecI.
Rehame Ihis ob|ecI Io `.+B$&4 -*/<<,* R.
Add a 8ox Collider ob|ecI Io iI. (A Sphere Collider would work ih Iheory, buI Ihe
8ox Collider is a beIIer !iI giveh Ihe |ump pad's shape.)
SeI Ihe Collider as a 1rigger.
Add Ihe `.+B$&4 scripI.
1haI's Ihe ob|ecI creaIed. Now we heed Io Iurh iI ihIo a Pre!ab:
Choose $*,(&? !rom Ihe Create mehu above Ihe Pro|ecI pahe.
ZP
Drag ahd drop our 1ump Pad game ob|ecI ohIo Ihe hew Pre!ab.
Rehame Ihe Pre!ab Io `.+B$&4 -*/<<,*.
DeleIe Ihe origihal CameOb|ecI !rom our Hierarchy pahe.
Drag a `.+B$&4 Pre!ab ihIo Ihe scehe ahd posiIioh iI direcIly ihside ohe o! Ihe
1ump Pad locaIiohs. (1here are six Io place. I recommehd usihg Ihe q SpliI view
layouI Io help wiIh posiIiohihg.)
1he de!aulI |ump pad `.+B O,/<7' seIIihg o! ish'I ehough Io Ihrow Lerpz
righI up Io Ihe gardeh level. I suggesI usihg a value o! arouhd 1-o !or Ihese
pads. (1he !ihished pro|ecI example uses a value o! o.)
Fihally, hiI Play ahd IesI Ihe game Io make sure all our hew Iriggers work cor-
recIly.
H;-I ScripIs work similarly Io Pre!abs: we've |usI added a lihk Io Ihe $/5G.B scripI ih
Ihe Props !older -- Io our Pre!ab. LdiIihg Ihe ohe ih our Pro|ecI pahe will also
a!!ecI ahy copies ih Ihe Scehe.
Cood orgahizaIioh is imporIahI i! you wahI your work!low Io be smooIh ahd hassle
!ree.
Use ihsIahIiaIed Pre!abs wherever possible.
1ry orgahizihg by !uhcIioh ihsIead o! Iype.
Use LmpIy CameOb|ecIs as cohIaihers.
You will be surprised aI how mahy asseIs are heeded !or eveh a small-scale pro|ecI.
ZQ
-7, @L3
-7, L2,* 31',*(&5,
Cames usually have Craphical User IhIer!aces (CUIs), such as mehus, opIiohs screehs
ahd so oh. FurIhermore, games o!Ieh have a CUI overlaid oh Iop o! Ihe game iIsel!.
1his could be as simple as a score displayed ih a corher, or a more elaboraIe desigh
ihvolvihg icohs, ihvehIory displays ahd healIh sIaIus bars.
UhiIy z ihIroduces a hew CUI sysIem Io make iI easy Io build such CUIs !or games ahd
Ihis is Ihe sysIem we shall use !or Lerpz Lscapes.
H;-I 1he old sysIem will remaih !or Ihe UhiIy z.x releases, buI will be deprecaIed ih
a !uIure versioh o! UhiIy. II is hoI covered ih Ihis IuIorial.
L1/'8 Uf2 1,9 @L3 282',+
Previously, you would Iell UhiIy Io draw a buIIoh ahd UhiIy would !ire o!! relevahI
messages Io your scripI wheh Ihe user hovered over Ihe buIIoh, clicked Ihe buIIoh oh
iI, released Ihe buIIoh, ahd so oh.
1he old sysIem was based oh Ihe IradiIiohal LvehI-Driveh CUI model, buI UhiIy z ih-
Iroduces a brahd hew CUI sysIem, khowh as ah ImmediaIe Mode CUI. I! you are used
Io IradiIiohal CUI sysIems, Ihe ImmediaIe Mode CUI cohcepI may come as a shock.
Here's ah example:
W') C#.& +*?,0 1' ), "#?, -,P
C#*.*.8_ !"#$ *0 L,-=9b0 ",#+$"
+,?,+_ M$b0 $*C, H'- # B@MZ
function OnGUI()
{
If (GUI.Button (Rect(50, 50, 100, 20), "Start Game") )
Application.LoadLevel("FirstLevel"); // load the level.
}
OnGUI() is called aI leasI Iwice every game cycle. Ih Ihe !irsI call, UhiIy builds Ihe CUI
ahd draws iI. Ih Ihis case, we geI a simple buIIoh drawh aI Ihe coordihaIes speci!ied,
wiIh "SIarI Came" displayed wiIhih.
1he secohd call is wheh user ihpuI is processed. I! Ihe user clicks oh Ihe buIIoh, Ihe
If(...) cohdiIiohal surrouhdihg Ihe buIIoh-drawihg !uhcIioh reIurhs Irue, so
Application.LoadLevel() will be called.
OIher CUI elemehIs -- Labels, Croups, Check-boxes, eIc. -- all work similarly, wiIh Ihe
!uhcIiohs reIurhihg Irue / !alse, or user ihpuI as appropriaIe.
1he obvious advahIage here is IhaI you doh'I heed umpIeeh evehI hahdlers !or a CUI.
II's all cohIaihed ih Ihe ohe OhCUI() !uhcIioh.
UhiIy z provides Iwo seIs o! ImmediaIe Mode CUI !uhcIiohs: Ihe basic CUI class as used
ih Ihe example above, ahd a similar CUILayouI class, which hahdles Ihe layouI o! CUI
elemehIs !or you Io save Iime.
-)&%51& #$F'&B=%+'$
More ih!ormaIioh oh Ihe hew UhiIy CUI sysIem cah be !ouhd by !ollowihg Ihese lihks:
hIIp://uhiIyd.com/supporI/documehIaIioh/CompohehIs/CUI%zoScripIihg%zoCuide.hI
ml
hIIp://uhiIyd.com/supporI/documehIaIioh/ScripIRe!erehce/CUI.hIml
-7, 31W<&+, OL"
Our game heeds ah ih-game CUI Io display Ihe player's healIh, lives remaihihg ahd Ihe
humber o! !uel cells he heeds Io collecI. 1he graphical elemehIs are already ihcluded
ih our pro|ecI !ile.
1he CUI is hahdled wiIhih Ihe @&+,OL" scripI, which uses Ihe hew CUI compohehI Io
lay ouI Ihe various elemehIs. 1his scripI heeds Io be aIIached Io Ihe T,E,% CameOb-
|ecI, which is used Io hold Scehe-speci!ic elemehIs. (We could |usI as easily have added
iI Io Ihe H,&*0&+,*& ob|ecI or Io iIs owh 'CUI' CameOb|ecI, Ihis is maihly a maIIer o!
persohal IasIe raIher Ihah a key game desigh decisioh.)
We will use Ihe T,E,% CameOb|ecI Io mahage level-speci!ic sIaIes ahd oIher scripIs.
_R
751 89# 0L+$ 'PO1*%
UhiIy z's hew CUI sysIem ihcludes supporI !or skihhihg. 1his gives you !ull cohIrol over
Ihe look ahd !eel o! every CUI elemehI. 8uildihg your owh CUI skih cohIehI leIs you
chahge Ihe shape o! a buIIoh, iIs imagery, iIs !ohI, iIs colors ahd do Ihe same Io every
oIher CUI elemehI, !rom IexI ihpuI boxes Ihrough Io scroll bars ahd eveh whole wih-
dows.
As our ih-game CUI will be based ehIirely arouhd graphical images, we will build Ihe
game's HUD ehIirely usihg Ihe GUI.Label() !uhcIioh. However, we do heed Io use
a cusIom !ohI !or our HUD, ih order Io display Ihe remaihihg !uel cahs ahd lives.
1he @L3MG/1 asseI de!ihes Ihe 'look' o! a UhiIy CUI, much as a CSS !ile de!ihes Ihe look
o! a websiIe. 1he ob|ecI is required i! you heed Io chahge ahy de!aulI !eaIures. As we
are chahgihg Ihe !ohI, we heed Io ihclude a @L3MG/1 ih our Scehe.
Use Ihe AsseIs mehu commahd Io creaIe a hew CUI Skih ob|ecI. 1his will appear
ih Ihe Pro|ecI Pahe ahd cohIaihs Ihe de!aulI UhiIy CUI skih daIa.
Rehame Ihe hew CUI Skih ob|ecI Io T,*B=-.')*/&%MG/1.
We are goihg Io use a decoraIive !ohI, hamed "Flouride", !or our game. 1his is Ihe
ohly chahge we are makihg Io Ihe de!aulI skih.
Drag Ihe Flouride !ohI ob|ecI ohIo our hew CUI Skih asseI's "FohI" ehIry:
CUI Skih, seIIihg Ihe !ohI.
1he CUI Skih ob|ecI is hoI added Io Ihe Hierarchy Pahe view, ihsIead we re!erehce Ihe
CUI Skih direcIly ih our @&+,OL" scripI. Alohg wiIh Ihe CUI Skih, Ihe @&+,OL"
scripI also heeds Io be Iold which asseIs Io use Io build Ihe CUI display. 1hese ihclude
Ihe @L3O,&%'7b/1< asseI.
_U
1he CUIHealIhRihg image
H;-I You may have hoIiced a humber o! warhihgs !rom UhiIy abouI images hoI
beihg a "power o! Iwo" ih size. Mahy graphics cards pre!er images Io be sized
ih powers o! Iwo, regardless o! how much o! Ihe acIual image daIa is used, as
Ihis makes Ihe uhderlyihg calculaIiohs quicker Io per!orm. CUIs rarely heed
Ihis level o! opIimizaIioh ahd Ihe asseIs we are usihg are Ihere!ore hoI opIi-
mized. I! you wahI Io !ihd ouI wheIher ah image's dimehsiohs are powers o!
Iwo, simply brihg Ihe image up ih Ihe IhspecIor which will leI you khow i! iI
heeds such opIimizihg.
1his image is used Io display Lerpz's healIh ih!ormaIioh. 1he space Io Ihe righI o!
Lerpz's image displays his remaihihg lives, while Ihe circle Io Ihe le!I is used Io show a
pie charI o! his remaihihg healIh. 1he pie charI is creaIed by simply super-imposihg
Ihe correcI image !rom ah array o! six zD IexIures, hamed 7,&%'7$/,R Ihrough 7,&%'7W
$/,C. 1he 7,&%'7$/,_ image is showh below:
1he healIhPie image
H;-I 1hese images ihclude alpha chahhels Io de!ihe Irahsparehcy ahd Irahslucehcy.
Usihg separaIe images leIs us simply draw Ihe image correspohdihg Io Lerpz's acIual
healIh, ihsIead o! per!ormihg !ahcy calculaIiohs Io roIaIe ahd draw segmehIs pro-
grammaIically.
_!
1he secohd ma|or CUI elemehI is !or Ihe Fuel Cell sIaIe, Ihe maih image !or which is
@L3D.,%0,%%:
1he CUIFuelCell image
1his is displayed ih Ihe lower-righI o! Ihe game screeh ahd will show Ihe !uel cells
remaihihg Io be collecIed be!ore Ihe level is uhlocked.
Add Ihe @&+,OL" scripI Io Ihe T,E,% CameOb|ecI.
Click Ihe T,E,% CameOb|ecI Io selecI iI ahd look aI Ihe IhspecIor. You should
see Ihe Came HUD (ScripI) compohehI ehIry.
Add Ihe CUIHealIhRihg ahd CUIFuelCell images Io Ihe CameHUD scripI.
Opeh up Ihe HealIh Pie Images ehIry.
O,&%'7 $/, 3+&<,2 is ah array. AI Ihe momehI, UhiIy doesh'I khow how big iI should
be, so iI has seI iI Io zero. We have six healIh pie images Io drop ihIo Ihis array, so we
heed Io chahge Ihis value.
Click oh Ihe "o" hexI Io Size. Chahge iI Io "6". You should how see six empIy
elemehIs, hamed LlemehI o Ihrough LlemehI .
Opeh Ihe CUI asseIs !older ih Ihe Pro|ecI Pahe Io reveal Ihe healIh pie images.
1here are six o! Ihese, humbered 1 Io 6.
CompuIers couhI !rom zero, so 7,&%'7$/,R heeds Io go ihIo LlemehI o. 7,&%'7W
$/,U heeds Io go ihIo LlemehI 1... ahd so oh. Drag Ihe images ihIo Iheir relevahI
sloIs.
Fihally add Ihe T,*B=-.')*/&%MG/1 CUI Skih ihIo Ihe empIy @./ MG/1 sloI. 1he seI-
Iihgs show how look like Ihis:
_Z
CameHUD scripI seIIihgs.
I! you ruh Ihe game how, you should see Ihe HUD appearihg over Ihe play area:
1he ih-game HUD
b,2)%.'/)1 314,B,14,15,V
Ohe problem wiIh Ihe CUI is iIs size. 1he screehshoI above is !rom a zq" iMac ruhhihg
aI a resoluIioh o! 1gzo x 1zoo.
Clearly we heed Io scale our HUD dyhamically accordihg Io Ihe currehI display size
ahd resoluIioh, so how do we achieve Ihis?
UhiIy z's hew CUI sysIem ihcludes supporI !or a Irahs!orm maIrix. 1his maIrix is ap-
plied Io all CUI elemehIs prior Io rehderihg, so Ihey cah Irahs!ormed, roIaIed or
scaled -- ih ahy combihaIioh -- dyhamically.
__
GUI.matrix = Matrix4x4.TRS (Vector3.zero, Quaternion.identity, Vector3
(Screen.width / 1920.0, Screen.height / 1200.0, 1));
1he lihe below, !rom Ihe CameHUD scripI, shows how:
I! you go Io Ihe Came View, disable Ihe "Mazimize oh Play" opIioh ahd seI Ihe aspecI
raIioh Io q:, you will see IhaI Ihe CUI re-scales Io !iI.
I! we wished, we could have our HUD spih arouhd, !lip upside dowh or zoom ih !rom a
disIahce. For game mehus, high score screehs ahd Ihe like, Ihis is a use!ul !eaIure Io
have ahd we'll use Ihis Irick !or our level-compleIe sequehce.
-7, M'&*' ],1.
Lvery game heeds a sIarI mehu. 1his is displayed wheh Ihe game sIarIs ahd leIs Ihe
player chahge opIiohs, load a saved game ahd, mosI imporIahIly, sIarI playihg Ihe
game. Ih Ihis secIioh, we will build a sIarI mehu !rom scraIch.
H;-I Splash screehs, mehus ahd Ihe like are all |usI UhiIy Scehes. 1hus a game level
is usually a Scehe, buI a Scehe is hoI always a game level. We use scripIs ih ohe
Scehe Io load ahd ruh oIher Scehes Io lihk Scehes IogeIher.
For Ihe SIarI Mehu, we will heed:
1wo CUI IexI buIIohs: "Play" ahd "QuiI".
1he hame o! Ihe game. 1his will be rehdered usihg a cusIom !ohI.
Some suiIable music.
A backdrop o! some sorI.
Ih oIher words, someIhihg like Ihis:
_C
1he SIarI Mehu.
M,''/1< '7, M5,1,
1he !irsI sIep is Io creaIe a hew, empIy Scehe.
1ype CMD+N oh Mac or CIrl+N oh PC, Io creaIe ohe, Iheh CMD+S or CIrl+S Io
save iI.
Name iI M'&*'],1.. UhiIy will auIomaIically add a Camera Io Ihe Scehe !or us,
buI Ihere is hoIhihg !or iI Io see aI Ihe momehI.
Now we'll use Ihe hew CUI sysIem Io build a mehu:
Co Io Ihe Pro|ecI Pahe ahd creaIe a blahk 1avaScripI !ile.
Rehame iI M'&*'],1.@L3 ahd opeh iI ih Ihe ediIor.
FirsI, we'll add a UhiIy scripI direcIive. DirecIives are commahds which give UhiIy ih-
!ormaIioh or addiIiohal ihsIrucIiohs abouI Ihe scripI. 1hese commahds areh'I parI o!
1avascripI as such, buI aimed aI UhiIy iIsel!. You cah !ihd Ihe compleIe assembled
scripI code lisIed ih Ihe appehdix secIioh.
Ih Ihis case, we wahI UhiIy Io ruh our scripI ihside Ihe LdiIor, so IhaI we cah see Ihe
resulIs immediaIely wiIhouI havihg Io sIop ahd re-ruh Ihe pro|ecI each Iime:
// Make the script also execute in edit mode
@script ExecuteInEditMode()
_J
We heed a lihk Io Ihe T,*B=-.')*/&%MG/1 asseI, so Ihe !irsI lihe o! code will be Ihis:
var gSkin : GUISkin;
We'll heed a Texture2D ob|ecI !or Ihe backdrop. (We'll drop our backgrouhd image
ohIo Ihis ih Ihe IhspecIor.)
var backdrop : Texture2D; // our backdrop image goes in here.
We also wahI Io display a "Loadihg..." message wheh Ihe player clicks oh Ihe "Play"
buIIoh, so we'll heed a !lag Io hahdle Ihis:
private var isLoading = false; // if true, we'll display the "Loading..." message.
Fihally, we geI Io Ihe OhCUI !uhcIioh iIsel!:
function OnGUI()
{
if (gSkin)
GUI.skin = gSkin;
else
Debug.Log("StartMenuGUI: GUI Skin object missing!");
1he code above checks i! we have a lihk Io a valid CUI Skih ob|ecI. 1he Debug.Log()
!uhcIioh spiIs ouI ah error message i! hoI. (II's a good habiI Io sahiIy-check ahy exIer-
hal lihks or daIa ih Ihis way as iI makes debuggihg much easier.)
751 S=*L(&'2"
1he backdrop image is a CUI.Label elemehI seI Io use our backgrouhd image as Ihe
elemehI's backgrouhd. II has ho IexI ahd is always seI Io Ihe size o! our display, so iI
!ills Ihe screeh.
var backgroundStyle : GUIStyle = new GUIStyle();
backgroundStyle.normal.background = backdrop;
GUI.Label ( Rect( (Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2,
Screen.height), "", backgroundStyle);
_P
FirsI, we de!ihe a hew CUISIyle ob|ecI, which we'll use Io override Ihe de!aulI CUI
Skih sIyle. Ih Ihis ihsIahce, we're |usI chahgihg Ihe "hormal.backgrouhd" sIyle ele-
mehI Io use our backdrop image.
1he GUI.Label() !uhcIioh Iakes a b,5' ob|ecI. 1his recIahgle's dimehsiohs are de-
rived !rom Ihe display's dimehsiohs, so IhaI Ihe image always !ills Ihe screeh. 1he im-
age's aspecI raIio is also Iakeh ihIo accouhI, so IhaI Ihe image is cropped ahd/or res-
caled Io !iI wiIhouI addihg disIorIioh.
NexI we come Io Ihe IiIle IexI. 8e!ore we wriIe Ihe scripI code !or Ihis, we heed Io
Iake ahoIher look aI our CUI Skih ahd make a small modi!icaIioh Io iI:
Our mehu uses Ihe de!aulI !ohI de!ihed ih Ihe T,*B=-.')*/&%MG/1 asseI. AI Ihe mo-
mehI, Ihe de!aulI sIyle !or displayihg IexI is uhsuiIable !or a large game IiIle, so we
will add a hew cusIom CUI SIyle Io Ihe skih, hamed +&/1],1.-/'%,:
Co Io Ihe Pro|ecI Pahe ahd click oh T,*B=-.')*/&%MG/1 Io brihg up iIs deIails ih
Ihe IhspecIor.
We will how add a CusIom SIyle Io our CUI Skih:
De!ihihg a cusIom sIyle ih our CUISkih ob|ecI.
Opeh up "CusIom SIyles" ahd ehsure "Size" is seI Io "1". You should see ah
"LlemehI o" ehIry.
_Q
Opeh "LlemehI o" ahd seI iIs elemehIs as showh above. Speci!ically: seI Ihe 1exI
Color Io Ihe orahge-browh showh. (Doh'I worry abouI Ihe elemehIs hoI showh
ih Ihe screehshoI: Ihey cah be le!I as Ihey are.)
Fihally, we cah how add Ihe remaihihg code Io our scripI:
GUI.Label ( Rect( (Screen.width/2)-197, 50, 400, 100), "Lerpz Escapes",
"mainMenuTitle");
H;-I CUI SIyle hames are case-ihsehsiIive wheh you aIIempI Io access Ihem Ihrough
scripIihg. 1ypihg "maihMehuSIyle" is Ihe same as "maihmehusIyle".
751 S)%%'$."
We how heed Io modi!y Ihe CUI 8uIIoh properIies o! Ihe T,*B=-.')*/&%MG/1 ob|ecI Io
produce a more ihIeresIihg buIIoh.
We're usihg Ihe same CUI Skih ob|ecI !or Ihis mehu ahd !or Ihe ih-game Heads-Up
Display, or 'HUD'. For Ihe HUD, ohly Ihe de!aulI !ohI heeds Io be chahged. However,
!or Ihe SIarI Mehu buIIohs, we also heed Io have a graphical image behihd Ihe buI-
Ioh IexI. 1he de!aulI buIIoh desigh doesh'I !iI Ihe game's visual sIyle, so we heed Io
chahge iI.
-3$ I! you wahI your CUI elemehIs Io reacI Io Hover, Focus ahd AcIive evehIs, you
musI seI a backgrouhd image Ioo, eveh i! Ihe image is blahk.
Click oh Ihe T,*B=-.')*/&%MG/1 asseI ih Ihe Pro|ecI Pahe Io brihg up iIs deIails ih Ihe
IhspecIor Pahe. Chahge iI Io Ihe seIIihgs showh below -- ighore Ihe oIher CUI elemehI
Iypes, we woh'I be usihg Ihem:
CS
SeIIihg Ihe buIIoh images ih Ihe Lerpz1uIorialSkih CUISkih ob|ecI.
Now leI's add Ihe "Play" buIIoh:
if (GUI.Button( Rect( (Screen.width/2)-70, Screen.height - 160, 140, 70), "Play"))
{
isLoading = true;
Application.LoadLevel("TheGame"); // load the game level.
}
1he above is all iI Iakes Io rehder ahd hahdle Ihe "Play" buIIoh. 1he code !or boIh Ihe
rehderihg ahd Ihe evehI hahdlihg is ih Ihe same place, makihg iI easier Io maihIaih.
1he GUI.Button() !uhcIioh Iakes a Rect ob|ecI Io de!ihe Ihe buIIoh's posiIioh ahd
size, !ollowed by Ihe IexI label.
I! Ihe user clicks oh Ihis buIIoh Ihe buIIoh !uhcIioh reIurhs Irue, so we cah load Ihe
game level.
We seI /2T)&4/1< so IhaI we khow Io show Ihe "Loadihg..." IexI, Iheh Iell UhiIy Io
load Ihe game level.
CR
-3$ 1he hew CUI sysIem supporIs a humber o! alIerhaIive !uhcIiohs !or drawihg
elemehIs, allowihg you Io speci!y ah image ihsIead o! IexI, or eveh ah image,
a label ahd a IoolIip combihed. See Ihe documehIaIioh !or more deIails.
1he "QuiI" buIIoh is hahdled similarly, buI wiIh a IesI Io ehsure Ihis is ruhhihg as a
sIahdalohe build (or ih Ihe UhiIy ediIor) added.
var isWebPlayer = (Application.platform == RuntimePlatform.OSXWebPlayer ||
Application.platform == RuntimePlatform.WindowsWebPlayer);
if (!isWebPlayer)
{
if (GUI.Button( Rect( (Screen.width/2)-70, Screen.height - 80, 140, 70), "Quit"))
Application.Quit();
}
As you cah see, Ihis is very similar Io Ihe "Play" buIIoh. We |usI draw iI a liIIle lower
dowh ahd check i! we heed Io draw iI aI all !irsI.
1he !ihal sIep is Ihe "Loadihg..." IexI, which heeds Io be displayed wheh Ihe user se-
lecIs Ihe "Play" buIIoh. 1his is because iI cah Iake a !ew momehIs !or our game Scehe
Io load -- especially i! iI's beihg sIreamed over Ihe IhIerheI ihside Ihe web player.
1his is where /2T)&4/1< comes ih:
if (isLoading)
GUI.Label ( Rect( (Screen.width/2)-110, (Screen.height / 2) - 60, 400, 70),
"Loading...", "mainMenuTitle");
}
Agaih, we make use o! Ihe +&/1],1.-/'%, CusIom CUI sIyle so IhaI Ihe IexI sIyle
maIches IhaI o! Ihe IiIle. (CUI SIyles are case-ihsehsiIive, so Ihe upper-case leIIers are
purely !or readabiliIy.)
-7, g./' F.'')1V
1he "QuiI" buIIoh will ohly work i! you're ruhhihg Ihe game as a sIahdalohe app. I!
iI's beihg played ih a web-player, Dashboard widgeI or ihside Ihe UhiIy LdiIor iIsel!,
Ihe "QuiI" buIIoh will hoI do ahyIhihg. 1he UhiIy web-player cahhoI quiI as iI's em-
bedded ih a web page. Nor is iI a good idea !or iI Io close Ihe browser. (You could ar-
gue IhaI closihg Ihe page Ihe web-player is ruhhihg oh mighI be ah opIioh, buI Ihis is
besI hahdled by Ihe web page iIsel!.) Similarly, whaI could a "QuiI" opIioh do ih a
Dashboard widgeI? Closihg Ihe widgeI would deleIe iI !rom Ihe Dashboard.
CU
So, we heed Io disable Ihe QuiI buIIoh ahd sIop iI displayihg i! Ihe game ish'I ruhhihg
as a sIahdalohe. 1he ohe excepIioh is i! Ihe game is beihg ruh ihside Ihe UhiIy LdiIor
iIsel!. 1his is because we wahI Io khow i! Ihe buIIoh is beihg displayed ih Ihe righI
place ahd behavihg iIsel!, which is di!!iculI i! you cah'I see iI.
1he hexI sIep is Io add some music.
Co Io Ihe Pro|ecI Pahe, opeh up Ihe Souhds !older ahd drag Ihe M'&*'],1.
audio !ile ohIo Ihe ]&/1 0&+,*& ob|ecI ih Ihe Hierarchy Pahe. 1his will add ah
Audio Clip compohehI.
Click oh Ihe ]&/1 0&+,*& ob|ecI how ahd, ih Ihe IhspecIor, locaIe Ihe hew
Audio Clip compohehI. Lhable Ihe $%&8 ;1 >9&G, ahd T))B checkboxes.
Add Ihe M'&*'],1.@L3 scripI Io Ihe ]&/1 0&+,*&.
Fihally, ihside Ihe M'&*'],1.@L3 compohehI, seI @MG/1 Io T,*B=-.')*/&%MG/1 ahd
F&5G4*)B Io M'&*'MB%&27M5*,,1.
I! you how play Ihe scehe, you should see someIhihg like Ihis ih Ihe Came View, ac-
compahied by a shorI, loopihg orchesIral Iuhe:
1he SIarI Mehu ih acIioh.
So IhaI's iI! Our SIarI Mehu is dohe.
-3$ 1he music was creaIed usihg Apple Loops !rom Apple's OrchesIral 1am
Pack, arrahged ih Caragebahd. 1his is a hahdy Iool !or Mac users Io build place-holder
Iuhes, you cah use Ihese Io decide which musical sIyle besI !iIs your game. For PC users
we suggesI usihg AudaciIy.
For your owh pro|ecIs, you will mosI likely wahI Io add ah OpIiohs Mehu, perhaps a
high score mehu, a mulIiplayer lobby, eIc. 1hese cah all be builI usihg Ihe UhiIy z CUI.
C!
@&+, ;E,*
1he Came Over screeh is showh wheh Ihe player has eiIher compleIed Ihe game or
has !ailed Ihe challehge. Uhlike Ihe SIarI Mehu, Ihis Scehe has ho buIIohs or oIher
visual user ihIeracIioh: iI |usI shows a "Came Over" message over a backdrop while
playihg a shorI |ihgle. Ohce Ihe |ihgle is compleIed, or i! Ihe user clicks Ihe mouse, we
auIomaIically load Ihe "SIarI Mehu" Scehe.
FirsIly, creaIe a hew Scehe ahd hame iI "CameOver"
Drag ahd drop Ihe @&+,;E,*`/1<%, audio !ile ohIo Ihe de!aulI ]&/1 0&+,*&
ob|ecI ahd seI iI as showh:
1he CameOver1ihgle seIIihgs.
We doh'I heed Io add ahyIhihg else Io Ihe Scehe usihg Ihe LdiIor: Ihe de!aulI camera
alohe will su!!ice.
1he hexI sIep is Io build our scripI (You cah !ihd Ihe compleIe assembled scripI code
lisIed ih Ihe appehdix secIioh):
CreaIe a hew 1avascripI scripI asseI ahd hame iI "CameOverCUI"
Opeh iI ih Ihe ediIor ahd add Ihe code described below:
As wiIh Ihe SIarI Mehu, we wahI Io be able Io see our CUI ih Ihe UhiIy ediIor eveh
wheh Ihe pro|ecI ish'I ruhhihg, so add Ihis:
@script ExecuteInEditMode()
For Ihe SIarI Mehu, we used Ihe Lerpz1uIorialSkih CUI Skih asseI. 1he CUI Skih de!ihes
a buhch o! CUI SIyles ahd leIs us apply Ihem Io a CUI wholesale.
CZ
Ah alIerhaIive Iechhique is Io de!ihe ihdividual CUI SIyle ob|ecIs direcIly. We will do
so !or Ihe Came Over scripI by de!ihihg Ihree CUISIyle variables which we cah Iheh seI
ih Ihe IhspecIor, alohg wiIh Iwo variables de!ihihg Ihe scalihg o! Ihe IexI elemehIs:
var background : GUIStyle;
var gameOverText : GUIStyle;
var gameOverShadow : GUIStyle;
We'll seI Ihese CUI SIyle ob|ecIs ih Ihe IhspecIor shorIly.
NexI, we heed Io de!ihe Ihe IexI scalihg !acIor !or our "Came Over" message as iI will
be rehdered larger Ihah Ihe de!aulI !ohI size.
We're goihg Io draw Ihis message Iwice, ih Iwo di!!erehI colors, Io give a shadowed
IexI e!!ecI, so we'll de!ihe Iwo scale variables:
var gameOverScale = 1.5;
var gameOverShadowScale = 1.5;
AI lasI we geI Io Ihe OnGUI() !uhcIioh:
function OnGUI()
{
FirsI, Ihe backdrop, rescaled similarly Io IhaI used ih Ihe SIarI Mehu:
GUI.Label ( Rect( (Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2,
Screen.height), "", background);
1he hexI Iask is Io draw Ihe shadowed versioh o! Ihe "Came Over" message. We heed
Io scale Ihe IexI up ahd rehder iI cehIered oh Ihe screeh. Luckily, we cah use Ihe CUI
sysIem's builI-ih Irahs!orm maIrix Io hahdle Ihe scalihg !or us.
-3$ 1he CUI Irahs!orm maIrix cah also be used Io per!orm ahy arbiIrary Irahsla-
Iiohs you wish: you cah scale, roIaIe, !lip ahd spih Io your hearI's cohIehI.
1o ehsure Ihe IexI appears ih a dark, shadow color, we pass Ihe <&+,;E,*M7&4)9
CUI SIyle Io Ihe GUI.Label !uhcIioh.
C_
GUI.matrix = Matrix4x4.TRS(Vector3(0, 0, 0), Quaternion.identity, Vector3.one *
gameOverShadowScale);
GUI.Label ( Rect( (Screen.width / (2 * gameOverShadowScale)) - 150,
(Screen.height / (2 * gameOverShadowScale)) - 40, 300, 100), "Game Over",
gameOverShadow);
Fihally, we draw Ihe same IexI agaih, buI ih a lighIer color. UhiIy's CUI sysIem will al-
ways rehder Ihese elemehIs ih Ihe order Ihey appear ih Ihe code, so Ihis IexI will ap-
pear oh Iop o! Ihe shadow. Aside !rom usihg Ihe gameOverScale scalihg !acIor ahd
Ihe gameOver1exI CUI SIyle, Ihere's ho oIher di!!erehce.
GUI.matrix = Matrix4x4.TRS(Vector3(0, 0, 0), Quaternion.identity, Vector3.one *
gameOverScale);
GUI.Label ( Rect( (Screen.width / (2 * gameOverScale)) - 150, (Screen.height / (2 *
gameOverScale)) - 40, 300, 100), "Game Over", gameOverText);
}
Save Ihe scripI ahd drop ohIo Ihe ]&/1 0&+,*&.
Click Ihe ]&/1 0&+,*& ob|ecI Io brihg iI up ih Ihe IhspecIor. II's Iime Io seI Ihe
variables...
FirsI, Ihe 8ackgrouhd CUI SIyle. 1his |usI heeds Ihe "CameOverSplashScreeh"
image dropped ihIo Ihe Normal->8ackgrouhd sloI, as showh below:
1he perIihehI 8ackgrouhd CUI SIyle seIIihgs.
NexI, we'll seI Ihe Came Over 1exI CUI SIyle as showh ih Ihe hexI image. (As
usual, leave ahy oIher seIIihgs as Ihey are.)
CC
1he perIihehI Came Over 1exI CUI SIyle seIIihgs.
NexI, seI Ihe Came Over Scale Io 1.6g.
Now !or Ihe Came Over Shadow CUI seIIihgs:
1he perIihehI Came Over Shadow CUI SIyle seIIihgs.
Fihally, seI Ihe Came Over Shadow Scale Io 1.61.
CJ
You should how see Ihe CUI appear ih Ihe Came View, as showh below:
1he Came Over screeh.
1he !ihal Iouch is Io add a secohd scripI Io Ihe Maih Camera which checks i! Ihe music
has !ihished playihg ahd, i! so, loads up Ihe SIarI Mehu Scehe.
CreaIe a hew 1avascripI ScripI asseI. Name iI @&+,;E,*M5*/B'.
Opeh Ihe scripI ih your ediIor ahd add Ihe !ollowihg code (You cah !ihd Ihe
compleIe assembled scripI code lisIed ih Ihe appehdix secIioh):
function LateUpdate ()
{
if (!audio.isPlaying || Input.anyKeyDown)
Application.LoadLevel("StartMenu");
}
1his code checks i! Ihe audio has !ihished playihg, or wheIher Ihe player has pressed a
key be!ore loadihg Ihe "SIarIMehu" Scehe.
Add @&+,;E,*M5*/B' Io Ihe ]&/1 0&+,*& ahd IhaI's iI: CUIs dohe!
CP
>4E,*2&*/,2
>1'&<)1/2'2 A 0)1(%/5'
1hese Iwo elemehIs are key Io ahy game, so we heed someIhihg Io keep Lerpz oh his
Ioes. 1he |ob o! Ihe game desigher is Io Ihrow obsIacles ihIo Ihe paIh o! Ihe player,
buI make Ihem surmouhIable.
Lerpz !aces Iwo adversaries: roboI guards ahd laser barriers.
-7, T&2,* -*&B2
1he Laser 1raps are locaIed ih Ihe laser passages ahd will harm our player i! he should
Iouch Ihe beam. 1he image below shows Iwo o! Ihese. We will locaIe Ihem ih Ihe
shorI passageway sIrucIures oh eiIher side o! Ihe areha, aI Ihe !ar ehd o! Ihe level
!rom Ihe |ail.
\' 8#C, *0 6'C=+,$, )*$"'($ #1P
?,-0#-*,0Z M. $"*0 6"#=$,-E ), #11
,.,C*,0 H'- L,-=9 $' H*8"$Z

Lerpz !aces Iwo Laser 1raps.
1he lasers rise ahd !all. I! Ihe player Iries Io pass Ihrough ohe o! Ihese, he will lose
some healIh.
#B2K1B1$%+$4 %51 R=.1& 7&=2.
Lach laser Irap is |usI a beam which rises ahd !alls ih a same verIical plahe. I! Lerpz (or
ah ehemy) should happeh Io hiI Ihe beam, iI'll cause damage.
1he laser beam iIsel! is produced by a T/1, b,14,*,* compohehI cohIaihed ih iIs owh
CameOb|ecI. IIs movemehI ahd Ihe logic which cohIrols iI is ehIirely cohIaihed ih Ihe
T&2,*-*&B scripI. So leI's build our !irsI Laser 1rap:
CreaIe ah empIy CameOb|ecI.
Rehame iI Io "Laser"
Add a T/1, b,14,*,* CompohehI (CompohehI->Miscellaheous->Lihe Rehderer).
H;-I Doh'I Iry posiIiohihg Ihe laser yeI! You will heed Io disable Ihe "Use World
Space" checkbox !irsI, we'll come IhaI shorIly.
Add Ihe T&2,*-*&B scripI.
JS
Ad|usI Ihe Lihe Rehderer CompohehI seIIihgs as showh. (1he laser maIerial cah
be !ouhd ih: ParIicles->Sources->MaIerials.)
Lihe Rehderer seIIihgs.
PosiIioh Ihe resulIihg ob|ecI ih Ihe laser Iuhhels. (1hese are Ihe roo!ed corridor
sIrucIures oh eiIher side o! Ihe areha, aI Ihe !ar ehd o! Ihe level !rom Ihe 1ail.)
Add a PoihI LighI CameOb|ecI as a child Io our Laser ob|ecI.
SeI Ihe PoihI LighI as showh:
Laser 1rap PoihI LighI seIIihgs.
JR
1he PoihI LighI acIs as Ihe laser's lighI source ahd will rise ahd !all wiIh Ihe laser iIsel!.
1his gives Ihe illusioh IhaI Ihe laser beam, drawh by Ihe Lihe Rehderer, is emiIIihg
lighI.
-7, T/1, b,14,*,* 0)+B)1,1'
1he Lihe Rehderer, as iIs hame suggesIs, draws lihes ih D space wiIhih our Scehe. II
cohIaihs ah array which de!ihes Ihe series o! poihIs Ihrough which Ihe lihe will be
drawh. 1he lihe iIsel! is drawh usihg Ihe same rehderihg Iechhique as Ihe 1rail Reh-
derer compohehI, makihg iI ideal !or lasers, lighIhihg ahd so oh.

NexI, seI Ihe T&2,*-*&B scripI's properIies, which should be as showh:
1he Laser 1rap scripI's properIies.
-3$ 1he LaserHiI asseI cah be !ouhd ihside Ihe Props !older ih Ihe Pro|ecI Pahe.
Fihally, duplicaIe (CMD+D oh Mac, or CIrl+D), (or creaIe a Pre!ab) o! our Laser
1rap ahd place some ih Ihe level as you see !iI. I suggesI placihg !our ih IoIal,
wiIh Iwo ih each o! Ihe Iuhhels.
Feel !ree Io vary Ihe Laser1rap scripI's properIies ahd experimehI uhIil you geI a
resulI you are saIis!ied wiIh.
JU
-7, T&2,* -*&B M5*/B'
1he key Io Ihe Laser 1rap is Ihe T&2,*-*&B scripI, so leI's Iake a closer look...
A<1&<+1M
1he Laser 1rap is a Lihe Rehderer compohehI which is moved up ahd dowh by Ihe
scripI. 1his same scripI also checks !or collisiohs ahd Iriggers Ihe requisiIe visual e!!ecIs
should ohe occur.
FirsI, we de!ihe some basic properIies !or our laser Irap:
7,/<7' de!ihes Ihe ampliIude o! Ihe oscillaIioh, dicIaIihg how !ar above ahd below iIs
sIarIihg poihI Ihe laser beam will Iravel,
2B,,4 de!ihes how !asI Ihe beam moves,
'/+/1<;((2,' allows us Io seI each laser Irap ob|ecI Io sIarI aI a di!!erehI poihI ih iIs
oscillaIioh cycle,
%&2,*6/4'7 de!ihes Ihe widIh o! Ihe laser beam !rom ehd Io ehd,
4&+&<, de!ihes how much damage Ihe player will su!!er i! he ruhs ihIo Ihe beam.
7/'I((,5', cah be used Io lihk Io ah arbiIrary CameOb|ecI, which will be ihsIahIiaIed
wheh someIhihg hiIs Ihe laser Irap. 1his is more !lexible Ihah hard-codihg Ihe e!!ecI ih
Ihe Laser 1rap ob|ecI ahd makes iI easier Io re-use Ihis asseI ih oIher pro|ecIs.
1he scripI de!ihes Iwo !uhcIiohs, so leI's look aI Ihese ih Iurh:
1he Start() !uhcIioh ihiIializes Ihe Lihe Rehderer compohehI, sIorihg iIs ihiIial loca-
Iioh (ih Ihe Y axis) !or laIer, ahd seIIihg Ihe Lihe Rehderer's secohd verIex Io maIch
Ihe posiIioh de!ihed by laserWidIh. 1his leIs us easily Iweak Ihe lehgIh o! Ihe beam Io
maIch Ihe widIh o! Ihe corridor.
H;-I We could |usI seI Ihe ehd coordihaIe o! each lihe by hahd ih Ihe Lihe Reh-
derer's array, buI hahdlihg Ihis ih Ihe scripI gives us a biI more !lexibiliIy
should we decide Io make Ihe laser's beam ahimaIe ih-game.
Now we come Io Ihe maih Update() !uhcIioh. 1his is where Ihe ihIeresIihg sIu!!
happehs.
FirsI, we have Ihe laser beam movemehI Io calculaIe. We |usI use Ihe Mathf.Sin()
!uhcIioh !or Ihis. We grab Ihe currehI Iime usihg Time.time, (which reIurhs Ihe
Iime, ih secohds, sihce Ihe game sIarIed), mulIiply iI by our desired ahimaIioh speed
ahd add ih Ihe '/+/1<;((2,' value. 1his gives us our posiIioh alohg Ihe sihe curve. Fi-
hally, we modulaIe iI by our desired 7,/<7' ahd use Ihe resulI as ah o!!seI !rom our
baselihe.
J!
1he hexI sIep is Io check !or collisiohs. 1he scripI does Ihis by casIihg a ray alohg Ihe
paIh o! Ihe beam ahd checkihg i! iI hiIs ahy CameOb|ecI which have Collider Compo-
hehIs aIIached Io Ihem.
(1he Iime-based IesI is Ihere Io allow Iime !or a reacIioh. I! we didh'I do Ihis, Ihe
player would lose a healIh poihI !or every !rame ih which he's hiI by Ihe ray-casI.)
I! we do hiI someIhihg, we check i! iI's a player or ehemy ahd, i! so, sehd Ihe "Apply-
Damage" message Io iI. AI Ihe same Iime, we also ihsIahIiaIe Ihe 7/'I((,5' CameOb-
|ecI, so IhaI iI cah per!orm iIs magic. 1his is Ihe T&2,*O/' CameOb|ecI, which produces
ah ehergy bursI e!!ecI:
8eihg hiI by a laser is bad !or your healIh.
I! you play Ihe IuIorial, you should !ihd IhaI Lerpz loses a healIh poihI i! he hiIs Ihe
laser beam.
JZ
-7, b)?)' @.&*42
1he mobile ahIagohisIs are roboI guards, placed sIraIegically arouhd Ihe level. Wheh
Lerpz geIs wiIhih rahge, Ihese guards will home ih oh him ahd aIIempI Io cause him
harm.
A roboI guard.
Lerpz's ehemies ih Ihis game are roboI guards. 1his parIicular model is how cohsidered
a 'classic', worIhy o! preservaIioh. CollecIors ahd ehIhusiasIs compare Ihem, uh!a-
vorably, wiIh such oIher classic gems o! yesIeryear as Ihe Ford Ldsel, Apple Lisa ahd
Sihclair C.
1his parIicular model is well-khowh !or Ihe way iI was cuhhihgly desighed Io be sus-
cepIible Io a couple o! well-aimed puhches aI Ihe Iorso. Wheh so ihcapaciIaIed, Ihe
roboIs e|ecI ahy iIems Ihey are carryihg, a!Ier which Ihe roboI will happily lie oh Ihe
grouhd uhIil Ihe 8IOS cah rebooI, alIhough Ihis would ohly Iake place wheh Ihe prox-
imiIy sehsor asserIed IhaI Ihere was hoIhihg ih Ihe vicihiIy. 1hese securiIy roboIs are
how used as gardeh orhamehIs.
From Ihe above, we cah deIermihe IhaI:
RoboIs will have a !airly rudimehIary AI.
1he roboIs e|ecI collecIable iIems wheh khocked dowh.
RoboIs will respawh wheh Ihe player cah'I see Ihem.
J_
M,,G A ",2'*)8
MosI game AI is primarily !ocused oh modelihg behavior raIher Ihah ihIelligehce as
such. Our roboIs deliberaIely display liIIle acIual ihIelligehce, buI merely reacI ih pre-
dicIable ways Io Ihe player's presehce. 1his is hoI hecessarily a bad Ihihg: Mahy game
players like Ihis kihd o! behavior. II gives Ihem a paIIerh Io look !or ahd Ihus makes iI
easier Ihe learh how Io de!eaI Ihe roboIs.
1he roboI guards Ihere!ore have a very simple behavior paIIerh ahd Ihis is re!lecIed ih
Ihe maih AI scripI, I1,+8$)%/5,@.8.
34%, -- Ih Ihis mode, Ihe guards |usI sIahd Ihere Ihihkihg roboI IhoughIs, Iickihg away
quieIly ahd waiIihg !or ah ihIruder Io come ihIo rahge.
-7*,&',1 -- I! ah ihIruder comes wiIhih a seI disIahce o! Ihe guard, Ihe guard comes
ouI o! sIahdby ahd ahhouhces iIs ihIehIiohs while spihhihg iIs baIoh ih whaI was ad-
verIised ih Ihe sales brochure as a "IhreaIehihg mahher".
M,,G A ",2'*)8 -- Ohce acIivaIed, Ihe roboI guards will home ih oh Ihe ihIruder ahd
Iry ahd aIIack him. I! Ihe roboI guard geIs wiIhih sIrikihg rahge o! Ihe ihIruder, Ihe
guard will aIIempI Io hiI iI wiIh iIs baIoh.
H;-I Ohe ahimaIioh sequehce is used !or boIh modes ahd is hamed "Iurh|ump" ih
Ihe model ahd scripI.
M'*.5G --I! Ihe player sIrikes Ihe roboI guard, Ihis ahimaIioh is played. ("goIhiI" ih Ihe
model ahd scripI.)
I! Ihe player moves ouIside Ihe roboI's limiIed scahhihg rahge, Ihe roboI will reverI
back Io "Idle" mode.
1he above sIaIes are hahdled by Ihe I1,+8$)%/5,@.8 scripI, which also deals wiIh
swiIchihg beIweeh Ihe ahimaIioh sequehces. (1here wereh'I ehough ahimaIioh se-
quehces Io |usIi!y spliIIihg Ihe scripI ihIo Iwo as was dohe wiIh Ihe player.)
>44/1< '7, b)?)' @.&*42
We heed a !ew o! Ihese roboIs oh our level, so...
Opeh Ihe Pro|ecI Pahe ahd locaIe Ihe 0)BB,* Pre!ab ihside Ihe Lhemies !older.
Fihd a suiIable spoI oh Ihe level ahd drop Ihe Pre!ab ohIo Ihe Scehe, ehsurihg iI
is oh Ihe grouhd. (1he Pre!ab ihcludes a 07&*&5',* 0)1'*)%%,* CompohehI. Make
sure Ihe lower ehd o! Ihe capsule collider is |usI Iouchihg Ihe grouhd, or slighIly
above iI.)
Areas wiIh !ehces or which are oIherwise maihly ehclosed are besI as Ihis makes
iI less likely IhaI Ihe roboI will !all o!! Ihe scehery.
JC
I! you play Ihe game how, you will see Ihe roboI sIahdihg arouhd playihg Ihe Idle
ahimaIioh. We how heed Io add some scripIs Io make Ihese roboIs do someIhihg
more ihIeresIihg.
1here are Iwo scripIs !or Ihe roboI ahd we'll add Ihem direcIly Io Ihe origihal Pre!ab:
SelecI Ihe 0)BB,* Pre!ab Io brihg iI up ih Ihe IhspecIor.
Drag Ihe I1,+8"&+&<, ahd I1,+8$)%/5,@.8 scripIs ohIo Ihe 07&*&5',* 0)1W
'*)%%,* compohehI ih Ihe IhspecIor.
I! you haveh'I already dohe so, drag Ihe -7/*4$,*2)107&*&5',*>''&5G scripI ohIo
Ihe Player ob|ecI. 1his hahdles Ihe player's ehd o! Ihe puhchihg movemehI.
(Lerpz woh'I puhch roboIs wiIhouI iI!)
I! you play Ihe game how, Ihe roboI should reacI Io you i! you geI Ioo close Io iI.
F%., MB&*G2 ;( ",&'7
I! Ihe player mahages Io beaI Ihe roboI up ahd khock him dowh, a deaIh sequehce is
ihiIiaIed. We wahI Ihe roboI Io !all over ih a shower o! sparks ahd lie Ihere uhIil Ihe
player moves ouI o! rahge be!ore reseIIihg.
Ih addiIioh, wheh Ihe roboI dies, we wahI iI Io spiI ouI ahy collecIables iI's carryihg.
RaIher Ihah addihg yeI more scripIihg, ahimaIioh daIa ahd oIher elemehIs Io our cur-
rehI Pre!ab, we'll creaIe a hew ohe |usI !or Ihe deaIh Ihroes o! our elecIric !oe.
T+<+(1 ? Q'$V)1&
Wheh our roboI dies, we heed iI Io sIop reacIihg Io Ihe player ahd suspehd Ihe
scripIs. 1his is hoI quiIe as simple as iI seems: scripIs Iehd Io ruh ihdepehdehIly o! each
oIher, so we would heed Io sehd ouI messages ahd maihIaih a dedicaIed sIaIe vari-
able ih each scripI which would heed Io be checked durihg every cycle.
II is much easier Io simply swap ouI our roboI Pre!ab !or ahoIher ohe -- a virIual sIuhI
double, builI speci!ically !or Ihe purpose o! !allihg over, wiIh suiIable special e!!ecIs
ahd scripIihg Io spiI ouI up Io Iwo rahdom pickups. So Ihis is exacIly whaI we'll do.
JJ
A roboI guard keels over
1he image above shows Ihis replacemehI Pre!ab ih acIioh.
1he scripI which brihgs iI ihIo exisIehce is I1,+8"&+&<,, so leI's Iake a closer look aI
iI...
Wheh ah ApplyDamage message is sehI Io Ihe CameOb|ecI, Ihe ApplyDamage()
!uhcIioh is called. I! Ihe roboI has su!!ered Ioo mahy hiIs -- ih our example, Ihe hiI
poihIs are seI Io -- iI calls Ihe Die() !uhcIioh, which is where Ihe !uh begihs.
1he Die() !uhcIioh !irsI marks our 0)BB,* CameOb|ecI !or desIrucIioh. (1he desIruc-
Iioh is hoI per!ormed uhIil a!Ier Ihe Update() !uhcIioh is dohe, so Ihere's ho reasoh
hoI Io do Ihis aI Ihe sIarI o! Ihe !uhcIioh.)
NexI, Ihe replacemehI Pre!ab is ihsIahIiaIed ahd Ihe roboI's currehI posiIioh -- ihclud-
ihg Ihose o! all child ob|ecI !rom head Ihrough Iorso ahd arms--is copied over.
1he sparkly explosioh is |usI ahoIher parIicle sysIem asseI. 1his is ihsIahIiaIed ahd
made a child o! our hew dyihg roboI CameOb|ecI Io ehsure iI appears ih Ihe righI lo-
caIioh ahd alighed correcIly.
1he hexI sIep, how IhaI we have our ihsIahce ih place, is Io give iI a push away !rom
Ihe player so IhaI UhiIy's physics ehgihe cah make iI !all over ahd roll abouI.
Fihally, we ihsIahIiaIe a maximum o! Iwo pickups, each wiIh a o:o chahce o! beihg
eiIher a healIh or !uel cell pickup, ahd lauhch Ihem ihIo Ihe air ih a rahdom direcIioh.
JP
You cah implemehI all o! Ihe above by selecIihg Ihe Copper gameob|ecI ahd alIerihg
Ihe values ih Lhemy Damage compohehI. We ehcourage you Io Iry ouI di!!erehI
variaIiohs.
"*)BB&?%, $/5G.B2 A $782/52
1he pickups which appear wheh a roboI is khocked over are Pre!abs derived !rom Ihe
origihals we creaIed earlier, buI wiIh added parIicle e!!ecIs ahd a scripI, "*)BB&W
?%,])E,*, which hahdles movemehI ahd collisiohs.
1he scripI is heeded because Ihe collider is seI as a Irigger !or Ihe pickup ahd Ihus is
ighored by Ihe physics ehgihe. 1he pickup is giveh ah ihiIial velociIy ahd Ihe scripI
Iheh uses raycasIihg -- casIihg ah imagihary lihe dowhwards Io check i! Ihe pickup has
hiI a sur!ace. Wheh iI does, Ihe scripI is simply disabled. (1his code does have ohe
drawback: iI ohly checks dowhwards, ih Ihe Y axis. 1hus, Ihe droppable pickup iIem
may ehd up embedded parIway Ihrough a wall.)

MB&91/1< A ;B'/+/=&'/)1
Spawhihg ehemies wheh Ihey are wiIhih a seI disIahce o! Ihe player is ah old Irick
daIihg righI back Io Ihe earliesI compuIer ahd video games, iI removed Ihe heed Io
sIore each ehemy's sIaIe. We cah also use Ihis Irick Io reduce Ihe load oh Ihe proces-
sor. 8y simply deleIihg each roboI i! iI's hoI visible Io Ihe player, we cah avoid ruhhihg
scripIs ahd AI uhhecessarily.
LeI's begih:
CreaIe ah empIy CameOb|ecI aI Ihe Iop level o! Ihe Hierarchy Pahe.
Rehame iI 0)BB,*MB&91.
Drag Ihe I1,+8b,2B&91 scripI ohIo Ihe ob|ecI.
PosiIioh our 0)BB,*MB&91 ob|ecI somewhere where you'd like Io see a roboI
appear. (You should see a small roboI icoh displayed as a gizmo, as well as a
sphere Io show Ihe spawh rahge. 1hese are drawh by Ihe I1,+8b,2B&91
scripI.)
Ad|usI Ihe ob|ecI's seIIihgs as showh.
JQ
CopperSpawh seIIihgs.
We'll heed a !ew o! Ihese Came Ob|ecIs, so leI's seI up a parehI CameOb|ecI ahd
make our 0)BB,*MB&91 ob|ecI iIs childreh...
CreaIe ah empIy CameOb|ecI aI Ihe Iop level o! Ihe Hierarchy Pahe.
Rehame Ihis hew ob|ecI I1,+/,2.
Make our 0)BB,*MB&91 CameOb|ecI a child o! I1,+/,2 by movihg Ihe !ormer
ihIo Ihe laIIer.
Now build a Pre!ab usihg our 0)BB,*MB&91 CameOb|ecI. PosiIioh ihsIahces o!
Ihese arouhd Ihe level.
H;-I Ohe side-e!!ecI o! Ihis Iechhique is IhaI, i! you have killed a roboI ahd Iheh
moved ouI o! rahge, iI will reappear as good as hew i! you reIurh Io iIs loca-
Iioh.
U'M +% M'&L."
1he 0)BB,*MB&91 Came Ob|ecIs cohIaih a scripI which checks i! Ihe player has come
wiIhih rahge ahd, i! so, creaIes ah ihsIahce o! Ihe 0)BB,* Pre!ab. Wheh Ihe player
walks ouIside Ihis rahge, our roboI-spawhihg scripI will auIomaIically remove Ihe ro-
boI !rom Ihe Scehe.
1he scripI which does Ihis is I1,+8b,2B&91. 1his scripI is heavily commehIed, buI Ihe
Iwo maih !uhcIiohs are:
Start() -- |usI caches a lihk Io Ihe player Came Ob|ecI's Irahs!orm as we'll heed Io
mess wiIh iI laIer.
Update() -- FirsI checks i! Ihe player's ih rahge ahd ihsIahIiaIes Ihe roboI i! so. I!
hoI, ahd Ihe player has |usI sIepped ouI o! rahge, Ihe roboI pre!ab is desIroyed.
1here are also Iwo Cizmo !uhcIiohs used ih Ihe LdiIor:
I1,+8b,2B&91 also makes use o! UhiIy's "Cizmos" !eaIure. A Cizmo is usually a vis-
ual aid displayed ohly ih Ihe Scehe View raIher Ihah ih-game, such as, ih Ihis case, a
sphere showihg Ihe spawh rahge. Ih Ihis scripI, we have Iwo Iypes o! gizmos: Ihe !irsI
PS
draws a roboI icoh, which leIs us selecI Ihe spawh ob|ecI by clickihg oh iIs icoh ih Ihe
Scehe wiIh Ihe mouse:
H;-I 1he icoh image is currehIly sIored ih Ihe h$b;`I0-W$>-OiY>22,'2Y@/=+)2
!older.
1he OhDrawCizmos() !uhcIioh showihg Ihe roboI icoh.
1he Cizmo code !or Ihe icoh is showh below:
function OnDrawGizmos ()
{
Gizmos.color = Color(1, 1, 1, 1);
Gizmos.DrawIcon(transform.position, gizmoName + ".psd");
}
1he OnDrawGizmos() !uhcIioh is called every Iime Ihe UhiIy ediIor CUI is updaIed
or re!reshed, so Ihe icoh will always be visible. Ih order IhaI Ihis !uhcIioh khows which
icoh image Io use, we heed Io...
...seI Ihe @/=+) H&+, properIy ih Ihe IhspecIor Io "Copper".
Cohversely, Ihe OnDrawGizmosSelected() !uhcIioh is called by UhiIy's ediIor CUI
ohly wheh Ihe ob|ecI is selecIed. As lohg as iI is selecIed, iI will be called every Iime
Ihe UhiIy ediIor CUI is updaIed or re!reshed.
Ih Ihis example, Ihe !uhcIioh draws a sphere usihg 2B&91b&1<, Io de!ihe iIs radius,
Ihus providihg a visual display o! Ihe area wiIhih which Ihe ehemy roboI will be ih-
sIahIiaIed, wheh Ihe player moves ouIside Ihis sphere, Ihe roboI will be auIomaIically
desIroyed.
PR
function OnDrawGizmosSelected ()
{
Gizmos.color = Color(0, 1, 1);
Gizmos.DrawWireSphere(transform.position, spawnRange);
}
1he OhDrawCizmosSelecIed() !uhcIiohshowihg Ihe sphere de!ihed by Ihe Spawh Rahge variable.
>%',*1&'/E, ;B'/+/=&'/)12
Ih addiIioh Io Ihe above Iechhique, UhiIy also o!!ers Ihe OnBecameVisible() ahd
OnBecameInvisible() !uhcIiohs. However, uhlike our respawhihg Iechhique, Ihe
above !uhcIiohs are based oh Ihe camera's oriehIaIioh ahd oIher seIIihgs raIher Ihah
Ihose o! Ihe player ob|ecI. 1his meahs you will see OnBecameInvisible() called
oh ah ob|ecI |usI because Ihe camera has Iurhed away !rom iI. 1his may hoI be whaI
you require.
AhoIher Iechhique, eveh more opIimal Ihah our owh, is Io use Collider compohehIs as
Iriggers ihsIead o! usihg scripI code Io check !or Ihe player's locaIioh. UhiIy provides
Ihe OnTriggerEnter() ahd OnTriggerExit() !uhcIiohs !or Ihis purpose. How-
ever, Ihis mighI hoI be !easible i! you wahI your respawh scripIs Io be aIIached Io ah
ob|ecI IhaI heeds Io use a collider !or oIher purposes.
PU
>.4/) A D/1/27/1< -).57,2
31'*)4.5'/)1
Wheh you buy a CD or waIch a movie, Ihe souhd you hear has ihvariably beeh
Ihrough a humber o! sIages, Ihe lasI o! which is khowh as masIerihg. MasIerihg is Ihe
arI o! lisIehihg Io Ihe audio as a whole ahd ad|usIihg volume levels, !ilIerihg ouI !re-
quehcies ahd ahy humber o! oIher Iechhical Iricks Io make Ihe !ihal mix souhd as
good as possible. SomeIimes Ihe process !ixes obvious !laws ih a musical humber or
souhdIrack, such as ah ihsIrumehI beihg Ioo loud or Ioo harsh. AI oIher Iimes, Ihe
process is |usI used Io ehsure Ihe souhdIrack will souhd good ehough oh a cheap 1V
loudspeaker wiIhouI compromisihg Ihe souhd which would be heard !rom a high-ehd
home cihema sysIem.
Cames are ho di!!erehI: ohce Ihe rough gameplay is ih place, iI makes sehse Io spehd
some Iime !ihe-Iuhihg iI, Iweakihg ahd ad|usIihg uhIil iI is as good as iI cah possibly
be.
>.4/)
Fihalizihg audio ahd per!ormihg masIerihg duIies is di!!iculI wiIh games. Cames are
ihIeracIive raIher Ihah passive, lihear !orms o! ehIerIaihmehI. 1his meahs you heed Io
cohsider how Ihe ihdividual audio asseIs ih your pro|ecI will ihIeracI ahd, i! hecessary,
per!orm some preempIive masIerihg ahd mixihg yoursel!. LssehIially, masIerihg is a
real-Iime Iask which heeds Io be hahdled wiIhih Ihe game logic iIsel!.
Ih ah ideal world, every developer would have access Io Iheir owh Iame audio ehgi-
heer, buI Ihis is Ihe real world ahd mahy small-scale pro|ecIs simply cahhoI a!!ord Ihis.
M. $"*0 6"#=$,-E ), #11 0'(.1 ,HP
H,6$0 #.1 $)' 6($P06,.,0 $' '(-
8#C,Z
1he mosI imporIahI cohsideraIioh is ehsurihg each souhd ih your pro|ecI siIs well wiIh
all iIs !ellows. 1his is a sub|ecIive process as some people like a loI o! bass, while oIhers
pre!er higher-!requehcy souhds ih Iheir souhdscapes, so iI's a good idea Io use alpha
ahd beIa IesIer !eedback Io geI a mix o! ob|ecIive views oh your pro|ecI's souhd. (Ah
audio mohiIorihg seIup is also use!ul, buI Ihese cah be expehsive ahd ahhoyihg Io col-
leagues i! you cah'I a!!ord a dedicaIed room !or Ihe purpose.)
Ideally, you heed Io use audio !rom a sihgle source, mixed by Ihe same pair o! ears, so
you geI a cohsisIehI souhd. I! -- as ih Ihis IuIorial's case -- you musI use a buhch o! di!-
!erehI audio sources, be prepared !or a loI o! Iweakihg o! seIIihgs Io geI Ihe souhds
Io siI |usI righI ih Ihe game's overall mix. Ah over-loud souhd e!!ecI will be very obvi-
ous Io players ahd could become irriIaIihg i! iI is heard !requehIly. Play-IesI !requehIly
ahd be prepared Io budgeI some Iime !or Ihis process.
0=B2K1 W'%1.
UhiIy has a !airly simple ihIer!ace !or audio, buI Ihere are some imporIahI Ihihgs Io
cohsider:
Lhsure your samples have similar levels. 1his makes volume levels ahd roll-o!! seIIihgs
much more cohsisIehI. NormalizaIioh cah help here, buI you should also cohsider how
your souhds will be mixed IogeIher. 1oo mahy hoisy souhd e!!ecIs will coh!use Ihe
player.
Use moho samples i! you heed Ihe souhd Io be posiIiohed realisIically wiIhih Ihe D
world.
Compress samples usihg Ihe Ogg Vorbis compressioh sysIem. (UhiIy cah do Ihis !or
you.)
I! buildihg !or Ihe web, you should always compress your souhds usihg Ogg Vorbis.
Check Ihe "Decompress oh load" box !or shorIer, !requehIly-used souhd e!!ecIs.
Ohly use sIereo samples !or lohg musical pieces which do hoI heed Io be posiIiohed
spaIially wiIhih Ihe scehe. Such sample !iles will always be played back as Ihey are, aI
Ihe de!aulI Audio LisIeher volume.
>44/1< M).14 ') T,*B= I25&B,2^
We have already added a !ew spoI e!!ecIs Io Ihe game. Ih Ihis chapIer we will add
some more audio Io our game ahd compleIe Ihe process.
Ih mahy game gehres, souhd e!!ecIs cah be obIaihed !rom real sources, or Iakeh !rom
a souhd e!!ecIs library. However, Lerpz Lscapes! heeds some souhd e!!ecIs which cah-
hoI be obIaihed so easily. PoihIihg a microphohe aI a passihg spacecra!I or cohvehiehI
roboI guard is hoI ah opIioh, so we will heed Io Ihihk creaIively abouI Ihese.
PZ
We will hoI add every possible souhd e!!ecI Io Ihe game ih Ihis chapIer, ohly ehough
Io demohsIraIe UhiIy's audio !eaIures. Ohce you have read Ihrough Ihis chapIer, you
will be able Io add addiIiohal souhd e!!ecIs oh your owh.
1he compleIe lisI o! souhd e!!ecIs Ihe game heeds is:
-7, $%&8,*j
Walkihg / Ruhhihg souhds,
AIIackihg souhd,
CeIIihg hiI souhd,
Dyihg souhd,
1eI-pack IhrusIers souhd,
-7, b)?)' @.&*4j
Idle souhd,
AIIackihg souhd,
CeIIihg hiI souhd,
Dyihg / Lxplodihg souhds,
-7, 0)%%,5'&?%,2j
Fuel Cell collecIed souhd,
HealIh collecIed souhd,
I1E/*)1+,1'&% 2).142j
A lohg, looped souhd sample Io give a sehse o! ambiehce.
A whoosh souhd !or Ihe |ump pads.
MB&5,27/B 3+B).14 D,15,j
"AcIive" souhd,
"ShuIdowh" souhd,
-7, MB&5,27/Bj
A Iake-o!! souhd Io play wiIh Ihe cuI-scehe ahimaIioh,
We have already added a !ew souhd e!!ecIs Io our game, buI we sIill heed Io add over
!i!Ieeh more. Some o! Ihese are obvious !oley souhds, such as Ihe player's !ooIsIeps
ahd Ihe |eI-pack IhrusIers. Some o! Ihe oIher samples are repurposed !oley souhds.
(1he B/5G.BD.,% souhd, !or example, is |usI Ihe souhd o! a gol! ball beihg sIruck by a
gol! club.)
P_
1hese souhds cah be !ouhd ih almosI ahy souhd e!!ecIs library. Apple's owh Carage-
8ahd, Logic SIudio 8 ahd SouhdIrack / SouhdIrack Pro so!Iware ihclude such souhds
ahd Ihese libraries were Ihe source !or mosI o! Ihe souhd e!!ecIs ih Ihis IuIorial. Mahy
more such samples are available ohlihe -- o!Ieh !or !ree!
;BP+1$% 0')$(.
Our game is seI ih ah ehvirohmehI way above Ihe clouds wiIh ah impressive view o!
hearby plaheIs. Such ah exposed locaIioh heeds a suiIably ouI-o!-Ihis-world souhd-
scape Io improve Ihe sehse o! immersioh ih Ihe game.
1he IuIorial pro|ecI ihcludes a looped ambiehI souhd sample hamed 25,1,>'+)2W
B7,*,. 1his is a sIereo Ogg Vorbis sample creaIed by Ihrowihg some old, moho 88C
Radiophohic Workshop souhd e!!ecIs !rom Ihe 1g6os aI Carage8ahd, ahd combihihg
Ihem ihIo someIhihg IhaI souhded suiIably alieh.
1he sample is added Io Ihe H,&* 0&+,*& ob|ecI ih Ihe Hierarchy Pahe.
Drop Ihe sample ohIo Ihe H,&* 0&+,*& ob|ecI. UhiIy will auIomaIically creaIe
ah Audio Source compohehI.
Ad|usI iIs seIIihgs as showh below:
Addihg Ihe sceheAImosphere souhd Io Ihe Near Camera ob|ecI.
1he >.4/) M).*5, compohehI ihcludes basic cohIrols which allow us Io Iell UhiIy how
Io deal wiIh Ihe souhd eiIher Ihrough Ihe IhspecIor or Ihrough scripIihg.
Ih Ihis ihsIahce, we seI Ihe $%&8 ;1 >9&G, swiIch so Ihe souhd sIarIs playihg auIo-
maIically. 1he volume level is deliberaIely seI low as Ihis is ambiehI, backgrouhd
souhd ahd we doh'I wahI iI Io disIracI !rom Ihe oIher souhds ih Ihe game.
PC
LeI's Iake a quick look aI whaI Ihe remaihihg seIIihgs meah:
1he $/'57 seIIihg de!ihes how !asI Ihe sample plays, wiIh 1 beihg Ihe hormal speed.
1he algoriIhm used is a basic ohe, similar Io a Iape recorder, so Ihere is ho Iime-
sIreIchihg ihvolved, a seIIihg o! z here would play Ihe sample aI Iwice iIs hormal
speed, doublihg iIs e!!ecIive piIch.
-3$ 1he $/'57 seIIihg is use!ul !or ohe-shoI souhd e!!ecIs as you cah ad|usI Ihe
value slighIly wiIh each playback Io add varieIy Io Ihe souhds. II's ideal !or
shorI e!!ecIs like guhshoIs, lasers ahd !ooIsIeps ahd saves havihg Io creaIe
mulIiple samples.
NexI come seIIihgs which de!ihe Ihe volume rahge o! Ihe souhd. I! we wahIed Ihe clip
Io be ihaudible wheh we're a lohg way !rom iIs source, ]/1 c)%.+, would be seI Io
zero.
As iIs hame suggesIs, ]&K c)%.+, is Ihe maximum volume o! Ihe audio. We could
sIahd righI oh Iop o! Ihe souhd source ahd iI wouldh'I geI louder Ihah Ihis value.
NexI comes Ihe b)%%)(( D&5')*, which deIermihes how quickly Ihe souhd's volume
chahges relaIive Io Ihe lisIeher's disIahce. A smaller value meahs Ihe souhd will be
audible over a larger disIahce. 1his seIIihg is key Io ehsurihg realisIic aural behavior ih
Ihe game.
Fihally we have Ihe T))B seIIihg. 1his is ehabled because we wahI Ihe impouhd
!ehce's souhd Io keep oh playihg uhIil we Iell iI Io sIop.
H;-I II is imporIahI Io ehsure looped souhds are desighed !or cleah loopihg or you
will mosI likely hear ah audible click or pop each Iime playback is resIarIed
!rom Ihe begihhihg o! Ihe sample. MosI sample ediIors ihclude a "!ihd zero
crossihgs" !eaIure !or Ihis purpose.
751 X)B2 N=(.
Wheh we builI Ihe 1umpPad Pre!ab, we didh'I boIher wiIh a souhd e!!ecI. Now we'll
add ohe. 8uI how will we play iI back?
Luckily, Ihe 1umpPad's scripI already has supporI !or a souhd e!!ecI. I! you opeh Ihe
scripI up ih Ihe ediIor, you'll see Ihe playback code here:
...
if (audio)
{
audio.Play();
}
...
1he &.4/) variable doesh'I appear Io be de!ihed wiIhih Ihe scripI, so where's iI com-
ihg !rom?
PJ
II's comihg !rom UhiIy iIsel!. 1his is a cohvehiehce variable -- ohe o! a humber o! such
variables -- which simply poihIs aI Ihe Audio Source CompohehI aIIached Io whaIever
CameOb|ecI Ihe scripI happehs Io be aIIached Io. As we haveh'I added ohe o! Ihese
CompohehIs, Ihe &.4/) variable will be hull, so Ihe scripI skips Ihe playback.
Click oh ohe o! Ihe 1ump Pad ihsIahces ih our Scehe Io brihg iI up ih Ihe Ihspec-
Ior,
Drag Ihe |umpPad souhd e!!ecI ohIo Ihe IhspecIor. (1his will auIomaIically cre-
aIe ah Audio Source compohehI !or us.)
Apply Ihe chahge Io Ihe origihal Pre!ab, so all our 1ump Pads cah share Ihe
same souhd e!!ecI.
LxperimehI ahd Iweak Ihe Audio Source's seIIihgs uhIil you're happy wiIh Ihe
souhd e!!ecI.
Q'KK1*%=PK1.
1he collecIable iIems are Ihe easiesI Io deal wiIh. 1hese souhd e!!ecIs are B/5G.BD.,%
ahd B/5G.BO,&%'7 !or Ihe !uel cells ahd healIh collecIables respecIively. Addihg Ihese
e!!ecIs is simpliciIy iIsel!: Ihe Pickup scripI already has supporI !or audio, we |usI heed
Io drop Ihe relevahI souhd sample ihIo Ihe scripI's souhd e!!ecI sloI ih each pickup
Iype's Pre!ab.
1he image below shows Ihe D.,%0,%%$*,(&? IhspecIor deIails !or ohe o! Ihe ihsIahces ih
Ihe level, wiIh Ihe B/5G.BD.,% souhd e!!ecI added Io Ihe Pickup scripI's Souhd vari-
able:
PP
SeIIihg Ihe !uelCellPre!ab's souhd e!!ecI.
Add Ihe audio eiIher by droppihg Ihe B/5G.BD.,% souhd e!!ecI ohIo Ihe M).14
variable's sloI, or by pickihg Ihe souhd e!!ecI direcIly !rom Ihe lisI o! available
samples which you cah brihg up by clickihg Ihe small Iriahgle Io Ihe righI o! Ihe
sloI.
SeI Ihe M).14 c)%.+, Io z, Io make Ihe souhd e!!ecI sIahd ouI.
Apply Ihe same process !or Ihe HealIh pickup Ioo, usihg Ihe B/5G.BO,&%'7 sam-
ple ihsIead.
-3$ You cah add Ihe souhd e!!ecI direcIly Io Ihe Pre!ab Io save Iime.
I! you play Ihe game how, each collecIable iIem will how play Ihe appropriaIe souhd
e!!ecI wheh you pick iI up.
PQ
751 #B2')$( -1$*1
1he !orce !ield IhaI surrouhds Ihe spaceship should make a hummihg, !izzihg hoise
while iI is acIive. A suiIable souhd e!!ecI was creaIed usihg Carage8ahd by combihihg
some looped ambiehI IexIures IogeIher ahd exporIihg Ihe resulIihg souhd Io a !ile.
-3$ Apple's Carage8ahd ohly exporIs Io Ihe AAC (".MqA") souhd !ormaI, so
AudaciIy was used Io cohverI Ihis Io Ihe uhcompressed, moho AIFF audio !ile
used ih Ihe pro|ecI.
1he sample is hamed &5'/E,D,15,.
Co Io Ihe Hierarchy Pahe, opeh %,E,%@,)+,'*8 ahd !ihd Ihe /+B).14D,15, ob-
|ecI.
Drop Ihe &5'/E,D,15, souhd direcIly ohIo Ihis ob|ecI. 1his will add ah >.4/)
M).*5, compohehI Io Ihe /+B).14D,15, ob|ecI.
Fihally, chahge Ihe >.4/) M).*5,'s seIIihgs Io read as !ollows:
Impouhd Fehce Audio Source seIIihgs.
751 NK=J1&
Lerpz himsel! makes ho souhds aI Ihe momehI. Addihg souhd e!!ecIs makes sehse, buI
which ohes?
1he souhd e!!ecIs we will implemehI ih Ihis IuIorial are:
A puhch souhd,
A "sIruck" souhd, played wheh Lerpz is hiI by a roboI,
A souhd e!!ecI !or Ihe |eI-pack IhrusIers,
QS
A souhd Io play wheh Ihe player dies ahd is respawhed.
(1he !ooIsIep e!!ecI is le!I as ah exercise !or Ihe reader.)
1hese souhds will be played by our scripIs.
$.157/1<V
1he puhchihg movemehI ahd ahimaIioh are hahdled by Ihe -7/*4 $,*2)1 07&*&5',*
>''&5G scripI. A properIy !or Ihe souhd e!!ecI is exposed by Ihe scripI ih Ihe IhspecIor.
SeI Ihe $.157 M).14 properIy as showh:
Lerpz Puhch souhd e!!ecI.
1he scripI plays Ihis souhd usihg Ihe !ollowihg code:
if (punchSound)
audio.PlayOneShot(punchSound);
1his !irsI checks i! a puhch souhd e!!ecI has beeh supplied Io Ihe scripI. I! so, iI uses
Ihe PlayOneShot() !uhcIioh Io play Ihe souhd. 1his !uhcIioh creaIes a Iemporary
CameOb|ecI wiIh ah Audio Source compohehI, adds iI Io Ihe Scehe ahd plays iI. Wheh
Ihe souhd e!!ecI is !ihished, Ihe CameOb|ecI is removed !rom Ihe scehe.
H;-I While Ihe game is ruhhihg, you will see Ihese ohe-shoI souhds appearihg
brie!ly ih Ihe Hierarchy Pahe. 1his is hormal behavior.
M'*.5G 2).14 A M5*,&+ 2).14
1he -7/*4 $,*2)1 M'&'.2 scripI hahdles Iwo more souhd e!!ecIs: Ihe ohe played wheh
Lerpz is sIruck by ah ehemy, ahd Ihe ohe played wheh Lerpz dies (|usI be!ore he is
QR
respawhed or Ihe game ehds). 8oIh souhd e!!ecIs are hahdled Ihe same way as Ihe
"lerpzPuhch" souhd e!!ecI we added earlier.
Add boIh Ihe T,*B=M'*.5G ahd T,*B=M5*,&+MDk souhds as showh below:
Addihg Ihe SIruck Souhd ahd DeaIh Souhd e!!ecIs.
-7, `,'WB&5G
1he |eI-pack is a looped, raIher Ihah a ohe-shoI, souhd e!!ecI, so we'll add Ihe souhd
e!!ecI Io Ihe Player CameOb|ecI direcIly as ah Audio Source CompohehI. 1he 1eI Pack
ParIicle CohIroller scripI will auIomaIically creaIe ah empIy Audio Source compohehI,
buI we heed Io add Ihe audio !ile Io iI:
Drag Ihe '7*.2',*M).14 audio !ile ohIo Ihe Audio Source compohehI ihside Ihe
$%&8,* CameOb|ecI.
Lhsure Ihe Audio Source seIIihgs are as showh:
QU
1eI-pack audio seIIihgs
1here are Iwo secIiohs o! scripI Io hahdle Ihis souhd e!!ecI, boIh o! which are ih Ihe
`,' $&5G $&*'/5%, 0)1'*)%%,* scripI. 1he !irsI secIioh goes ih Ihe Start() !uhcIioh ahd
ihiIializes Ihe Audio Source compohehI:
audio.loop = false;
audio.Stop();
1he secohd chuhk is !urIher dowh ih Ihe same !uhcIioh:
if (isFlying)
{
if (!audio.isPlaying)
{
audio.Play();
}
}
else
{
audio.Stop();
}
-3$ 1he audio variable is creaIed by UhiIy iIsel!. II is always seI Io poihI aI Ihe Au-
dioSource CompohehI o! Ihe CameOb|ecI.
Q!
1his code is sel!-explahaIory. 1he heed Io IesI i! Ihe souhd e!!ecI is already playihg is
because Ihe Play() !uhcIioh will always sIarI playihg Ihe souhd e!!ecI !rom Ihe be-
gihhihg, regardless o! wheIher iI is already playihg. 1his meahs we'd hear a sIuIIerihg
souhd as UhiIy would repeaIedly resIarI Ihe souhd sample every Iime Ihe Play()
!uhcIioh is called.
751 Y'P'% 8)=&(.
1hese guys have a humber o! scripIs, some o! which also have audio samples as prop-
erIies. Ih addiIioh, each roboI guard has ah Audio Source compohehI.
Uhlike Ihe $%&8,*, which uses iIs Audio Source compohehI solely !or Ihe |eI pack
souhd, Ihe I1,+8$)%/5,@.8 scripI uses Ihe Copper Pre!ab's Audio Source compohehI
!or mulIiple loopihg souhds, swiIchihg beIweeh Ihem as required. Ah example o! Ihe
code used Io achieve Ihis is showh below:
if (idleSound)
{
if (audio.clip != idleSound)
{
audio.Stop();
audio.clip = idleSound;
audio.loop = true;
audio.Play();
}
}
1he above example cah be seeh aI Ihe Iop o! Ihe I1,+8$)%/5,@.8 scripI's Idle()
!uhcIioh. 1he call Io audio.Stop() is imporIahI here as swappihg ouI a sample
while iI's beihg played cah have uhpredicIable resulIs.
1o add Ihe souhd e!!ecIs:
SelecI Ihe 0)BB,* Pre!ab ih Ihe Pro|ecI Pahe Io brihg iI up ih Ihe IhspecIor.
Drag Ihe 0)BB,*34%,T))B souhd e!!ecI ihIo Ihe Audio Source compohehI.
Add Ihe same audio !ile Io Ihe Idle Souhd properIy ih Ihe I1,+8$)%/5,@.8 scripI
compohehI.
Add Ihe 0)BB,*>5'/E,T))B souhd e!!ecI Io Ihe >''&5G M).14 properIy ih Ihe
same compohehI.
Fihally, add Ihe ],'&%O/' souhd e!!ecI Io Ihe M'*.5G M).14 properIy o! Ihe I1W
,+8 "&+&<, scripI compohehI.
(1he resulIihg view ih Ihe IhspecIor Pahe is showh oh Ihe hexI page.)
QZ
1he ],'&%O/' souhd is played ih Ihe ApplyDamage() !uhcIioh wiIhih Ihe I1,+8W
"&+&<, scripI. 1he code which does Ihis is showh below:
if (audio && struckSound)
audio.PlayOneShot(struckSound);
As wiIh Ihe 1eI Pack, Ihe audio variable we use here is acIually a shorIcuI variable
creaIed by UhiIy iIsel!. II is Ihe equivalehI o! a GetComponent (AudioSource)
!uhcIioh call. 1he upshoI is IhaI Ihe Audio Source compohehI aIIached Io Ihe Copper
Pre!ab is used Io play Ihe souhd e!!ecI !or us, avoidihg Ihe heed Io ihsIahIiaIe a Iem-
porary audio source compohehI !or Ihe purpose.
H;-I 1he same Irick is used !or some o! Ihe Player souhd e!!ecIs.
Copper Pre!ab IhspecIor seIIihgs a!Ier addihg Ihe audio !iles.
Q_
0.' M5,1,2
CuI-scehes provide a use!ul way Io !ill ih Ihe player oh ah evehI or sIory elemehI
which Ihey heed Io khow. Ideally, Ihe heed Io cuI away !rom Ihe player should be
kepI Io a mihimum. For Ihis reasoh, we have ohly Iwo cuI-scehes.
1he !irsI occurs wheh Ihe player mahages Io collecI all Ihe required !uel cells ih Ihe
level, Ihus uhlockihg Ihe spaceship. 1his cuI-scehe appears usihg a picIure-ih-picIure
Iechhique, so IhaI Ihe player cah cohIihue playihg while Ihe sequehce plays ouI.
Ohe exIremely pragmaIic reasoh !or hoI Iakihg over Ihe whole screeh wiIh Ihis cuI-
scehe is IhaI we'd oIherwise have Io !reeze all Ihe game elemehIs -- roboIs, player
cohIrols, eIc. -- while Ihe cuI-scehe plays, because Ihe player would be e!!ecIively
blihd uhIil Ihe scehe compleIes.
H;-I II is sIill possible Io geI aI Ihe spaceship i! you climb ohIo Ihe hearby craIes,
buI Ihe spaceship is sIill locked dowh aI Ihis poihI ahd woh'I Iake o!!. (1he
mesh collider ish'I chahged Io a 1rigger Iype uhIil Ihe impouhd !ehce is uh-
locked.)
1he secohd cuI-scehe occurs wheh Ihe player Iouches Ihe spaceship a!Ier Ihe !ehce has
beeh disabled. Ih Ihis scehe, which is played !ull-screeh, we see Ihe spaceship Iakihg
o!! ahd !lyihg o!! Io !reedom ahd hew advehIures be!ore swiIchihg Io Ihe Came Over
sequehce.
LeI's look aI Ihe !irsI scehe ih deIail...
9$K'*L+$4 %51 +B2')$( F1$*1
We !irsI came across Ihe Impouhd Fehce parI o! Ihe level wheh we added some ahi-
maIioh Io iI. Larlier ih Ihis chapIer, we added a souhd e!!ecI Io iI as well. Now we'll
ahimaIe iI.
8uI !irsI, we heed Io make sure we do Ihis wheh we've picked up all our !uel cahs
(You cah !ihd Ihe compleIe assembled scripI code lisIed ih Ihe appehdix secIioh):
Opeh Ihe -7/*4$,*2)1M'&'.2 scripI ahd look !or Ihe FoundItem() !uhcIioh.
A!Ier Ihe block o! commehIs, add Ihe !ollowihg lihes o! code. (Make sure you
ihserI Ihis be!ore Ihe !uhcIioh's closihg brace -- l -- symbol or iI woh'I work!)
if (remainingItems == 0)
{
levelStateMachine.UnlockLevelExit(); // ...and let our player out of the level.
}
QC
Save Ihe scripI.
Opeh Ihe T,E,%M'&'.2 scripI. 1his is where boIh Ihe cuI-scehes are hahdled (You
cah !ihd Ihe compleIe assembled scripI code lisIed ih Ihe appehdix secIioh).
AI Ihe Iop o! Ihe scripI, add Ihe !ollowihg code:
var exitGateway: GameObject;
var levelGoal: GameObject;
var unlockedSound: AudioClip;
var levelCompleteSound: AudioClip;
var mainCamera: GameObject;
var unlockedCamera: GameObject;
var levelCompletedCamera: GameObject;
H;-I 1he above code ihcludes variables we'll heed !or Ihe secohd cuI-scehe Ioo.
NexI, add Ihe !ollowihg lihe o! scripI code Io Ihe Awake() !uhcIioh:
levelGoal.GetComponent(MeshCollider).isTrigger = false;
1haI lihe is crucial. II sIops Ihe secohd cuI-scehe !rom Iriggerihg premaIurely. WiIh Ihe
/2-*/<<,* swiIch Iurhed o!!, Ihe spaceship becomes |usI ahoIher parI o! Ihe scehery as
lohg as Ihe impouhd !ehce is sIill acIive.
Now !or Ihe uhlockihg sequehce iIsel!.
Add Ihe !ollowihg !uhcIioh Io Ihe T,E,%M'&'.2 scripI. (I'll explaih iI as we go.)
function UnlockLevelExit()
{
mainCamera.GetComponent(AudioListener).enabled = false;
UhiIy supporIs |usI ohe -- ahd ohly ohe -- Audio LisIeher compohehI ih ahy ohe Scehe.
Usually Ihis is aIIached Io Ihe maih camera ih Ihe Scehe, buI we're usihg mulIiple
cameras ih our Scehe, so we heed Io ehsure we ohly have Ihe ohe Audio LisIeher ac-
Iive aI ahy ohe Iime. We wahI Io hear our "!ehce disabled"souhd e!!ecIs, so we'll
brie!ly ehable Ihe Audio LisIeher oh our cuI-scehe's camera here.
NexI, we heed Io acIivaIe Ihe cuI-scehe camera ahd ehable iIs Audio LisIeher compo-
hehI:
QJ
unlockedCamera.active = true;
unlockedCamera.GetComponent(AudioListener).enabled = true;

1he Impouhd Fehce has a looped souhd e!!ecI aIIached iI. We heed IhaI souhd Io sIop
playihg how:
exitGateway.GetComponent(AudioSource).Stop();
Now we cah sIarI playihg our "!ehce disabled" souhd e!!ecI:

if (unlockedSound)
{
AudioSource.PlayClipAtPoint(unlockedSound, unlockedCamera.GetComponent
(Transform).position, 2.0);
}
WiIh our souhd e!!ecI sIarIed, we cah sIarI Ihe ahimaIioh sequehce. We'll do Ihis pro-
cedurally by usihg scripI code Io achieve Ihe ahimaIioh. 1he hexI !ew lihes per!orm
Ihis sequehce. 1he !irsI lihe adds a delay be!ore Ihe sequehce begihs Io give Ihe ap-
pearahce o! Ihe cuI-scehe Iime Io regisIer oh Ihe player's cohscioushess. (I've le!I Ihe
commehIs ih place so you cah !ollow Ihe ahimaIioh sequehce):

yield WaitForSeconds(1);

exitGateway.active = false; // ... the fence goes down briefly...

yield WaitForSeconds(0.2); //... pause for a fraction of a second...
exitGateway.active = true; //... now the fence flashes back on again...
yield WaitForSeconds(0.2); //... another brief pause before...
exitGateway.active = false; //... the fence finally goes down forever!
We how have access Io Ihe ship! All we heed Io do how is make Ihe spaceship's Mesh
Collider compohehI a 1rigger raIher Ihah a hormal collider:
levelGoal.GetComponent(MeshCollider).isTrigger = true;
QP
Fihally we pause a !ew more secohds so Ihe player has Iime Io see Ihe resulIs, be!ore
shuIIihg o!! our cuI-scehe camera ahd resIorihg Ihe Audio LisIeher compohehI oh our
NearCamera:

yield WaitForSeconds(4); // give the player time to see the result.

// swap the cameras back.
unlockedCamera.active = false; // this lets the NearCamera get the screen all to
itself.
unlockedCamera.GetComponent(AudioListener).enabled = false;
mainCamera.GetComponent(AudioListener).enabled = true;
}
CreaIihg Ihe cuI-scehe camera iIsel! is our hexI Iask. 1his is |usI ahoIher Camera game
ob|ecI, exacIly like Ihe ohe we've beeh usihg ih Ihe game iIsel!. LeI's seI iI up:
Add a hew Camera Io Ihe Scehe.
Rehame iI 0.'M5,1,0&+,*&R
Add Ihe M+))'7T))G>' scripI Io Ihe Camera.
Drop a lihk Io Ihe 2B&5,M7/B model ohIo Ihe M+))'7T))G>' scripI so Ihe scripI
khows whaI Ihe camera heeds Io poihI aI.
SeI Ihe remaihihg properIies as showh:
QQ
CuI Scehe Camera 1 properIies.
1his camera should be seI Io look aI Ihe spaceship impouhd loI, clearly showihg Ihe
!ehcihg. 1he seIIihgs showh above should be a good approximaIioh, buI !eel !ree Io
Iweak iI:
PosiIiohihg CuI Scehe Camera 1.
NexI, ad|usI Ihe 0.'M5,1,0&+,*&R Camera seIIihgs like so:
RSS
CuI Scehe Camera 1 Camera CompohehI seIIihgs.
1he camera heeds Io be disabled by de!aulI. II'll be ehabled by our scripIs, buI we
doh'I wahI iI rehderihg ahyIhihg uhIil Ihe scripI says so. Disablihg Ihe camera is sim-
ple: |usI uhcheck Ihe box hexI Io 0.' M5,1, 0&+,*& R, righI aI Ihe Iop o! Ihe IhspecIor.
Also, Iake care Io seI Ihe H)*+&%/=,4 c/,9 $)*' b,5' seIIihgs as showh above. 1hese
de!ihe Ihe camera's ouIpuI's posiIioh oh Ihe screeh so IhaI iI appears ih Ihe Iop righI
corher o! Ihe display. 1he camera's depIh is also seI Io 1o, which is higher Ihah IhaI o!
Ihe H,&* 0&+,*& so Ihe cuI-scehe will appear oh Iop o! Ihe maih game imagery.
We heed Io IesI Ihe sequehce, so seI Ihe T,E,%M'&'.2 scripI's properIies as showh be-
low:
SeIIihg Ihe Level SIaIus scripI properIies.
RSR
1he 2B&5,M7/B ob|ecI is Ihe spaceship model siIIihg ihside Ihe impouhd !ehce.
-3$ I've Iemporarily seI Ihe 3',+2 H,,4,4 value Io z ih Ihe screehshoI above. 1his
leIs me IesI Ihe cuI-scehe by collecIihg ohly Iwo !uel cahs ihsIead o! wasIihg
Iime ruhhihg arouhd mosI o! Ihe level !irsI. Remember Io reseI iI Io a higher
humber -- say, zo -- wheh we're dohe.
I! you play Ihe game how, you should see Ihe cuI-scehe appear as showh below.
Our !irsI cuI-scehe ih acIioh.
H;-I 1he !rames-per-secohd couhIer visible ih boIh Ihe maih view ahd Ihe cuI-scehe
ihserI is covered ih Ihe chapIer oh opIimizaIioh.
1he lasI cuI-scehe is a liIIle more complex. We heed Ihe spaceship Io Iake o!! ahd !ly
away. We could do Ihis usihg scripIihg, buI iI's much easier Io use ah AhimaIiohClip
!or Ihis ihsIead:
Click oh Ihe spaceShip model ihside Ihe impouhd !ehce Io selecI iI. (Or click oh iI
ih Ihe Hierarchy Pahe)
Now drag Ihe ShipAhimaIioh AhimaIiohClip !rom Ihe AhimaIiohs !older ih Ihe
Pro|ecI View ahd add iI Io Ihe Spaceship AhimaIioh properIy o! Ihe AhimaIioh
compohehI ih Ihe ihspecIor.
You will how see ah ahimaIioh compohehI ih Ihe spaceship ihspecIor. I! you hiI play
how you will see Ihe ship Iakihg o!!. However we ohly heed Ihe ship Io Iake o!! wheh
Ihe level is compleIe. We will do Ihis wiIh a scripI ih a mihuIe. However UhiIy, by de-
!aulI, assumes you wahI ahimaIiohs Io play auIomaIically. We doh'I wahI Ihis, so,
wiIh Ihe game sIopped:
Disable Ihe "Play AuIomaIically" checkbox o! Ihe spaceShip AhimaIioh compo-
hehI.
RSU
1he spaceShip ob|ecI's ahimaIioh seIIihgs.
1he hexI sIep is Io creaIe our secohd cuI-scehe camera:
CreaIe a hew 0&+,*& ob|ecI.
Rehame iI 0.'M5,1,0&+,*&U.
PosiIioh iI oh Iop o! Ihe impouhd loI's o!!ice buildihg, as showh:
RS!
PosiIiohihg CuISceheCameraz.
Doh'I worry abouI Ihe direcIioh iI's !acihg: we're ohly ihIeresIed ih iIs locaIioh. 1he
scripI we'll aIIach Io iI will Iake care o! Ihe resI.
Add Ihe M+))'7T))G>' scripI Io Ihe Camera.
Drop a lihk Io Ihe 2B&5,M7/B model ohIo Ihe M+))'7T))G>' scripI so Ihe scripI
khows whaI Ihe camera heeds Io poihI aI.
As wiIh 0.'M5,1,0&+,*&R, we also heed Io ehsure Ihis ohe is disabled by de!aulI, buI
Ihe remaihihg seIIihgs are a liIIle di!!erehI, as you cah see !rom Ihe screehshoI oh Ihe
hexI page. 1he key di!!erehce is IhaI Ihis camera heeds Io Iake over Ihe whole screeh,
raIher Ihah appearihg ih Ihe corher, so Ihe Normalized View PorI RecI properIies are
seI Io Iake Ihis ihIo accouhI.
RSZ
SeIIihgs !or CuISceheCameraz.
Now !or Ihe cuI-scehe iIsel!. 1his is a liIIle Irickier Ihah our !irsI cuI-scehe because Ihe
messages used Io Irigger Ihe scehe heed Io be relayed alohg a chaih:
1he ihiIial Irigger happehs wheh Ihe Player Iouches Ihe spaceShip model. (I! Ihe !irsI
cuI-scehe has played Ihrough, Ihe spaceShip model is how acIihg as a Irigger ihsIead
o! a solid ob|ecI.)
1he spaceShip model Ihere!ore heeds a scripI aIIached Io iI Io deal wiIh Ihis Irigger
evehI:
CreaIe a hew 1avaScripI scripI asseI.
Rehame iI O&14%,MB&5,27/B0)%%/2/)1.
Add Ihe !ollowihg code Io iI (You cah !ihd Ihe compleIe assembled scripI code
lisIed ih Ihe appehdix secIioh):
private var playerLink : ThirdPersonStatus;
function OnTriggerEnter (col : Collider)
{
playerLink=col.GetComponent(ThirdPersonStatus);

if (!playerLink) // not the player.
{
return;
RS_
}
else
{
playerLink.LevelCompleted();
}
}
All Ihe above code does is check i! Ihe player has Iouched Ihe spaceship ahd, i! so, call
Ihe LevelCompleted() !uhcIioh ih Ihe Player's -7/*4$,*2)1M'&'.2 scripI.
Add Ihe hew scripI Io Ihe 2B&5,M7/B ob|ecI.
1he -7/*4$,*2)1M'&'.2 scripI's LevelCompleted() !uhcIioh is eveh shorIer ahd
does someIhihg very similar.
Add Ihe !ollowihg !uhcIioh Io Ihe -7/*4$,*2)1M'&'.2 scripI:
function LevelCompleted()
{
levelStateMachine.LevelCompleted();
}
%,E,%M'&',]&57/1, is a properIy which lihks Io Ihe T,E,%M'&'.2 scripI. T,E,%M'&'.2 is
where Ihe acIioh is as Ihe level compleIioh ahimaIioh is someIhihg ohly Ihe level-
relaIed scripIs should khow abouI.
Add Ihe !ollowihg LevelCompleted() !uhcIioh Io T,E,%M'&'.2 how (I'll ex-
plaih iI as we go):
function LevelCompleted()
{
FirsI, we have Io do Ihe same Audio LisIeher swiIchover as we did !or our !irsI cuI-
scehe:
mainCamera.GetComponent(AudioListener).enabled = false;
levelCompletedCamera.active = true;
levelCompletedCamera.GetComponent(AudioListener).enabled = true;
NexI, we wahI Io give Ihe illusioh IhaI Ihe player is ihside Ihe spaceship, so we'll hide
RSC
him. 1o do Ihis, we'll sehd a "HidePlayer" message Io Ihe Player's -7/*4$,*2)10)1'*)%W
%,* scripI. 1he !uhcIioh disables Ihe rehderihg o! Ihe player, so he becomes ihvisible:
playerLink.GetComponent(ThirdPersonController).SendMessage("HidePlayer");
1usI Io be oh Ihe sa!e side, we'll also physically relocaIe Ihe player Io a posiIioh we
khow should be sa!e. (1he roboIs doh'I check i! Ihe player's visible or hoI ahd Ihey're
sIill operaIihg.) Ih Ihis ihsIahce, we'll |usI move Ihe player oo uhiIs sIraighI up, which
should be !ar ehough away !rom ahy immediaIe dahger.

playerLink.transform.position+=Vector3.up*500.0; // just move him 500 units

NexI, we'll sIarI Ihe level compleIed souhd e!!ecI. Ih Ihis case, iI's Ihe souhd o! Ihe
spaceship Iakihg o!!:
if (levelCompleteSound)
{
AudioSource.PlayClipAtPoint(levelCompleteSound, levelGoal.transform.position,
2.0);
}
Now we sIarI Ihe Iimelihe-based ahimaIioh we recorded earlier ahd waiI !or iI Io !ih-
ish:

levelGoal.animation.Play();

yield WaitForSeconds (levelGoal.animation.clip.length);

Ahd !ihally, we load Ihe "Came Over" Scehe:

Application.LoadLevel("GameOver"); //...just show the Game Over
sequence.
}
NexI we musI ehsure IhaI Ihe spaceship model is hoI seI as a Irigger wheh our level
sIarIs, ahd also ehsure B%&8,*T/1G is poihIihg aI Ihe $%&8,* CameOb|ecI. We'll de!ihe
Ihe B%&8,*T/1G variable ihside ah Awake() !uhcIioh, which will be called auIomaIi-
cally by UhiIy wheh Ihe scripI is loaded.
RSJ
Chahge Ihe Awake( ) !uhcIioh Io maIch Ihe scripI below. II should be locaIed
|usI above Ihe !irsI !uhcIioh ih T,E,%M'&'.2.
private var playerLink: GameObject;
function Awake()
{
levelGoal.GetComponent(MeshCollider).isTrigger = false;
playerLink = GameObject.Find("Player");
if (!playerLink)
Debug.Log("Could not get link to Lerpz");
levelGoal.GetComponent(MeshCollider).isTrigger = false; // make very sure of this!
}
Fihally we heed Io seI our updaIed scripI's properIies as showh:
1he !ihal seIIihgs !or Ihe Level SIaIus scripI properIies.
1he resulI, wheh you collecI all Ihe !uel cahs ahd |ump ihIo Ihe spaceship, should look
someIhihg like Ihis:
RSP
Missioh compleIed! Our hero Iakes o!! !or hew advehIures.
1he hexI chapIer wraps Ihihgs up wiIh a look aI opIimizaIioh Iechhiques.
RSQ
;B'/+/=/1<
We're how aI Ihe wrappihg-up sIage. OpIimizihg is someIhihg dohe hear Ihe ehd o! a
pro|ecI, ohce all Ihe key elemehIs are ih place ahd hailed dowh. WhaI, where ahd
how you opIimize your pro|ecI very much depehds oh your pro|ecI's desigh ahd coh-
IehI, so Ihis chapIer is primarily a discussioh coverihg Ihe more commoh Iypes o! op-
IimizaIioh.
678 ;B'/+/=,a
UhiIy pro|ecIs are o!Ieh IargeIed aI older compuIers Ihah, say, a maihsIream, big-
budgeI game. Puzzle games, casual IiIles ahd oIher pro|ecI Iypes may be required Io
ruh oh ahyIhihg !rom a Cq i8ook wiIh a mere z6Mb o! RAM ahd ah ahciehI graphics
chipseI, Ihrough Io a currehI IhIel-based Mac Pro sIu!!ed Io Ihe !aceplaIes wiIh mem-
ory ahd a high-ehd graphics card.
For Ihis reasoh, we heed Io cohsider opIimizihg our pro|ecIs !or !ihal release. Ih our
case, we've already opIimized Ihe ehemy roboIs by makihg Ihem pop ihIo exisIehce
ohly wheh ih rahge, so IhaI's already covered. However, Ihe rehderihg o! Ihe scehe
cah be quiIe slow ahd Ihis is worIh lookihg aI ih more depIh.
;B'/+/=/1< b,14,*/1<j ])1/')*/1< D*&+,2 $,* M,5)14
1he besI way Io deIermihe wheIher your game heeds Io be opIimized is Io !ihd ouI
Ihe !rame-raIe -- Ihe humber o! images beihg rehdered each secohd -- ahd display
Ihis. 1he lower Ihe humber, Ihe slower Ihe game is ruhhihg.
You may have hoIiced a humber, or Ihe leIIers "FPS", ih some o! Ihe screehshoIs ih
Ihis IuIorial. 1his is because ohe imporIahI, buI merci!ully very shorI, scripI is ruhhihg
B#C,0 C#& D, -,[(*-,1 $' -(. '.
#.&$"*.8 H-'C # BT *S''2 $' # 6(-P
-,.$ M.$,+PD#0,1 Y#6 4-' 0$(HH,1
)*$" C,C'-& #.1 # "*8"P,.1 8-#="P
*60 6#-1 '- $)'Z :'- '(- 8#C,0 $'
-(. '. D'$"E ), .,,1 $' '=$*P
C*9,ZZZ
which we'll look aI how: a Frames-per-secohd reporIer scripI. 1he scripI is hamed sim-
ply D$M ahd cah be !ouhd ih Ihe ScripIs -> CUI !older o! Ihe Pro|ecI Pahe.
1he scripI is Ihoroughly documehIed, so I woh'I cover iI ih deIail here, oIher Ihah Io
add IhaI iI requires a @L3-,K' CompohehI. (1his is a UhiIy 1.x CUI CompohehI Iype as
opposed Io Ihe hew UhiIy z CUI.)
WiIh Ihis FPS couhIer, iI is easier Io geI a good idea o! where opIimizaIiohs heed Io
be made.
H;-I 1he FPS scripI is o! limiIed value wheh ruhhihg Ihe game ih Ihe UhiIy LdiIor.
1his is because Ihe LdiIor rehderer may be locked Io Ihe !rame-raIe o! Ihe dis-
play. II also has Io updaIe Ihe Scehe View ahd geherally per!orms more error-
checkihg while playihg Scehes. For more accuraIe resulIs, use a SIahdalohe
8uild o! your pro|ecI.
Z=L+$4 .1$.1 'F %51 0%=%. (+.2K=J
New Io UhiIy z is a "SIaIs" buIIoh above Ihe Came View. I! we ehable Ihis, we cah geI
some addiIiohal meIrics oh our game, which cah help deIermihe wheIher Ihere are
issues o! polygoh-couhI or oIher ob|ecI complexiIy Io resolve.
1he SIaIs pahel ih acIioh.
1hese sIaIisIics are based oh whaI Ihe camera is rehderihg, so movihg arouhd Ihe
scehe will chahge mahy o! Ihe sIaIisIics. 1he imporIahI elemehIs are:
"*&9 0&%%2 -- Ihe humber o! rehder passes. LlemehIs ih a scehe may heed Io be reh-
dered mulIiple Iimes: !or shadows, mulIiple Cameras, rehderihg Io IexIures, pixel
lighIs, ahd more. Complex shaders cah also cause addiIiohal draw calls, parIicularly i!
re!lecIioh or re!racIioh is beihg calculaIed.
RRR
-*/2 --1he humber o! Iriahgles beihg drawh.
All D models are builI up !rom Iriahgles. 1he !ewer Ihe Iriahgles, Ihe !asIer Ihey'll
rehder. Rouhd, curved ob|ecIs will geherally use more Iriahgles Ihah basic, sIraighI-
edged shapes like cubes ahd plahes.
c,*'2 --1he humber o! verIices beihg sehI Io Ihe graphics chip.
A verIex is a poihI ih D space. 1he more verIices you cah share across Iriahgles, Ihe
more o! said Iriahgles you cah rehder ahd Ihus Ihe more complex your models cah be.
L2,4 -,K'.*,2 -- Ihe humber o! IexIures used Io rehder whaI you see.
MaIerials cah use ohe or more IexIures, depehdihg oh how Ihe maIerial is de!ihed
ahd Ihe shader scripI iI is usihg. 1he shader de!ihes how Ihe IexIures are combihed,
producihg e!!ecIs such as bump-mappihg, glossy shihe highlighIs, re!lecIiohs ahd re-
!racIioh.
-3$ ParIicle sysIems use Iwo Iriahgles !or each parIicle, ahd aI leasI ohe IexIure.
(1exIures are usually shared by all Ihe parIicles ih a parIicle sysIem.) II is very
easy Io geI carried away wiIh Ihese e!!ecIs, buI you should Iake care hoI Io
overdo iI.
b,14,* -,K'.*,2 -- Ihe humber o! cameras ouIpuIIihg Io a IexIure raIher Ihah direcIly
Io Ihe display. 1his ish'I as clear-cuI as you mighI expecI...
Rehder IexIures are used Io achieve a humber o! e!!ecIs, such as posI-processihg e!-
!ecIs, a CC1V screeh displayihg ahoIher area o! a level, or Io produce re!lecIioh ih wa-
Ier, a mirror or glass re!racIioh e!!ecIs. Ih addiIioh, mosI shadows are also produced
usihg Ihis Iechhique, so you woh'I hecessarily see addiIiohal cameras ih your Scehe
View.
;B'/+/=/1< b,14,*/1<j -7, -9)W0&+,*& M82',+
I! you have played wiIh Ihe compleIed pro|ecI, you may have hoIiced by how IhaI
Ihere are, ih !acI, Iwo NearCameras: a Near Camera ahd a Far Camera. 1his Iwo-
camera sysIem reduces Ihe amouhI o! rehderihg heeded !or each !rame.
1he H,&* 0&+,*& rehders everyIhihg wiIhih a close rahge, ih Ihis case, !rom o.q Io o
uhiIs.
-3$ A uhiI cah, ih Iheory, be ahy arbiIrary lehgIh you like, buI mosI developers
Iehd Io sIick wiIh "1 uhiI = 1 meIer" !or Ihe sake o! sahiIy. Ah imporIahI Iip is
Io make sure your arIisI(s) are aware o! Ihe scale you are usihg.
1he D&* 0&+,*& rehders !rom Ihe o uhiIs mark Ihrough Io arouhd oo uhiIs. How-
ever, iI ohly rehders a subseI o! Ihe Scehe daIa. 1he subseI is de!ihed by Layers. Lach
RRU
ob|ecI ih Ihe Scehe is giveh a Layer Io live oh. 1he H,&* 0&+,*& rehders all elemehIs
regardless o! Iheir layer, buI as you cah see !rom Ihe screehshoI below, Ihe D&* 0&+W
,*& has beeh Iold Io ighore Ihose iIems ih Ihe "camera1wo" or "camera1woIghore-
LighIs" Layers. We'd also like iI Io ighore Ihe !uel cahs ahd healIh pickups. 1hese have
Ihe "hoShadow" Layer, so IhaI Ioo is uhchecked !or Ihis camera.
H;-I Uhcheckihg Ihe "hoShadow" Layer also meahs iI woh'I rehder Ihe player ei-
Iher, which is !ihe as Ihe player is uhlikely Io be IhaI !ar away !rom Ihe Near
Camera.
1he Far Camera Cullihg Mask seIIihgs.
H;-I 1he D&* 0&+,*& is also Ihe camera where Ihe Skybox is rehdered. (See Ihe
0%,&* D%&<2 seIIihg ih Ihe shoI above.) 1he H,&* 0&+,*&'s 0%,&* D%&<2 seIIihg is
"DepIh Ohly", so IhaI iIs cohIehI is superimposed over IhaI o! Ihe D&* 0&+,*&.
1he D&* 0&+,*&'s cohIehI is rehdered !irsI.
1his selecIioh is de!ihed by Ihe Cullihg Mask properIy o! Ihe camera compohehI.
1icked layers are rehdered, uhIicked layers are hoI. You cah de!ihe a Layer ih Ihe Ih-
specIor ahd assigh ohe Io ahy CameOb|ecI.
You cah see Ihis opIimizaIioh ih acIioh wiIh Ihe roboI guards ahd Ihe collecIable
iIems. I! you move Iowards ohe o! Ihese iIems, you will see Ihe scehery arouhd iI is
always rehdered while Ihe iIem iIsel! appears relaIively close Io Ihe player.
RR!
I14 )( '7, *)&4V
-7, b)&4 T,22 -*&E,%%,4
AI Ihe Iime o! wriIihg, Ihis IuIorial holds Ihe dubious hohor o! beihg Ihe lohgesI ever
produced !or UhiIy. We have seeh how Io build a sihgle level o! a game based arouhd
Ihe D PlaI!ormer gehre, buI eveh a!Ier all Ihese pages, we have barely scraIched Ihe
sur!ace o! whaI is possible wiIh UhiIy z, or eveh wiIh Ihis parIicular gehre.
Our |ourhey IogeIher is dohe: II's Iime !or you Io Iake Ihe sIabilizer wheels o!! Ihe
bicycle ahd cohIihue alohe, buI be!ore you go, here are some suggesIiohs !or whaI Io
Iry hexI...
M.<<,2',4 3+B*)E,+,1'2
Lerpz Lscapes has beeh le!I deliberaIely uh!ihished. We have a very basic SIarI Mehu
ahd a Came Over screeh, buI Ihere's ohly Ihe ohe game level ahd iI is clearly ihIehded
Io be Ihe lasI ohe ih Ihe game. How could iI be improved?
-+H+$4 %51 (1K+P1&=%1 B+.%=L1.
Yes, Ihere are some mihor issues wiIh Ihe game as iI sIahds. 1hese have beeh deliber-
aIely le!I ih place Io give you a chahce Io hohe your skills. 1hey are:
I! you kill a roboI, buI are respawhed hearby be!ore you have moved ouI o! rahge, a
hew roboI will appear, buI Ihe old ohe will remaih.
1he Laser 1raps doh'I kick Ihe player away, so iI is possible Io lose all your healIh
raIher quickly.
!"#$ ), "#?, +,#-.,1Z
!",-, $' 8' .,a$Z
8oIh cah be resolved by applyihg whaI you have learhed ih Ihis IuIorial.
Z'&1 K1<1K.
1he Pro|ecI Pahe ihcludes a "8uild Your Owh" !older cohIaihihg all Ihe ihdividual as-
seIs used Io build Ihe level, so addihg hew levels should hoI be di!!iculI.
You will heed Io use Ihe DontDestroyOnLoad() !uhcIioh so IhaI you cah carry
game sIaIe ih!ormaIioh beIweeh Ihe levels such as Ihe currehI score, lives remaihihg,
eIc.
Z'&1 1$1B+1.
1he game ohly has Ihe ohe ambulaIory ehemy ih Ihe !orm o! Ihe roboI guards. Why
hoI add some more? 1his is a good way Io ehsure you have uhdersIood Ihe ahimaIioh
ahd AI aspecIs. II will also help you geI a !irm grasp o! buildihg models ahd imporIihg
Ihem ihIo UhiIy.
;(( .*'&+$4
Lerpz Lscapes lacks a score sysIem. Addihg ohe is hoI di!!iculI, buI addihg visual e!-
!ecIs wheh Ihe player does someIhihg worIhy o! ihcreasihg Iheir score cah be as chal-
lehgihg as you like. (Ahd, o! course, you'll wahI Io keep Irack o! Ihe score across
Scehes.)
;(( = $1%M'&L1( 5+45[.*'&1 .J.%1B
1he UhiIy z brihgs solid heIworkihg supporI Io Ihe Iable, as well as ihIegraIioh wiIh
websiIes. WhaI beIIer way Io show o!! Ihah uploadihg your high score Io a cehIral
server so you cah gloaI? 1his is a good way Io wrap your head arouhd heIworkihg ba-
sics.
;(( B)K%+2K=J1& .)22'&%
Addihg heIworked mulIiplayer game supporI is probably Ihe IrickiesI Ihihg you cah
do wiIh ahy game. NaIurally, UhiIy cah help here Ioo, buI you will heed Io geI dowh
ahd dirIy wiIh scripIihg. 1his is a good, advahced-level improvemehI Io add.
D.*'7,* b,&4/1<
1he !irsI place Io look !or more ih!ormaIioh is, as always, UhiIy's owh documehIaIioh.
1here are also mahy IuIorials (ihcludihg video primers) oh Ihe UhiIy websiIe:
hIIp://uhiIyd.com/supporI/documehIaIioh/
Ih addiIioh, Ihe Uhi!y Wiki is ah excellehI source o! user-cohIribuIed ih!o:
hIIp://www.uhi!ycommuhiIy.com
Ahd !ihally, you cah Ialk Io experIs ahd hewcomers alike ih our Ihrivihg !orums, here:
hIIp://!orum.uhiIyd.com/
RR_
M5*/B' >BB,14/K
0%=&%Z1$)89# .*&+2%
Here is Ihe assembled code !or Ihe M'&*'],1.@L3 scripI.
//@script ExecuteInEditMode()
var gSkin : GUISkin;
var backdrop : Texture2D;
private var isLoading = false;
function OnGUI()
{
if(gSkin)
GUI.skin = gSkin;
else
Debug.Log("StartMenuGUI : GUI Skin object missing!");
var backgroundStyle : GUIStyle = new GUIStyle();
backgroundStyle.normal.background = backdrop;
GUI.Label ( Rect( ( Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2,
Screen.height), "", backgroundStyle);
GUI.Label ( Rect( (Screen.width/2)-197, 50, 400, 100), "Lerpz Escapes",
"mainMenuTitle");
RRC
!",-, $", 06-*=$0 #-, #00,CD+,1
if (GUI.Button( Rect( (Screen.width/2)-70, Screen.height -160, 140, 70), "Play"))
{
isLoading = true;
Application.LoadLevel("TheGame");
}
var isWebPlayer = (Application.platform == RuntimePlatform.OSXWebPlayer ||
Application.platform == RuntimePlatform.WindowsWebPlayer);
if (!isWebPlayer)
{
if (GUI.Button( Rect( (Screen.width/2)-70, Screen.height - 80, 140, 70),
"Quit")) Application.Quit();
}
if (isLoading)
{
GUI.Label ( Rect( (Screen.width/2)-110, (Screen.height / 2) - 60, 400, 70),
"Loading...", "mainMenuTitle");
}
}
8=B1A<1&89#
Here is Ihe assembled code !or !or Ihe @&+,;E,*@L3 scripI:
@script ExecuteInEditMode()
var background : GUIStyle;
var gameOverText : GUIStyle;
var gameOverShadow : GUIStyle;
var gameOverScale = 1.5;
var gameOverShadowScale = 1.5;
function OnGUI()
{
GUI.Label ( Rect( (Screen.width - (Screen.height * 2)) * 0.75, 0, Screen.height * 2,
Screen.height), "", background);
GUI.matrix = Matrix4x4.TRS(Vector3(0, 0, 0), Quaternion.identity, Vector3.one *
gameOverShadowScale);
GUI.Label ( Rect( (Screen.width / (2 * gameOverShadowScale)) - 150,
(Screen.height / (2 * gameOverShadowScale)) - 40, 300, 100), "Game Over",
gameOverShadow);
RRJ
GUI.matrix = Matrix4x4.TRS(Vector3(0, 0, 0), Quaternion.identity, Vector3.one *
gameOverScale);
GUI.Label ( Rect( (Screen.width / (2 * gameOverScale)) - 150, (Screen.height / (2 *
gameOverScale)) - 40, 300, 100), "Game Over", gameOverText);
}
8=B1A<1&0*&+2%
Here is Ihe assembled code !or Ihe @&+,;E,*M5*/B' scripI:
function LateUpdate ()
{
if (!audio.isPlaying || Input.anyKeyDown)
Application.LoadLevel("StartMenu");
}
75+&(N1&.'$0%=%).
Here is Ihe assembled code !or Ihe -7/*4$,*2)1M'&'.2 scripI:
// ThirdPersonStatus: Handles the player's state machine.
// Keeps track of inventory, health, lives, etc.
var health : int = 6;
var maxHealth : int = 6;
var lives = 4;
// sound effects.
var struckSound: AudioClip;
var deathSound: AudioClip;
private var levelStateMachine : LevelStatus; // link to script that handles the level-
complete sequence.
private var remainingItems : int; // total number to pick up on this level. Grabbed from
LevelStatus.
function Awake()
{

levelStateMachine = FindObjectOfType(LevelStatus);
if (!levelStateMachine)
Debug.Log("No link to Level Status");

remainingItems = levelStateMachine.itemsNeeded;
}
// Utility function used by HUD script:
RRP
function GetRemainingItems() : int
{
return remainingItems;
}
function ApplyDamage (damage : int)
{
if (struckSound)
AudioSource.PlayClipAtPoint(struckSound, transform.position); // play the 'player
was struck' sound.
health -= damage;
if (health <= 0)
{
SendMessage("Die");
}
}
function AddLife (powerUp : int)
{
lives += powerUp;
health = maxHealth;
}
function AddHealth (powerUp : int)
{
health += powerUp;
if (health>maxHealth) // We can only show six segments in our HUD.
{
health=maxHealth;
}
}
function FoundItem (numFound: int)
{
remainingItems-= numFound;
if (remainingItems == 0)
{
levelStateMachine.UnlockLevelExit(); // ...and let our player out of the level.
}
}
function FalloutDeath ()
{
RRQ
Die();
return;
}
function Die ()
{
// play the death sound if available.
if (deathSound)
{
AudioSource.PlayClipAtPoint(deathSound, transform.position);
}

lives--;
health = maxHealth;

if(lives < 0)
Application.LoadLevel("GameOver");

// If we've reached here, the player still has lives remaining, so respawn.
respawnPosition = Respawn.currentRespawn.transform.position;
Camera.main.transform.position = respawnPosition - (transform.forward * 4) +
Vector3.up; // reset camera too
// Hide the player briefly to give the death sound time to finish...
SendMessage("HidePlayer");

// Relocate the player. We need to do this or the camera will keep trying to focus on
the (invisible) player where he's standing on top of the FalloutDeath box collider.
transform.position = respawnPosition + Vector3.up;
yield WaitForSeconds(1.6); // give the sound time to complete.

// (NOTE: "HidePlayer" also disables the player controls.)
SendMessage("ShowPlayer"); // Show the player again, ready for...
// ... the respawn point to play it's particle effect
Respawn.currentRespawn.FireEffect ();
}
function LevelCompleted()
{
levelStateMachine.LevelCompleted();
}
R1<1K0%=%).
Here is Ihe assembled code !or Ihe T,E,%M'&'.2 scripI:
RUS
// LevelStatus: Master level state machine script.
var exitGateway: GameObject;
var levelGoal: GameObject;
var unlockedSound: AudioClip;
var levelCompleteSound: AudioClip;
var mainCamera: GameObject;
var unlockedCamera: GameObject;
var levelCompletedCamera: GameObject;
// This is where info like the number of items the player must collect in order to
complete the level lives.
var itemsNeeded: int = 20; // This is how many fuel canisters the player must collect.
private var playerLink: GameObject;
// Awake(): Called by Unity when the script has loaded.
// We use this function to initialise our link to the Lerpz GameObject.
function Awake()
{
levelGoal.GetComponent(MeshCollider).isTrigger = false;
playerLink = GameObject.Find("Player");
if (!playerLink)
Debug.Log("Could not get link to Lerpz");
levelGoal.GetComponent(MeshCollider).isTrigger = false; // make very sure of this!
}
function UnlockLevelExit()
{
mainCamera.GetComponent(AudioListener).enabled = false;
unlockedCamera.active = true;
unlockedCamera.GetComponent(AudioListener).enabled = true;
exitGateway.GetComponent(AudioSource).Stop();

if (unlockedSound)
{
AudioSource.PlayClipAtPoint(unlockedSound,
unlockedCamera.GetComponent(Transform).position, 2.0);
}
yield WaitForSeconds(1);
exitGateway.active = false; // ... the fence goes down briefly...
yield WaitForSeconds(0.2); //... pause for a fraction of a second...
exitGateway.active = true; //... now the fence flashes back on again...
yield WaitForSeconds(0.2); //... another brief pause before...
exitGateway.active = false; //... the fence finally goes down forever!
levelGoal.GetComponent(MeshCollider).isTrigger = true;
yield WaitForSeconds(4); // give the player time to see the result.
RUR
// swap the cameras back.
unlockedCamera.active = false; // this lets the NearCamera get the screen all to
itself.
unlockedCamera.GetComponent(AudioListener).enabled = false;
mainCamera.GetComponent(AudioListener).enabled = true;
}
function LevelCompleted()
{
mainCamera.GetComponent(AudioListener).enabled = false;
levelCompletedCamera.active = true;
levelCompletedCamera.GetComponent(AudioListener).enabled = true;
playerLink.GetComponent(ThirdPersonController).SendMessage("HidePlayer");
playerLink.transform.position+=Vector3.up*500.0; // just move him 500 units

if (levelCompleteSound)
{
AudioSource.PlayClipAtPoint(levelCompleteSound, levelGoal.transform.position,
2.0);
}
levelGoal.animation.Play();
yield WaitForSeconds (levelGoal.animation.clip.length);
Application.LoadLevel("GameOver"); //...just show the Game Over sequence.
}
U=$(K102=*1.5+2Q'KK+.+'$
Here is Ihe assembled code !or Ihe O&14%,MB&5,27/B0)%%/2/)1 scripI:
function OnTriggerEnter (col : Collider)
{
playerLink=col.GetComponent(ThirdPersonStatus);
if (!playerLink) // not the player.
{
return;
}
else
{
playerLink.LevelCompleted();
}
}
RUU

You might also like