Professional Documents
Culture Documents
Lea how to make a full 3D game for iOS with Unity! arn
This is a tu utorial by Joshu Newnham, the founder of We Make Play an independe studio craf ua f y, ent fting creative d digital play for em merging platfor rms. Unity is ar rguably the most popular 3D g game engine fo iOS and fo many good r for or reasons! Rap developme Writing yo game with U pid ent. our Unity is far qui icker than tryin to write you own 3D engi or ng ur ine, than using lower level 3D frame n l eworks. Vis sual scene layo Unity com with a powe out. mes erful 3D scene editor that you can use to de u esign a huge pa of art you app often without having to write code! ur w g Cro platform. If you write you game with U oss ur Unity, you can deploy it to iO Android, W OS, Windows, Mac, or , eve the web! en Eas to learn. Un is far easie to learn than straight OpenG or lower le framework Its friendly to sy nity er GL evel ks. y beg ginners and is easy to get star e rted! We just rel leased an epic three-part Beg ginning Unity 3 for iOS seri but if your itching to learn more, wev got 3D ies, re ve you covere ed! This time, you will create a simple but fun 3D basketb game calle Nothing bu Net. Along the way, youl e ball ed ut ll cover the m major concepts used in Unity and will be ready to create y s your own apps! ! Some of th tutorial will be review, but youll learn a ton along the way since this game is much more complic his l s h cated than the H Heroic Cube game ;] g Note: This tutorial was made with Unit 3, so there m be some sli s m ty may ight difference with Unity 4 es 4. Shall we play a game? :]
For this tut torial, lets assu your targe audience is a male between the ages of 12 ume et n 2-35 lets cal him Bryan. B ll Bryan is: a 33 year old Acc countant own an iPhone ns is in nterested in sports is a office dweller with an aver an rage commute time of 20 min per day on pu n ublic transport. .
Like most smartphone us sers, Bryans iP Phone is a regu form of entertainment du ular uring commutin and in gene ng, eral, every spare moment whe he is alone and even som e en metimes when h bored at di hes inner, much to his wifes annoyance e! Your goal will be to crea something th offers Brya a chance to escape for a fe minutes dur ate hat an ew ring his day. Youll create a ve simple (but fun!) app with just a single a easy to lear mechanic. T way, it can be easily pick up ery h and rn This n ked and used in a noisy and disruptive envir n d ronment, such as commuting g. As your tar audience is males between the ages of 12-35, your th rget i heme for the ga will be spo related. Mob ame ort bile casual gam play typicall ranges betw me ly ween 4-8 minute so aim for a complete gam es ming session including load ding and starting the game to last 5 minut g tes. So you w a simple mechanic, and a quick sportswant m -related game. How about sho ooting a basket tball? Heres a sketch of w it could lo like: what ook
Ah your getting some re ewhere! Time t flesh out the functionality and componen you will nee to e nts ed! Mechanic/ /Interaction: Goal: score as ma points as possible within the time limit any To throw the ball, the player tap and holds their finger on th screen. The longer their fin ps he nger is held do own the harder the ball will be throw Leaving it d wn. down too long will raise a fou ul. Features: Vis sually rich and engaging to at ttract the playe er Sim support menu (overlay the game screen with the opti to start the game) mple m n ion Rea alistic physics to allow for rebounds Inc crease the diffic culty by movin the avatar ar ng round the court more frequen as time pas and the pla t ntly sses ayer gets more comfor rtable with the game). Game asse and their fe ets eatures: Env vironment Hoop Ring Court Skybox
Okay, now that you have the basic design of the app d w e down, its time to start creatin :] e ng!
Note: The introductory videos and man v nuals listed here are helpful re e esources to che out after yo finish going eck ou g through thi tutorial the will give you a good overv is ey view of Unity a what its capable of. For a more and comprehen nsive review, check out the of fficial documentation athttp://doc cs.unity3d.com m/Documentation/Manual/Lea arningtheInterf face.html.
Before you get started, ha a quick loo at Unitys u interface, w u ave ok user which will beco the comm ome mand center for all of your Unity projects! :] y
Unitys UI is made up of 5 individual p I f panels, each tig ghtly related, bu giving you a different pers ut spective of the project. First, the P Project panel provides you w an overview and quick ac p with w ccess to all the assets of your game. Assets s means any resources that your game wi use, such as scripts, texture sounds, and data files. y t ill es, d Note that s some of the folder names that will appear in this panel are used for speci tasks. For i t n e ific instance, when using n graphical e elements for G Gizmos, which are design tim icons, you need to place t h me them in a Gizm folder so U mo Unity knows whe to search fo them. ere or Second, the Hierarchy pa anel is a view of all assets th are in the cu hat urrent scene. Th allows you to quickly sele his u ect items witho having to navigate throug the 3D view or perform a multi-select. A quick tip t get focus of a out n gh w to particular a asset, hover yo mouse over the item you w to focus o in the Scene panel and tap the F key. our r want on e p On to the C Camera panel! This gives yo the point of v ! ou view of the cam mera(s) in the scene. Note the three toggle e buttons at t top right. Maximize on P maximizes the window w the M Play s when you selec Play. Stats is handy when y ct s you are ready to optimize you app, as it wil show you dr calls and ot ur ll raw ther useful stat ts.Gizmos allow you to show and ws w hide specif Gizmos in the game scene fic t e.
The panel above the Cam mera panel is w where youll sp pend most of yo time design our ning your level This is theS ls. Scene panel whic allows you to visually desi your level. If youre fami ch t ign iliar with 3D m modeling tools, then you shou uld feel pretty comfortable here! :] If not, d dont fret Un is pretty in nity ntuitive and eas to learn. sy The selecte item, includ ed ding the camera can be manip a, pulated using t manipulatio tools at the t of the wind the on top dow:
The hand t tool allows you to pan around the scene. Th translation t u d he tool will show handles on the selected item e m, allowing y to move, or translate, the item around th scene. Rotat you r he tion and scale a allow you to m manipulate the selected ite by rotating or scaling it. em Note: Its w worth getting comfortable wi the short-cu to these tool Its pretty easy to rememb them; theyre the c ith uts ls. ber first four le etters on the ke eyboard and they correspond in order to the four tools: Q ( e (Hand), W (Tr ranslate), E (Ro otate), and R (Sca ale). Dont forg your good f get friend F to focu in on the sel us lected item you will use F a lot! :] A quick no about Scale its best not t manually sca things unle you are usin it for a visua effect. Scale your ote e: to ale ess ng al e models via the import op a ptions, which youll get into s shortly, and lea the scaling to 1.0. This en up being a lot ave nds more effici ient. The final p panel is the Insp spector panel this gives acc to all the p cess publicly accessible properties of the selected d object. Thi is an importa concept to u is ant understand so take some time explaining w this means e what s. All elemen in your gam inherit from GameObject. Different Com nts me mponents, whic derive from a component ch called Mon noBehaviour, are attached to each GameOb o bject. These Co omponents det termine how th GameObject will he t behave in y your scene. Each one o these Compo of onents is visibl via the Inspe le ector panel wh you can tw here weak their prop perties. Compo onents vary widel and can rang from anythi from a simp script that y write, to a camera, physi properties, an ly, ge ing ple you ic nd more. Esse entially, a Com mponent provides you with a f flexible way to build up your game element in a modular o r ts r fashion. It worth noting that all Game s g eObjects have a Transform component th heTransform co omponent determines where the Ga s ameObject lives in 3D space. Note: If yo oure familiar with iOS development think o your GameO w of Object as an NS SObject. Rathe than inheritin er ng functionali you attach specialized cla ity, asses to the obj each give it different f ject es functionality bu they are bun ut ndled together as one unit. s Below is a screenshot of the Inspector p panel when the camera is sel lected.
The components here include: Transform (attached to all GameObjects), Camera, GUILayer, Flare Layer, and Audio Listener. Dont worry about what they mean yet I just wanted to show an example of how you can see components on an object and configure its settings. Along with the panels, Unity exposes a host of functionality via the toolbar. The two items youll be most interested in are the Game Object and Component items. The Game Object menu item provides you with a list of items you can add to the current scene. The submenu items youll be interested in are Create Empty and Create Other -> GUI Texture. Create Empty places a new (empty) GameObject onto the scene. Create Other -> GUI Texture creates a GameObject with the GUITexture component attached and the currently selected texture as its texture, or the default Unity logo if a texture is not selected. At this point, you have a basic understanding of the Unity interface. Youll get a chance to start playing around with it in the next section, where youll start creating your Unity scene!
Game A Assets
In this sect tion, youll wal through the process of imp lk porting an asse into Unity, di et iscover how U Unity handles as ssets, and quickly cover what Materials are an what role th play in Uni y M nd hey ity. Looking at the list of feat t tures from the design section of this tutorial you have a p n l, pretty good han on what A ndle Assets youll requ uire. Imagine your designer h created the assets for you, including the images and fon necessary t y has , nts to create the m menu scr main reen:
Here the us can quickly initiate a gam and see their progress. Not that social networking is not implemented in ser y me r te this tutoria al. Your desig gner has also cr reated some tex xtures and 3D models for the main level, w e which will look like this:
He has delivered all of th hese assets as a zip file, which you can down h nload here. Af you unzip t file, you sh fter the hould see a directory of textures, fonts, image and models like this: es,
Now lets i import a few of the assets int your project. On the Projec panel in Unit click on the Createbutton and o to ct ty, e n select Fold Create the structure as sh der. hown below:
Start with t GUI graphics youlll be u the using in this tut torial. Drag all the files in the /NBNAssets/ l e /GUI folder int the to /NothingBu utNet/GUI fold These are the graphics th you will be using for your GUI, includin the icon and der. hat r ng d splash scre een. Unity will automatically detect the type of asset your importing an set some default properties In this case, Unity e re nd s. assumes th the .png file youre importing will be us as 3D mod textures and apply compre hat es sed del d ession to them. This . will result in a reduction in image quali when rendering them as G Textures, w ity GUI which you don want! :] nt Youll need to go through each image a set the type to GUI. To do this, select an item, navigat to the Inspec h and e o n te ctor panel and s select GUI option from the T Texture type dro opdown (as shown below).
Repeat the above for each of your imag h ges. Next, impo the textures for your mode Drag the .p files from t /NBNAssets/Textures fol ort s els. png the lder into the /NothingBu utNet/Textures folder in Unit Since these are textures fo your 3D models, you can l s ty. e or leave the defau ult settings as they are. Now import the fonts. Dr the .ttf files from the /NB rag s BNAssets/Fonts folder into the /NothingButN s Net/Fonts fold in der Unity. The fonts come from www.dafont.com (http://www.dafont ese t.com/score-board.font by Bo Fonts, ou and http://w www.dafont.co om/varsity.font by Unknown) t ). Finally, im mport the models. Drag the .fb files from th /NBNAssets bx he s/Models folde into the /Noth er hingButNet/M Models folder in U Unity. Note: The models for this game were cr reated in the op source (fre 3D creation tool Blender and exported a pen ee) n as FBX. Unity provides exte y ensive support for a wide array of media fo t ormats for audio graphics, an 3D assets be o, nd eyond just FBX f files for more information o the file form supported by Unity, please refer to Unitys importing e on mats guide. After addin the models, you should ch ng heck the texture are correctly associated wi your model To do this, c es y ith ls. click on each mo and inspec in the Previe pane of the Inspect panel If you click o the model an move the m odel ct ew l. on nd mouse around, yo can rotate th model to insp it from all sides. ou he pect l
If your mo odels are grey, then its most l t likely that the l link between th Material and Texture is br he d roken. Ill explain how this lin nking works an how you ca fix it in the n section m nd an next materials and t textures!
For the Ho oopTex Materia youll requi transparency to be set. Sel this materi and choose the al, ire lect ial Transparen nt/VertexLit Sh hader. Theres jus a few things left to do in th section befo you wrap th st his ore hings up. There is no standard e dized scaling between 3D modeling too so to get th models to a reasonable siz select each o them and up D ols, he ze, of pdate their scale factor from 0.01 to 1 as shown below: m s
Finally, open up the Player model and youll notice a few child elem p y ments, as below: w
Some of th hese child elem ments will differ depending on what 3D mod n deling tool you are using. In B u Blender, the BP Player and BPlaye erSkeleton are the objects, th BPlayer (und BPlayerSke he der eleton) is the m mesh data that d describes the geometry o the player, and finally the i of a items below th are animatio frames, whi will be desc hat on ich cribed in furthe er detail once you start wirin up your pla e ng ayer!
However, t is easier sa than done! :] this aid This is you first chance to start playing around with t Scene, Cam ur t g the mera, and Hiera archy panels in Unity. Perform the n m following s steps: Sel the Main Camera in the H lect C Hierarchy folde and set X=6 Y=7, Z=14 and the Y-Ro er, 6.5, 4, otation to -180 0. Dra a scene mod into the Hie ag del erarchy panel, and set X=0, Y Y=0, and Z=0. You should se it appear in t ee the Cam window! mera Dra a player mo into the Hi ag odel ierarchy panel, and the Y-rota ation to 90. Now that y have some basic objects a you appearing, exp periment movin the player ar ng round the scen using the Sce ne ene panel. Sele the player, and drag it arou the scene u ect a und using the X, Y and Z arrows that appear ne to the playe Y, s ext er when its s selected. You can also change the perspectiv of how youre looking at t scene using the perspectiv c e ve the g ve switcher in the upper righ of the scene panel. n ht
At this poin add the rem nt maining objects the basketba and the hoop See if you c arrange the into roughly the all op. can em y right spot y yourself using the Scene and Hierarchy pan if you ge stuck, you ca always set th position ba to nels et an heir ack the center ( (X=0, Y=0, Z= =0). While youre playing aro ound with this, you might not that whatev you click o in Hierarchy is highlighted in tice ver on y d the Scene. You can also easily zoom in on an object in the scene vie for examp try double clicking on the e n n ew ple, e Player to c center it.
If it isnt centered the wa you want it, use your mous wheel to zoo in or out, d ay se om drag the view in the window w n with the mouse, or hold down the Alt/Option key to rotate around and see things from a , n e another angle. Note that n none of these operations affec the actual po o ct osition of objec its just to h you get a better view. cts, help Now that y have your scene roughly set up, time to configure the scoreboard! you
Note: GameObjects can have children and those children can have children, and so on and so forth. Children of a GameObject dont directly inherit functionality of their parent (unless explicitly scripted), but rather use their parents scene space to position themselves. For instance, if the parent was moved along the x-axis, then all the children of the parent would also be moved e.g. if you held a basketball (your child) and walked forward, the basketball would move forward with you. To make a child independent so that it doesnt inherit the translation, orientation, and scale of its parent (also known as the objects pose), then simply drag it out of its parent folder as you did here. The reason you split out the Scoreboard like this was so you could add some 3D Text objects to it, to show the earned points and remaining time. This is not mandatory but rather an choice for aesthetics and organisation. Doing so helps (visually) de-couple it from the rest of the scene and gives you the choice of creating a prefab (which we will talk about later) that you would use if you were to create multiple levels. The 3D Text object is surprise! :] an object that renders text in a 3D environment. Add a 3D Text object to the scene by selecting the Menu GameObject -> Create Other -> 3D Text. This will place a new GameObject called New Text into your scene. Rename this 3D Text object to Points and drag it into your Scoreboard object. Next, associate thescoreboard font with the 3D text by performing the following steps: Drag the Project\NothingButNet\Fonts\Scoreboard font to theHierarchy\Scoreboard\Points\Text Mesh\Font property Drag the Project\NothingButNet\Fonts\Scoreboard\Font Material material to theHierarchy\Scoreboard\Points\Mesh Renderer\Materials\Element 0 property In the inspector for the 3D Text, set the default text to 0000 and the alignment to right middle aligned. Then use the Scene panel to position the font on the right spot on the Scoreboard. Note you may have to rotate the text to get it to show up right for me, my settings were X=0, Y=0, Z=2.8, Rotation X=270, Y=180, Z=0. Now perform the same step for the Time text by duplicating the Points text using Cmd-D and positioning it slightly below. Name the duplicated object Time and set the default text to 00:00. In the end you should have something that looks like the following:
same visua effect. Also, use the scenes ambient light to control the lighting inten al e nsity; this can b accessed via the be a Edit -> Ren nder Settings panel. p In your sim scene, you will add a lig Select Gam mple u ght. meObject -> Cr reate Other -> Directional Light to add a n new directional light GameOb l bject to your sc cene that will b brighten everyt thing up. A full discu ussion about li ighting is out o scope for this tutorial, but a directional lig influences the whole scen of ght ne depending on where you direct of the li ight by rotating the Direction Light Game g nal eObject. Select the light and use t the move a rotate tools in the Scene p and s panel to experi iment moving i in different p it positions.
Camera P Position
Now turn y your focus (pun fully intende :]) to the co n ed! orrect positionin of the came Camera positioning is not a ng era. t science, bu rather more of an art. Play the part of the director, and d ut o drag the camera into place using the movem a ment and rotatio tools in the Scene panel. on S You can us the preview available in th Game panel directly below the Scene pan where youre doing your scene se he w nel building. A well, you ca make use of the little previ window th pops up whe the camera is selected in th As an f iew hat en he Hierarchy view. Next, in th you should update your Ga screen dim he u ame mensions to iPh hone Wide 480320, via the d dropdown in th he upper right of the Game panel. If you d not see this, go to Unity\Bu Settings, a switch your platform to iO t p do uild and r OS. At this poin you should have a view si nt, imilar to the on below: ne
Your scene is looking pretty good, isnt it? Feel like a real director yet? :]
Before you add physics capabilities to your objects, youll need to first take a look into what Physics means in Unity. Click on the Components -> Physics menu (top toolbar) and have a quick look through the types of components readily available to you.
Colliders define the physical dimensions of your object, which can be independent of the visual shape of the object. In general, the colliders are ordered by complexity, and the more complex the object, the performance cost of using these objects rises. Where possible, use Box/Sphere to encapsulate your objects, as these Colliders have the least computational load for your application. The other common Collider youll use frequently is the Mesh Collider. This uses the 3D models mesh to define the boundary of your object. In this case, the visual dimensions will equal the physical dimensions. In addition to physically colliding with other objects, a Collider can be set up as a trigger that can detect collisions (so you can make something happen programmatically), but not actually cause any collision responses. This will be useful so you can detect when the ball goes through the basketball net. In order for objects to react, each object must have some form of body in addition to a collider. This is done by either adding a Rigidbody or CharacterController to the GameObject. The best way to get comfortable with Physics is to play around lets make that basketball bounce!
On the Project panel, select the Create dropdown menu and then select Physic Material to create aPhysic Material , and name it BallPhyMat.
Now set the properties of the Physic Material as shown below. Details on the function of each of the properties shown below is out of scope for this tutorial, but further information can be found athttp://docs.unity3d.com/Documentation/ScriptReference/PhysicMaterial.html.
In order to allow the ball to bounce, friction is set fairly low. To associate the newly created Physic Material to the basketball, select the Physic Material you just created and drag it to the to the basketballs Collider material property.
Click the play button again, and this time it falls to the floor and bounces, w00t! :] As for the hoop, you want it to react to the ball as well as detect when the ball goes through the net. Add aMesh Collider to the hoop mesh (hoop.LeftHoop). Also, you want to set up a sensor or trigger to detect when the ball goes through the hoop. To do this, add a Box Collider to hoop.LeftHoop_001, but shorten the box and position it so its just below the net (you can do this by tweaking the values in the Inspector I changed Center Z to -1.4 and Size Z to 0.2). Also, click the checkbox to set the trigger property to true.
Note: to vi isually resize colliders using t mouse, sele the collider object and h the ect rs hold down Shif This will sh ft. how the handles of the collide allowing you to resize it us s er, u sing the mouse e. Okay! Tha takes care of the ball tim to take a loo at the Player object! :] at f me ok r
Note: Colliders are shown in the Scene panel in a green outline unless they are Mesh Colliders , in which case its the mesh that shows the collision boundaries. The approach used to bounce the ball requires that the game can detect when the ball collides with the players hand. When this occurs, you will push the ball back down to the ground, just like it happens in real life! To attach the collider at the correct position, youll drill down to the players skeleton and add the collider to the hand which will be used to bounce the ball.
The above screenshot shows you the children of the player GameObject. Where do these children come from? Good question! :] These children form the skeleton built to animate the player the parent is the pelvis which also has theSkeleton Mesh Renderer component attached to it, which is responsible for rendering the mesh,. The children are the bones of the skeleton which were built in Blender. ArmIK_L, ArmIK_R, LegIK_L, LegIK_R are just handles used in Blender and have no function in your app. Now add a Box Collider toplayer\BPlayerSkeleton\Pelvis\Hip\Spine\Shoulder_R\UpperArm_R\LowerArm_R\Hand_R and resize the Collider similar to what is shown below, and set the trigger flag to true.
And thats it for the first part! :] In the next section of this tutorial, youll bring your scene to life with interactivity and animation. That will happen when youre introduced to Scripting. Until next time!
This is a post by Tutorial Team Member Christine Abernathy, an Engineer on the Developer Advocacy team at Facebook. Welcome to the second part of the tutorial series on Beginning Unity 3D for iOS! In the first part of this series, you learned the basics of Unity by building a very simple project and deploying it to an iOS device. Youll want to be sure to go through that part of the tutorial before moving on to this one. Now in this second part, youll add functionality to enrich the project, including better player movement and better game scenery. Youll also learn how to use Unity Remote for debugging. Once again, game on!
A Charact Controller is a Unity com ter mponent that yo can attach to a GameObjec to help create more realistic ou o ct e c movement. You manipul the Character Controller t late through script functions. For examp you can cal a pre-defined SimpleMove function to mo the charact The Simple ple, ll d ove ter. eMove function takes in a V Vector3 input representing th speed with w r he which to perfor the move. T characters movements rm The s automatica account for gravity, allow ally r wing it to move up slopes and down stairs. e d The charac also slides around any ob cter bstacles it finds in its path wit s thout your having to write co to take care of ode e that. To see wha this means, select the Cube GameObject (the player) in the Hierarchy View and at s e n y selectComp ponent\Physic cs\Character C Controller. You see a dialog asking for co ull g onfirmation to r replace the Box x Collider w a Character with rController.
Click Repl lace. You should see a new component in the Inspector for the Character Controller. Yo d e oure going to c create a brand-new script to co ontrol the playe movement so you no lon ers t, nger need to att tach the MoveSimple script t the Heroic C to Cube in this scen ne.
Click on th gear icon to the right of the MoveSimple script compon in the Insp he e e nent pector and sele Remove ect Componen The script should no longe show up in t Inspector. nt. er the
Create a ne JavaScript asset by selecti Assets\Cre ew a ing eate\JavaScript and name it M t MoveAround. D Double-click th he new script to open it in th MonoDevel Editor. Delete the stubbed out functions and add the fo he lop d s ollowing code:
var speed : float = 3.0; d var rotat teSpeed : fl loat = 3.0; function U Update () { var c controller : CharacterC Controller = GetCompon nent(Charact terControlle er); // Rota around y - ax ate xis tran nsform.Rotate(0, Input.Ge etAxis ("Horizon ntal") * rotat teSpeed, 0); // Mov forward / bac ve ckward var f forward : Vect tor3 = transform.Transfo formDirection(Ve ector3.forwa ard); var c curSpeed : float = spee * Input.GetAxis ("Vert f ed tical"); cont troller.Simp pleMove(forward * curSpeed d d); } @script RequireCom mponent(CharacterContro oller)
Save your changes. The last lin in the script specifies that this script can only be attached to a GameO ne Object that has a Character Controller component. The Updat function ge a handle to the Character C te() ets Controller com mponent. It then rotates the tra n ansform around the y-axis base on inputs rep ed presenting left t/right moveme ents. By defaul the left/right movement is controlled by b lt, t both the left/righ arrows and the A/D keys. ht t The Input.G GetAxis() valu ranges from -1 to +1. A ne ue egative value w result in an anti-clockwise rotation and a will n e positive va a clockwis rotation arou the y-axis. alue se und The Simple eMove functio moves the ch on haracter forward or backward depending on the input obt d, tained from Input.GetA Axis(Vertical This input is triggered by e ). s either the up/down arrows or the W/S keys. As with the r . horizontal input, the Inpu ut.GetAxis() va ranges from -1 to +1, and negative and positive value will result in alue d d es n backward a forward movement, respectively. You u a speed mu and m use ultiplier to cont the rotation angle or the m trol n move distance. Attach the new script to your Heroic Cu By now yo should know the drill. y ube. ou w (Hint: If yo dont remem ou mber, its Comp ponents\Script ts\Move Aroun :]) nd. When youre done, you should see the n Move Aro s new ound script com mponent in the players Inspe ector.
Why dont you take your Heroic Cube for a spin using the Unity Editor? Click the Play button and experience your newfound freedom oh, the joy of being able to rotate left and right, and move forwards and backwards! Use the left/right/up/down arrow keys to move around, and also test out the W/A/S/D keys. The player movements are much smoother now, thanks to the Character Controller component and your scripting genius. Give yourself a pat on the back before continuing. :]
When Unit Remote has paired with yo computer, y ty our your iOS devic should be ab to control th game runnin in ce ble he ng the Unity E Editor. The resolution of the d display on the device wont b ideal, but it a great way t quickly prot be s to totype your game. However, you want to oc ull ccasionally buil the project f iOS and lau ld for unch it from Xc code so you ca an properly te game physic under more realistic condi est cs itions. Test the ga on iOS. Yo ame oull find that t theres no way to move the p y player on your device because your e left/right/u up/down inputs do not exist on iOS (howeve you can still control it on y n er, l your Mac). Ne up, youll ext implement some joystick controls to fix this. t k x
Select the i indicated items that relate to j s joystick functi ionality. Click Import. When the import is c n complete, the Project Vie will contain a new folder called Standar Assets (Mob ew n rd bile). You may see a warning in Unity 4 with the y g imported jo oystick script, similar to this (in yellow at th bottom): he
To resolve this, double-click on the war rning. That sho ould open the J Joystick script file. Put your c cursor on the li ine with the warning:
game eObject.active = false; e
Now when you switch ba to the Unity Editor, the w n ack y warning should vanish. Take t that! First add th Dual Joystic prefab to y he cks your scene. A p prefab is a reusa and often customized Ga able ameObject. Yo can ou add a prefa to a scene by either draggi it from the Project View o adding it pro ab y ing or ogrammatically via a script. F y For example, y could build a prefab that represents a pl you d layer and progr rammatically a multiple players to a scen add ne. In your Pro oject View, open the Standar Assets (Mob rd bile)\Prefabs fo older. Drag the Dual Joystick prefab into y e ks your Hierarchy View.
You can se the joysticks by clicking th Game tab to go to the Game View: ee s he o m
Click on the triangle next to the Dual Joysticks GameObject in the Hierarchy View. Notice that the Dual Joysticks GameObject is actually composed of two child GameObjects. A procedure called parenting was used to set up the joystick parent/child GameObject relationship. Parenting is useful if you want to create a composite GameObject that has linked GameObjects. For example, you may want the left and right joysticks to be enabled or disabled at the same time, and its much easier to do this via script if they can be treated as a single object. Select the LeftJoystick GameObject and note that it has the Joystick script component attached to it. Select the RightJoystick GameObject and verify the same. The Joystick script detects touch events on the GUI Texture (the graphic) attached to it and repositions it with certain constraints. For example, the graphics only move inside a given boundary. The script also normalizes the position output so that its within the -1 to +1 range. This allows you to use the joystick in an iOS environment as a substitute for Input.GetAxis(). At this point youve placed the two joysticks in the scene, but theyre not yet connected to your Heroic Cube to drive input. Youll modify the script to assign the right joystick the task of rotating the player, while the left joystick will move the player back and forth. Modify the MoveAround script to handle joystick input. Open the script for editing and add two public variables representing the move and rotate joysticks (at the top where the other variables are):
var moveJoystick : Joystick; var rotateJoystick : Joystick;
Then add a new function that looks at the joystick position and returns an output between -1 and +1. Add it right after the Update() function:
function joyStickInput (joystick : Joystick) { var absJoyPos = Vector2 (Mathf.Abs(joystick.position.x), Mathf.Abs(joystick.position.y)); var xDirection = (joystick.position.x > 0) ? 1 : -1; var yDirection = (joystick.position.y > 0) ? 1 : -1; return ( ( absJoyPos.x > absJoyPos.y) ? absJoyPos.x * xDirection : absJoyPos.y * yDirection); }
The joystick input is a Vector2 input, having x and y components. You use the larger, absolute value of x or y to set the output. You use the direction of the joystick as a multiplier to denote a negative or positive value. This results in an output value between -1 and +1. Modify the Update() function to handle input from the Unity Editor or from an iOS device:
function Update () { var controller : CharacterController = GetComponent(CharacterController); // Rotate around y - axis var rotatePos = Input.GetAxis ("Horizontal") ? Input.GetAxis ("Horizontal") : joyStickInput(rotateJoystick); transform.Rotate(0, rotatePos * rotateSpeed, 0); // Move forward / backward var forward = transform.TransformDirection(Vector3.forward); var movePos = Input.GetAxis ("Vertical") ? Input.GetAxis ("Vertical") : joyStickInput(moveJoystick); var curSpeed = speed * movePos; controller.SimpleMove(forward * curSpeed);
The transfo orms Rotate() function gets i input from eith the left/righ arrow (or A/ keys or from the rotate jo her ht /D) m oystick input. The Character Con ntrollers SimpleMove functio gets input fr on from either the up/down arrow (or W/S) key or w ys from the le joystick inpu eft ut. Save your script changes. Select the pla ayer GameObje (the cube) a note that th Move Aroun script comp ect and he nd ponent has two ne public varia ew ables for Move Joystick and R Rotate Joystick k.
These varia ables are not cu urrently assign With the p ned. player GameOb bject still select drag ted, the LeftJoy ystickGameOb bject to the Move Joystick var riable. Drag th RightJoystic GameObject to the Rotate he ck t Joystickva ariable. (Or inst tead of draggin you can use the selector next to each variable, as indi ng, ed icated before.)
Click Play in Unity Edito Start Unity Remote on you iOS device. or. ur Test the joystick function nality and verif that you can move forward and backward using the left joystick and r fy n d d t rotate left and rig using the rig joystick. A you move th joysticks on your iOS device, you should see the joystic ght ght As he d cks moving in the Unity Edit tor.
Note: The joystick image might appea stretched like you see here. Dont worry, they wont sho up like that on es ar e . ow t the actual d device.
When the i import is comp plete, your Proj View shou have a new Standard Assets\Skyboxes f ject uld folder that cont tains the newly i imported asset t.
Select the M Camera object, then sel Componen Main o lect nt\Rendering\S Skybox.
The new co omponent show up in the In ws nspector. Notice that it has a v variable representing the material. This is w where the skybox material you imported earlie comes into p x i er play. Click on th little circular icon next to t Custom Sky he the ybox variable. The Select Ma aterial dialog s should pop up l listing any material assets that are available fo your project use. a or s
Click on th Sunny2 Sky he ybox material, t then close the Select Materia dialog. The C al Custom Skybox material shou x uld now have t Sunny2 Skybox material assigned to it. the
Your Scen View will no magically c ne ow change to display the sunny sk youve just added. You ca click on the ky an Game tab t view the sky in the Game V to y View, or click the Play button n.
The sun ha come out! And even thoug it may appea overcast, tha encouragem to add som green life to your as A gh ar ats ment me o world.
Click Impo to import al the selection The Terrain Assets should show up unde your Standar Assetsfolder ort ll ns. d er rd r. You can us the imported assets to mod the behavi of a terrain GameObject. se d dify ior Select Terr rain\Create Te errain to add a terrain GameO Object to your scene. Select t terrain obje and change its the ect transform p position to -1000,0,-1000 usi the Inspecto This stretch the terrain o far enough to give your p ing or. hes out h player room to mo ove.
The Terrai (Script) sect in tion contains to that you can use to dress up your terrai ools s in:
Select the P Paint tool to br ring up the bru ushes you can w work with:
Youll be p painting your terrain with gra Click Edit Textures\Add Texture: ass.
In the Add Terrain Textu dialog, click Select in the Texture area, s d ure k select the Grass (Hill) texture, close the Select s e l Texture2D pop up, then click Add: D c
Click aroun in your scen to paint the grass. To chec out your artw nd ne ck work, click on the Game tab:
If only land dscaping could always be so easy! d Switch bac to the Scene View now y ck e youre going to plant some pa trees! Sele the Place Tr o alm ect Trees tool in the Terrain (Script) secti n ion:
In the Add Tree dialog, click the circular icon next to the Tree entry select the Palm GameObject, then click Add: d c a y, l c
Start addin trees to your scene by click ng r king where you want the tree to be. Hint: Z u es Zoom into the scene and pan around as y place the trees. Try adjus you t sting the Point light range and height to see more of the sc d cene as you add d trees.
When done your scene should look som e, s mething like th his:
Wow, thats much better! Its starting to look like a re world down there. But you terrains stil looking a bit flat, o eal n ur ll t isnt it? You can ea asily add some height variatio to your terra In the Terr e on ain. rain (Script) se ection, select th leftmost too to he ol raise and lo ower the terrain height: n
Set the Bru Size to 20, then in the Sce View, click on two to thr spots aroun the player (n too near, th ush ene k ree nd not hough) to vary the terrain height. e
Preview th game and mo around the scene. Tweak the number of trees in the sc he ove e k f cene as you see fit but remem e mber to stop the game before making any cha m anges you wish to keep. h
Save your scene. Test your p project using Unity Remote a when satisf U and fied, build it as an Xcode pro s oject. Select Fil le\Build Settings an in the Build Settings dialog, click Add C nd Current to add t Level_2 sc the cene. The new s scene will show up w in the Scen In Build lis Deselect the Level_1 scene to build only Level_2. nes st. e e
Click Build choose to replace the previ d, ious project if asked and then launch the Xc n code project. D Deploy and test on t your iOS d device.
Not bad, eh Imagine how long it would have taken to do all this wi raw OpenG ;] h? w o ith GL
This is a po by Tutorial Team Membe Christine Abernathy, an En ost l er ngineer on the Developer Adv vocacy team at Faceboo ok. Welcome t the third and final part the Beginning Un 3D for iOS tutorial series! to d nity In the first part of this ser ries, you toured the basic Uni tools, create a game with a simple play control d ity ed h yer mechanism and learned how to deploy your project on iOS. m h n Then in the second part of the series, yo enhanced th movement o your Heroic Cube and brou e o ou he of ught some life t the to world it oc ccupies with sk grass, trees and a variable terrain. ky, In this third and final par youll add ga d rt, ameplay to the project. Instea of simply m e ad moving around t scene, your the r Heroic Cub will have to dash (as cubes do) to a finish line within a certain amoun of time. be o nt To give the player a chall e lenge, obstacle will rain dow on the Cube as it zigs and zags its way to that finish lin A es wn e d ne. countdown timer will add to the drama. Success will b greeted with cheers failu with the deafening silence of n d . be h ure e defeat. :] Youre alm to the finis line too, so remember its hip to be squ most sh uare!
To create t first post, se the elect GameObj ject\Create Ot ther\Cylinder. Rename it to P Post1. Set the T Transform Scal to le 1,3,1. Set t Transform Position to -10 the 0,0,20 to put it in front of the player and to t left. Using the Move Too the ol, adjust the y position so th the bottom of the cylinder object is just a little below t ground. hat r the Hint: View the scene fro the z-axis to help you mak the adjustme w om o ke ents.
Drag the P Post1 GameObj and place i under the Fin Line Gam ject it nish meObject to set the latter as th parent for P t he Post1.
To create a second post, select Post1, ri s ight-click and s select Copy. R Right-click once more and sele Paste. Rena e ect ame the new Ga ameObject from Post1 to Pos Using the M m st2. Move Tool, ad djust the x position so that the post is to the right e of the play yer. Hint: View the scene fro the y-axis (f w om from above) to help you mak adjustments. Alternatively, setting the o ke , Transform x position to 10 should do th trick. 1 he
Next, creat the wall that helps you dete when the fi te t ect inish line is cro ossed. Select G GameObject\Cr reate Other\Cub and rename it to Goal. Set the Transform Scale to 24,10 be m 0,0.5. Set the in nitial Transform Position to 0 m 0,2,0.
Move the w to just beh wall hind the two po osts. If you nee to, adjust the x scale value so the wall str ed e e retches from on ne post to the other.
With the w still selecte open the In wall ed, nspector\Box C Collider compo onent and check the Is Trigge value. Unche k er eck the Mesh R Renderer comp ponent to make the wall invis e sible.
Drag the G Goal GameObje and place it under the Fin Line Gam ect t nish meObject to par the object. rent
The LineRenderer class allows you to draw lines in 3D space. Given an array of points, you can use the Line Renderer component (Components\Effects\Line Renderer) to draw straight lines. You could have added the Line Renderer component to the Finish Line object and hard-coded the transform positions for Post1 and Post2, but its easier to create the Line Renderer through code. Thats what youre doing here. You draw the line in the Start() function, as it only needs to happen once. First you add the LineRendererscript interface component, then you set the first and second points for the line to the values from the variable inputs that will be tied to the two posts. You set the material for the renderer. Finally, you set the color for the start and end of the line. The line color variable is made public so you can change it. Attach the FinishLineRender script component to the Finish Line GameObject. Hint: You can add the script to the GameObject by selecting the Finish Line object and then tapping the Add Component button in the Inspector. This should bring up a search box simply type the first few letters of the word FinishLineRender and it should show you the script.
Assign the Post1 and Pos GameObjec to the Post 1 and Post 2 v st2 cts variables, respe ectively.
Preview th game in the Unity Editor. Y should see two goal post and a green l across them indicating th he U You e ts line m he finish line. Stop the game e.
Next youl create a new script that dete the finish l crossing event, and will attach this new script to ll ects line w the Goal G GameObject. To do this, selec Assets\Creat o ct te\JavaScript a name the scriptFinishLin and neDetection. Open the n script and delete the stub new bbed out functio Add the fo ons. ollowing code: :
function O OnTriggerEnt ter(other : C Collider) {
You call the OnTriggerEnter() function whenever another collider enters the GameObject. The GameObject needs to be set up as a trigger for the event to fire (which youve already done for the Goal object). The player GameObject has a Character Controller component that is a Collider. So when the player runs into the Goal GameObject, the OnTriggerEnter() event is fired. In your code, you check if the GameObject that entered the Goal has a tag named Player. If thats the case, the Heroic Cube has crossed the finish line. Attach the FinishLineDetection script to the Goal GameObject. Hint: With the Goal object selected in the Hierarchy View, you can drag the FinishLineDetectionscript from the Project View to the Inspector\Add Component button to attach the script component to the GameObject. Before you tag the player, give the player GameObject a name other than plain old cube. To keep things consistent, rename the Cube GameObject to Player.
Now, add a tag to the player object to enable the finish line detection logic. In the Inspector for the player, drop down the Tag selection and choose Player.
Player is on of the pre-b ne built tags availa able. Later on, youll create y your own tags t help identify all enemies in the to y n game. Click Play and move the Heroic Cube p the goal lin You should see a You m past ne. d made it!!! log m message letting you g know that the player cros ssed the finish line.
Yes, the Heroic Cube can get to the goa line and win the game, but you cant let it off so easy. Y n al Youll add two levels of co omplexity to th game: a time he e-based challen and obstac nge cles. First, lets add the obstac s cles.
The main r reason for the launchers exis l stence is to laun obstacles, so you need to give it some t launch! nch o to Ammunitio is typically created in Uni by designing GameObject and then crea on ity g ts ating Prefabs th can be hat instantiated in the scene, as required, du d uring gameplay Youll create an Obstacle G y. e GameObject, t turn it into a Pr refab, and then le the Launcher take care of la et r aunching it ont the hapless p to player.
Select the O Obstacle GameObject. Chang the render m ge material by mo odifying the Ins spector\Mesh Renderer\M Materials\Elem ment 0 propert Click on the circular icon n to the pro ty. e next operty to bring up the Select Material di ialog.
Select the constructor_done material yo just imported. Close the Se o ou e elect Material dialog.
Now you must tag the Obstacle GameObject so that later on you can take care of clearing out Obstacleinstances of the scene when a new game is started. For this, create a new tag named Enemy. Click on Inspector\Tag\Add Tag. The TagManager will show up in the right side panel. Expand the Tags array by clicking on the triangle next to the Tags label). Set the value of Element 0 to Enemy.
Select the Obstacle GameObject and tag the object with the new Enemy tag.
When Obstacle is instantiated, the code youll add will expect a Rigidbody component to be attached to the obstacle. Set that up by adding a Rigidbody. Select Component\Physics\Rigidbody (with Obstacle still selected):
Click on the Assets folder in the Project View. Create a Prefab of your obstacle by selectingAssets\Create\Prefab. The Project View should show an empty Prefab. Name it Obstacle.
Note: If you have larger asset icons than in the screenshot above and wonder how you can get the list view of asset items, simply slide the slider below the asset list all the way to the left. :] Drag the Obstacle GameObject into this new Prefab.
The Prefab changes to a blue color to indicate that it has been assigned. Now that youve created the Prefab as a reusable asset, you no longer need it in the scene. The launcher will take care of instantiating an Obstacle instance when needed. In the Hierarchy View, select theObstacle GameObject, right-click and select Delete.
private var nextLaunch : float = 0.0; private var numObstaclesLaunched = 0; function Start () {
if (target == null) { // Find the player transform target = GameObject.FindGameObjectWithTag("Player").transform; } } function Update () { if ((numObstaclesLaunched < maxObstacles) && (Time.time > nextLaunch)) { // Set up the next launch time nextLaunch = Time.time + launchInterval; // Set up for launch direction var hit : RaycastHit; var ray : Ray; var hitDistance : float;
// Instantiate the projectile var instantiatedProjectile : Rigidbody = Instantiate(projectile, transform.position, transform.rota // Simple block, try to get in front of the player instantiatedProjectile.velocity = target.TransformDirection(Vector3.forward * speed); // Increment the launch count numObstaclesLaunched++; } }
The launcher is programmed to launch a certain number of obstacles just in front of the player. It therefore needs an input that represents the player. Previously, when assigning GameObjects to script, youve done so by dragging the GameObject to the script variable using the Editor. The Start() function code shows another way to do this. In Start(), a check is made to see if there is no target assigned. If no target is found, the code looks for a GameObject with the Player tag and assigns this GameObject to the target variable. The GameObject.FindGameObjectWithTag() function call is typically an expensive call, as it needs to look through all GameObjects. So youll want to call this in Start() (which gets called once) and avoid putting it in, say, Update() (which gets called multiple times). In the code, Update() first checks if the Launcher has sent out the maximum obstacles allowed. If not, it also checks if a set time interval has passed. This is to avoid launching too many obstacles within a short amount of time. If its time to launch another obstacle, then the Obstacle Prefab is instantiated at the position and rotation corresponding to the Launcher. The instantiated obstacle is then launched in a direction that matches the players forward direction, so as to land just in front of the player. Now save your code and tie up loose ends. First, attach the ObstacleLauncher script to the LauncherGameObject. Assign the Obstacle Prefab to the projectile variable in the script (you can drag the Prefab from the Assets list to the variable). Assign the Player GameObject to the target variable in the script.
Play the ga in the Unit Editor and v ame ty verify that the b blocks are laun nched in front o the Heroic C of Cube as it move es around. Ad djust the launch hers position s that the bloc are launche in between t player and the finish line. You so cks ed the . can also ad djust the finish line by movin the Finish L ng Line GameObje in the z dire ect ection, away fr rom the player. . Hint: You can set the Tra ansform Position to 0,0,2. When you move the Finish Lin object, the c ne child objects co ome along for th ride, which is one perk of parenting or g he f grouping related GameObject d ts.
You have m of the gam functionalit working now Next youll pull everythin together with a mission con most me ty w. ng h ntrol script that displays the ga timer, coordinates the ga ame ameplay and re esets the scene to start a new g game.
var gameTimeAllowed : float = 20.0; private private private private var var var var gameMessageLabel = ""; gameMessageDisplay : Rect; timedOut : boolean = false; gameTimeRemaining : float = gameTimeAllowed;
function Awake() { gameMessageDisplay = Rect(10, 10, Screen.width - 20, 40); } function OnGUI() { GUI.color = Color.yellow; GUI.backgroundColor = Color.black;
var text : String = ""; if (timedOut) { gameMessageLabel = "Time's up!!"; } else { text = String.Format( "{0:00}:{1:00}", parseInt( gameTimeRemaining / 60.0 ), parseInt( gameTimeRemaini gameMessageLabel = "Time left: " + text; } GUI.Box(gameMessageDisplay, gameMessageLabel); } function Update() { if (!gameRunning) return; // Keep track of time and display a countdown gameTimeRemaining -= Time.deltaTime; if (gameTimeRemaining <= 0) { timedOut = true; gameRunning = false; } }
Unity provides GUI controls that make it easy to add text labels and button functionality. ThegameMessageDisplay variable controls where the display is shown. Here you set up the countdown timer to display across the top of the screen. OnGUI() is called when an event occurs such as a mouse click, or at least once a frame. GUI.Box() creates a Box Control using the dimensions you set up initially and with the current game message, which consists of the countdown time info, a success message or a failure message. The gameTimeAllowed variable represents the game timer and is set to 20 seconds. ThegameTimeRemaining variable tracks the currently remaining time. It is initially set to thegameTimeAllowed value and is decremented by Time.deltaTime in Update(). Time.deltaTime is the time in seconds that the last frame took to complete. Keep in mind that the frame rate may vary and so this value may also vary. When the gameTimeRemaining value is below zero, thetimedOut flag is set to true and the player is shown a timeout message. The code also sets up a gameRunning flag to track if you guessed it the game is running. This is useful to stop the countdown logic and youll use it later on to control object behavior when the game is not running.
Play the game and dawdle around until time runs out in order to test the countdown display and the failure case. Its a little hard to see, but dont worry, youll change that soon. Stop the game.
private var missionCompleted : boolean = false; private var missionCompleteTime : float = gameTimeAllowed;
Then add the following code to the end of the GameController script:
function MissionComplete() { if (!gameRunning) return; missionCompleted = true; gameRunning = false; missionCompleteTime = } gameTimeAllowed - gameTimeRemaining;
MissionComplete() checks if the game is running. If it is, it sets a private missionCompleted flag to true and the gameRunning flag to false. The time it took to complete the mission is then saved. Now modify OnGUI() and add the success case (as shown below) to show the time it took to complete the message. The new code goes just after the var text : String = ; line and alters the existing if condition:
if (missionCompleted) { text = String.Format( "{0:00}:{1:00}", parseInt( missionCompleteTime / 60.0 ), parseInt( missionComple gameMessageLabel = "Mission completed in: " + text; } else if (timedOut) { gameMessageLabel = "Time's up!!"; ...
Switch to the FinishLineDetection script and modify it as follows (the additions are marked with comments):
#pragma strict var gameControllerScript : GameController; // 1: new function OnTriggerEnter(other : Collider) { if (other.gameObject.tag == "Player") { Debug.Log("You made it!!!"); gameControllerScript.MissionComplete(); // 2: new } } @script RequireComponent(Collider)
The new code is numbered and does the following: 1. 2. Defines a public variable that points to the GameController script. Youll assign this shortly. Calls MissionComplete() in the GameController script to trigger the success case.
To assign the gameControllerScript variable, select the Goal GameObject, then select Inspector\Finish Line Detection and click the circular icon next to the Game Controller Script. In the pop-up dialog, select the Main Camera GameObject and close the dialog.
Play the ga and dash to the finish lin dodging tho nefarious blocks. Check that the correct message is ame t ne, ose h displayed w when you mak it in time. ke
Stop the game and click Play once more. Test the failure case to make sure that that logic still works.
Youve just imported your custom font and its ready for use in your project. Open the GameController script to modify the message font. Define a public variable to set the font:
var gameMessageFont : Font;
Change the font used for display labels by modifying OnGUI(), as shown below:
function OnGUI() { GUI.skin.font = gameMessageFont; GUI.color = Color.yellow; ...
You assign the gameMessageFont public variable to GUI.skin.font to change the font. Now select the Main Camera GameObject. Assign gameMessageFont to your newly imported font by dragging the font asset into the gameMessageFont variable.
Preview the game and verify that the messages are displayed using the new font.
Then add a new function called startGame() that sets up a new game:
function startGame() { // Reset if starting a new game gameTimeRemaining = gameTimeAllowed; timedOut = false; missionCompleted = false; // Change button text after the initial run playButtonText = "Play Again"; // Kick off the game gameRunning = true; }
Now modify OnGUI() to show the button when the game is not running by adding the following code to the end of OnGUI() (after all the existing code):
// The menu button if (!gameRunning) { var xPos = Screen.width / 2 - 100; var yPos = Screen.height / 2 + 100; if( GUI.Button( new Rect( xPos, yPos, 200, 50 ), playButtonText ) ) { startGame(); } }
Finally, set the gameRunning flag to false. Just modify the existing line for the variable to switch the initial value from true to false:
static var gameRunning : boolean = false;
OnGUI() places a button using the GUI.Button() function. The button text is a variable, so it says Play initially and Play Again every subsequent time. GUI.Button() is wrapped in an if statement. This returns true if the button is clicked. When the user clicks the button, you kick off the game. startGame() first initializes the game, changes the play button text and finally sets the gameRunning flag to true. Preview the game in the Unity Editor. Verify that the play button is initially visible and is hidden after you click on it. Verify also that when a run is completed, the play button becomes visible once again and that the text has changed from Play to Play Again. Note that each time you click on the play button after the first time, the time is reset and the countdown starts afresh. But also notice that the player can move even before the play button is tapped. Thats a little annoying, isnt it? Dont let your Heroic Cube get a head start!
To take care of that detail, make use of the gameRunning variable, which is a global variable by virtue of the static modifier. Add the following code to the top of Update() in the MoveAround script:
if (GameController != null && !GameController.gameRunning) return;
You should also disable the launcher from dropping obstacles when the game is not running. Add the following code at the top of Update() in the ObstacleLauncher script:
if (GameController != null && !GameController.gameRunning) return;
Preview the game to ensure that when the game is not running, the player cant move and obstacles are not launched.
Then open the ObstacleLauncher script and add this new function:
function resetGame() { // Reset to original data numObstaclesLaunched = 0; }
Next open the GameController script and add the following variable:
var gameObjectsToReset : GameObject [];
The above line defines an array of GameObjects that will have the resetGame function called on them to initiate a reset. Now replace the existing startGame() function with the following (or just update the code to match):
function startGame() { // Reset if starting a new game gameTimeRemaining = gameTimeAllowed; timedOut = false; missionCompleted = false; // Change button text after the initial run playButtonText = "Play Again"; // Clean out any enemy objects var enemies = GameObject.FindGameObjectsWithTag("Enemy"); for (var enemy : GameObject in enemies) { Destroy ( enemy); } // Call all game reset methods for (var gameObjectReceiver : GameObject in gameObjectsToReset) { gameObjectReceiver.SendMessage("resetGame", null, SendMessageOptions.DontRequireReceiver); } // Kick off the game gameRunning = true; }
The new code clears out all enemy instances by looking for GameObjects with the Enemy tag. Destroy() is called on the enemy GameObjects. This clears out the obstacles in the scene. Then the code processes the gameObjectsToReset array and sends a message to each GameObject to callresetGame(). It is not mandatory for a component in the array to have implemented resetGame(). You need to assign the objects to process. Now select the Main Camera object and note the new public variable for Game Objects To Reset:
Set the Size to 2. The array elements will expand. Assign the Player GameObject to Element 0 and theLauncher GameObject to Element 1.
Preview the game and verify that the game fully resets itself after a success or failure. Verify that the player position resets to the original one, that the obstacles are cleared, and that the obstacles start falling once more when the game is restarted.
Preview th game with th Unity Editor and adjust the position of th object so tha its horizonta centered a he he r e he at ally and you can see it clearly. Hint: Youll likely have to play around with the x and z positions: x to center to ob d d bject, and z to zoom in and o out.
Check out the game with Unity Remote as well and m h e make sure the te is visible w ext when viewed on an iOS device. n Make any n necessary adju ustments. Place the D Description Tex object under the Intro Gam ext r meObject. You doing this so you can late show or hide the ure er e menu displ info easily via code. lay
Create a se econd 3D Text GameObject a name it We and elcome Text. T text should appear above the descriptio This d e on text, so set the initial Tran t nsform Positio to -6,5,10. S the Inspecto on Set or\Text Mesh\T Textproperty to Welcome. o Set the Fon property to Transformers Movie by drag nt gging that font asset from the Project View and into the Fo e ont property in the Inspector (or by tapping the circle with a dot icon ne to Font and selecting it fro the pop-up list): n g h ext om
Adjust the position of We elcome Text so that you can see it clearly when you test the game on both the Unity Editor o h o d and throug Unity Remote. gh
Place the Welcome Text object under the Intro GameObject. You want to hide the Intro GameObject (and its child objects) when the game is running. Open theGameController script and make the following changes:
var intro : Transform; ... function startGame() { ... // Turn off the intro text for (var child : Transform in intro ) { child.gameObject.renderer.enabled = false; } // Clean out any enemy objects ...
Here you add a new public variable to get a handle to the Intro GameObject. Then you modify startGame()to make the Intro object invisible by turning off the renderers for its child GameObjects. Now set the Intro variable by selecting Main Camera and dragging the Intro GameObject from the Hierarchy View to the Inspector\Game Controller\Intro variable to assign it. Or use the circle dot icon, since its easier. :]
Preview the game to test that the text is hidden when the play button is clicked and the game begins.
The Resources.zip file you downloaded earlier contains all the audio files that youll be using. Feel free to create your own audio effects instead of using the ones Ive provided. :] For your reference (and for the sake of attribution), the original links to the audio files included in the Resources.zip file are as follows:
Do note though that the files in the Resources.zip file have been renamed for the sake of clarity and brevity. Go to the folder where you originally extracted Resources.zip and import the audio files by dragging them into your Project View\Assets folder.
When an audio file is imported into Unity, you can specify whether it should be compressed or remain as-is, i.e., native. (But note that MP3 and Ogg Vorbis audio are always imported in the compressed format.) Why does this matter? Compressed files tend to be smaller, but they need to be decompressed as the game runs, taking up CPU cycles. You generally want to compress background music. For short sound effects, native is better and tends to provide better sound quality. If the audio format is compressed, you can choose whether to handle the decompression using hardware, e.g., Apples hardware codec if running on an iOS device. Hardware is faster, but the hardware can handle one compressed music file at a time. You can also mark sounds as 3D. This means that when the sound is played, the effect will be relative to the 3D position of the GameObject. For example, if the GameObject is far away, the sound will be quieter.
Select the background audio in the Project View to show the Import Settings. Unselect the 3D Sound option. Select Hardware decoding. Click Apply to save the setting changes. The other audio files are .WAV files and you do not need to modify the default Import settings, which should be set to 3D and native audio format. For sounds to be heard, your scene needs an Audio Listener component to be added to a GameObject. There can only be one Audio Listener in the scene. The listener will pick up sounds from the audio sources close to it and send it to the device speaker. By default, an Audio Listener is attached to the Main Camera. You can leave it there or attach it to a different GameObject: the player, for example. In this game, youll keep the Audio Listener on the Main Camera, but you can experiment with the different options when you build your own games.
Now create a new JavaScript asset that will be used to play either a victory sound or a defeat sound. Name the new script FanReaction. Open the new script, remove the stub functions and add the following code:
var var var var audioVictory : AudioClip; audioDefeat : AudioClip; volumeVictory : float = 2.0; volumeDefeat : float = 2.0;
function playSoundOfVictory(isVictory : boolean) { // Stop any current audio if (audio.isPlaying) audio.Stop(); // Play either the sound of victory or defeat. audio.clip = isVictory ? audioVictory : audioDefeat; audio.volume = isVictory ? volumeVictory : volumeDefeat; audio.Play(); } function resetGame() { // Reset to original state, stop any audio if (audio.isPlaying) audio.Stop(); } @script RequireComponent(AudioSource)
The script takes in two audio clips, one for victory and one for defeat. The playSoundOfVictory() function first stops any audio thats currently playing, then plays the required audio based on the isVictory input. The resetGame() function stops any audio thats playing. Youll shortly wire up the GameController to callresetGame() every time the game is restarted. Attach this new script to the Goal GameObject. Set the victory audio asset to the Audio Victory variable. Set the defeat audio asset to the Audio Defeat variable.
The code defines a new public variable that references the FanReaction script. You modifyMissionComplete() to call playSoundOfVictory(), passing in true to play the victory sound. You also modify Update() to call playSoundOfVictory(), passing in false to play the defeat sound. You can now link the FanReaction script in the Goal GameObject with the variable in the Main CamerasGameController script component. Select Main Camera and then click on the circular icon next to the fanReactionScript variable under the GameController component in the Inspector. In the dialog that pops up, select the Goal GameObject, then close the pop-up.
To call resetGame() in FanReaction, select the Main Camera Object. In the Game Controllercomponent section in the Inspector, increase the Game Objects To Reset array size from 2 to 3. Set theGoal GameObject to Element 2.
Preview the game and test out the victory and defeat scenarios to make sure the game plays the correct sounds. Verify that the sounds are stopped when you hit Play Again.
Thud in 3D
It would also be nice to have some sort of a sound when obstacles hit the ground. To achieve this, youll attach an audio source to the Obstacle Prefab, then detect collisions so you can play the impact audio when the obstacles fall or bump into anything. Add an Audio Source component to the Obstacle Prefab. Assign the impact audio to the Audio Clipproperty.
Create a new JavaScript asset and rename it to ObjectCollision. Edit the script, delete the stubbed functions and add the following code:
var impact : AudioClip; function OnCollisionEnter () { audio.PlayOneShot(impact); } @script RequireComponent(AudioSource)
The code implements the predefined OnCollisionEnter() event function and calls the audio.PlayOneShot()function to play the impact audio clip. audio.PlayOneShot() illustrates another way to play audio, allowing you to pass in the audio you wish to play. Attach the script to the Obstacle Prefab. Set the impact audio asset to the Impact variable in the script.
Preview the game and verify that you hear a pleasing thud sound when obstacles hit the ground or another object. Note that closer the obstacles are to the player, the louder the sounds.
Music does a lot to set the mood for a game. It can get a users adrenaline flowing and help them feel the game environment by providing contextual clues like bird sounds or wolves howling. So add some music! Add an Audio Source component to the Main Camera GameObject. Set the background audio asset to the Audio Clip property. Select the Play on Awake and the Loop options. These ensure that the background music starts as soon as the game starts and that it will play continuously. Adjust the volume property to 0.1 so it doesnt drown out the other sounds. If youre using your own sounds, tweak the volume level depending on your musics default volume level to achieve the same goal. Users should be able to hear all the sound effects while the background music is playing.
Preview the project in the Unity Editor. When completely satisfied, deploy the project to your iOS device. Youll need to add the Level_3 scene in the Build Settings.
Test out the gameplay on your iOs device while you enjoy the sounds youve adde h n i d ed.
Your Hero Cube has a soundtrack to g oic glorify its brav very!