100% found this document useful (1 vote)
1K views184 pages

Unity All Lesson Plans

The document provides instructions for installing Unity software and creating a basic 3D game project in Unity. It outlines downloading and installing Unity Hub, Unity Editor, and Visual Studio. It then guides setting up a new project folder and project, importing vehicle and obstacle assets, positioning a camera, and customizing the Unity interface layout.

Uploaded by

GustavoLadino
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
1K views184 pages

Unity All Lesson Plans

The document provides instructions for installing Unity software and creating a basic 3D game project in Unity. It outlines downloading and installing Unity Hub, Unity Editor, and Visual Studio. It then guides setting up a new project folder and project, importing vehicle and obstacle assets, positioning a camera, and customizing the Unity interface layout.

Uploaded by

GustavoLadino
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 184

 
 
 

0.1​ I​ nstall Unity Software  


 
Example of progress by end of lesson 

Steps: 
Step 1: Download and install Unity Hub 

Step 2: Install a new version of Unity 

Step 3: Sign in or create a new Unity ID 


 

 
 
Length:  20 minutes 

Overview:   If you do not already have Unity installed on your computer, the first thing 
you need to do before you get started on the course is install it. In order to do 
so, if you don’t have one already, you will need to create a Unity ID. When you 
install the software, you will install Unity Hub, which allows you to manage 
your installations and projects, the Unity engine itself, and Visual studio, the 
Integrated Development Environment (or IDE) you will use to code in C#. 

Project  Unity Hub, the Unity Editor, and Visual Studio will all be installed on your 
Outcome:  computer. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Use Unity Hub to install and manage versions of Unity on your computer 
- Create a new Unity ID to be able to access of all Unity’s services 

   

© ​Unity 2019  Lesson 0.1​ - Install Unity Software 



Step 1: Download and install Unity Hub 
In order to most effectively download, install, and manage the versions of Unity on our 
computer, we will use something called Unity Hub. 
1. In a new tab, either Google “Download Unity Hub”  - Warning:​ If you already have a version 
or go to ​https://unity3d.com/get-unity/download​,  of Unity that is version 2018+, you do 
then click to ​Download Unity Hub  not need to complete this lesson 
- Warning:​ Don’t download Unity directly 
2. From your Downloads folder, ​double-click​ on the 
- download U ​ nity​ H
​ ub 
Unity Hub Setup​ file to begin the installation  - Warning:​ Will be different on a Mac vs 
3. Agree to Unity Terms of Service and follow the  a PC - on a Mac, you just have to drag 
instructions to install Unity Hub   the icon into the Applications folder, 
4. Open​ Unity Hub for the first time and click on the  then open it from there 
Projects, Learn, ​and​ Installs​ tabs  - Don’t worry: T ​ here might be old 
projects or other versions in the list 

 
 
 
   

© ​Unity 2019  Lesson 0.1​ - Install Unity Software 



Step 2: Install a new version of Unity 
Now that Unity Hub is installed, we need to actually install a new version of Unity and our code 
editor, Visual Studio 
1. In the ​Installs​ tab click to ​Add​ a new Unity  - Don’t worry:​ This may take a ​very l​ ong time, 
Version  depending on the speed of your computer 
2. Choose either 2 ​ 018.4.1f1​ (if you would like  and internet connection as it has to first 
download​, then ​install​ both Unity and Visual 
your version of Unity to look exactly the 
Studio 
same as the videos) or anything ​higher​ than  - Warning:​ You will likely be asked to provide 
that  your computer’s admin password 
3. Choose to install ​Visual Studio​ (for Mac or  - New Concept: L ​ TS stands for Long-term 
PC)   support, which means Unity will officially 
4. Accept any necessary terms and conditions  support it and keep it up-to-date for 2 years 
and begin installation  - Tip: ​You can continue onto next step of 
creating a Unity ID while it is installing 

 
 
   

© ​Unity 2019  Lesson 0.1​ - Install Unity Software 



Step 3: Sign in or create a new Unity ID 
In order to access a lot of important Unity services, including the Unity Asset Store, we need to 
be signed in with a Unity ID 
1. From the A ​ ccount​ menu in Unity Hub, click to ​Sign in  - New Concept:​ What is a Unity ID? 
2. If you already have an account, ​sign in​ - otherwise,  - Warning: ​If you create a new Unity 
you can sign in quickly through G​ oogle​ or ​Facebook  ID, you will be asked to complete a 
questionnaire 
or Create a ​New​ Unity ID  

 
 
 
 
Lesson Recap 
New Progress  ● Unity Hub, Unity Editor 2018+, and Visual Studio installed 
● Signed into Unity Hub  

New Concepts  ● Unity Hub and its features 


and Skills  ● Editor versions, including LTS releases 
● Visual Studio 
● Unity IDs   

Next Lesson  ● We will actually create a new project and open the Unity Editor to start 
creating 

 
 
 

© ​Unity 2019  Lesson 0.1​ - Install Unity Software 


 
 
 

1.1​ S​ tart your 3D Engines 


 
Steps: 
Step 1: Make a course folder and new project  Example of project by end of lesson 
Step 2: Import assets and open Prototype 1 

Step 3: Add your vehicle to the scene 

Step 4: Add an obstacle and reposition it 

Step 5: Locate your camera and run the game 

Step 6: Move the camera behind the vehicle 

Step 7: Customize the interface layout   


 
 
Length:  70 minutes 

Overview:   In this lesson, you will create your very first game project in Unity Hub. You 
will choose and position a vehicle for the player to drive and an obstacle for 
them to hit or avoid. You will also set up a camera for the player to see 
through, giving them a perfect view of the scene. Throughout this process, 
you will learn to navigate the Unity Editor and grow comfortable moving 
around in 3D Space. Lastly, you will customize your own window layout for 
the Unity Editor. 

Project  You will have a vehicle and obstacle positioned on the road and the camera 
Outcome:  set up perfectly behind the vehicle. You will also have a new custom Unity 
layout, perfectly optimized for editing. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Create a new project through Unity Hub 
- Navigate 3D space and the Unity Editor comfortably 
- Add and manipulate objects in the scene to position them where you want 
- Position a camera in an ideal spot for your game 
- Control the layout of Unity Editor to suit your needs 

   

© Unity 2019 Lesson 1.1​ - Start your 3D Engines 



Step 1: Make a course folder and new project 
The first thing we need to do is create a folder that will hold all of our course projects, then create a new 
Unity project inside it for Prototype 1. 
1. On your ​desktop​ (or somewhere else you will remember),  - Don’t worry:​ Unity might 
Right-click > create N ​ ew Folder​, then name it “​Create with Code​”  take a while to open, so 
2. Open ​Unity Hub​ and click ​New   just give it some time 
3. Name the project “​Prototype 1​”, select the correct ​version of 
Unity​, set the location to the new “​Create with Code​” folder, and 
select the 3 ​ D ​template 
4. Click C
​ reate Project​, then wait for Unity to open 

 
 
Step 2: Import assets and open Prototype 1 
Now that we have an empty project open, we need to import the assets for Prototype 1 and open the 
scene 
1. Click on one of the links to access the Prototype 1 starter  - Warning:​ You’re free to look 
files, then ​download a
​ nd​ import ​them into Unity  around, but don’t try moving 
2. In the ​Project ​window, in ​ Assets > Scenes > ​double-click on  yet 
- Warning:​ Be careful playing 
the ​Prototype 1 scene​ to open it  
with this interface, don’t click 
3. Delete the S ​ ample Scene​ without saving  on anything else yet 
4. Right-click + drag​ to look around at the start of the road  - New Concept:​ Project Window 

 
 

© Unity 2019 Lesson 1.1​ - Start your 3D Engines 



Step 3: Add your vehicle to the scene 
Since we’re making a driving simulator, we need to add our own vehicle to the scene. 
1. In the ​Project Window​, open ​Assets > Course Library >  - New:​ Hierarchy 
Vehicles​, then drag a vehicle into the ​Hierarchy   - New:​ ​Undo​ (Cmd/Ctrl + Z) and 
2. Hold​ ​right-click + WASD​ to fly to the vehicle, then try to  Redo​ (Cmd+Shift+Z / Ctrl+Y) 
- Warning:​ Mouse needs to be 
rotate around it 
in scene view for F/focus to 
3. Press F​ in the Scene view to focus on it, then use the s ​ croll  work 
wheel​ to zoom in and out and ​hold the scroll wheel​ to pan  - New Technique:​ Scroll Wheel 
4. Press F to focus on it, ​hold alt+left-click​ to rotate around it  for Zoom and Pan 
perfectly 
5. If anything goes wrong, press ​Ctrl/Cmd+Z ​to Undo until it’s 
fixed 

 
Step 4: Add an obstacle and reposition it 
The next thing our game needs is an obstacle! We need to choose one and position it in front of 
the vehicle. 
1. Go to ​Course Library > Obstacles ​and d ​ rag an obstacle  - New Concept:​ XYZ location, 
directly into ​scene view  rotation and scale 
2. In the Inspector for your obstacle, in the top-right of the  - New Concept:​ Inspector 
Transform component, click the ​Gear Icon >​ Reset Position 
3. In the ​Inspector,​ change the ​XYZ Location​ to ​0,0,25 
4. In the hierarchy, ​Right-click > R
​ ename​ your two objects as 
“​Vehicle​” and “​Obstacle​” 

© Unity 2019 Lesson 1.1​ - Start your 3D Engines 



Step 5: Locate your camera and run the game 
Now that we’ve set up our vehicle and obstacle, let’s try running the game and looking through 
the camera. 
1. Select the ​Camera​ in the hierarchy, then p
​ ress F​ to focus  - New Concept:​ Game View vs 
on it  Scene View 
2. Press the P​ lay button​ to run your Game, then press Play  - New Technique:​ Stop/Play 
(Cmd/Ctrl + P) 
again to ​stop​ it 

 
Step 6: Move the camera behind the vehicle 
In order for the player to properly view our game, we should position and angle the camera in a 
good spot behind the vehicle 
1. Use the ​Move a​ nd​ Rotate tools​ to move the camera behind the  - New Technique: 
vehicle looking down on it  Snapping (Cmd/Ctrl + 
2. Hold Ctrl/Cmd​ to move the camera by whole units  Drag) 
- New Concept:​ Rotation 
on the XYZ Axes 

© Unity 2019 Lesson 1.1​ - Start your 3D Engines 



Step 7: Customize the interface layout 
Last but not least, we need to customize the Unity Editor layout so that it’s perfect for editing 
our project. 
1. In the top-right corner, change the layout from “Default” to “​Tall​”,   - New Concept:​ Layouts 
2. Move G ​ ame view​ beneath Scene view 
3. In the ​Project ​window, click on the little drop-down menu in the 
top-right and choose “​One-column layout” 
4. In the layout Dropdown, ​save a new Layout​ and call it “​My 
Layout​” 

 
 
Lesson Recap 
New  ● Project set up with assets imported 
Functionality  ● Vehicle positioned at the start of the road 
● Obstacle positioned in front of the vehicle 
● Camera positioned behind vehicle 

New Concepts  ● Create a new project 


and Skills  ● Import assets  
● Add objects to the scene 
● Game vs Scene view 
● Project, Hierarchy, Inspector windows 
● Navigate 3D space 
● Move and Rotate tools 
● Customize the layout   

Next Lesson  ● We’ll really make this interactive by writing our first line of code in C# to 
make the vehicle move and have it collide with other objects in the scene 

 
 

© Unity 2019 Lesson 1.1​ - Start your 3D Engines 


 
 
 

1.2 ​Pedal to the Metal 


 
Steps: 
Step 1: Create and apply your first script  Example of project by end of lesson 
Step 2: Add a comment in the Update() method 

Step 3: Give the vehicle a forward motion 

Step 4: Use a Vector3 to move forward 

Step 5: Customize the vehicle’s speed 

Step 6: Add RigidBody components to objects 

Step 7: Duplicate and position the obstacles   


 
 
Length:  70 minutes 

Overview:   In this lesson you will make your driving simulator come alive. First you will 
write your very first lines of code in C#, changing the vehicle’s position and 
allowing it to move forward. Next you will add physics components to your 
objects, allowing them to collide with one another. Lastly, you will learn how 
to duplicate objects in the hierarchy and position them along the road.  

Project  You will have a moving vehicle with its own C# script and a road full of 
Outcome:  objects, all of which may collide with each other using physics components. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Create C# scripts and apply them to objects 
- Use Visual Studio and a few of its basic features 
- Write comments to make your code more readable 
- Utilize fundamental C# methods and classes like transform.Translate and 
Vector3 
- Add Rigidbody and Collider components to allow objects to collide 
realistically  
- Duplicate objects in the hierarchy to populate your scene 

   

© Unity 2019 Lesson 1.2​ - Pedal to the Metal 



Step 1: Create and apply your first script 
We will start this lesson by creating our very first C# script that will control the vehicle’s 
movement. 
1. In the Project window, ​Right-click > Create​ > Folder  - New Concept:​ C# Scripts 
named “​Scripts​”  - Warning:​ Type the script name as 
2. In the “Scripts” folder, ​Right-click > Create >​ ​C#  soon as the script is created, since it 
adds that name to the code. If you 
Script​ n
​ amed “​PlayerController​”  
want to edit the name, just delete it 
3. Drag​ the new script onto the V ​ ehicle object  and make a new script 
4. Click​ on the Vehicle object to make sure it was  - New Concept:​ Components 
added as a ​Component​ in the Inspector 

 
 
Step 2: Add a comment in the Update() method 
In order to make the vehicle move forward, we have to first open our new script and get familiar 
with the development environment. 
1. Double-click​ on the script to open it in ​Visual  - New:​ Start vs Update functions  
Studio  - New:​ Comments 
2. In the ​Update()​ method, add a comment that you 
will: ​// Move the vehicle forward 

​ pdate​()
void​ U
{
​// Move the vehicle forward
}
 

© Unity 2019 Lesson 1.2​ - Pedal to the Metal 



Step 3: Give the vehicle a forward motion 
Now that we have the comment saying what we WILL program - we have to write a line of code 
that will actually move the vehicle forward. 
1. Under your new comment, type ​transform.tr​, then  - New Function:​ transform.Translate  
select ​Translate​ from the autocomplete menu  - New Concept:​ Parameters 
2. Type​ (​, add ​0, 0, 1​ between the parentheses, and  - Warning:​ Don’t use decimals yet. Only 
whole numbers! 
complete the line with a semicolon (​;)​  
3. Press ​Ctrl/Cmd + S​ to save your script, then run 
your game to test it 

void​ ​Update​()
{
​// Move the vehicle forward
​transform.Translate(0, 0, 1);
}
 
Step 4: Use a Vector3 to move forward 
We’ve programmed the vehicle to move along the Z axis, but there’s actually a cleaner way to 
code this. 
1. Delete​ the 0, 0, 1 you typed and use auto-complete  - New Concept:​ Documentation 
to ​replace it​ with ​Vector3.forward   - New Concept:​ Vector3 
- Warning:​ Make sure to save time and 
use Autocomplete! Start typing and VS 
Code will display a popup menu with 
recommended code. 

void​ ​Update​()
{
​// Move the vehicle forward
transform.Translate(​0, 0, 1​ ​Vector3.forward​);
}
 
 
   

© Unity 2019 Lesson 1.2​ - Pedal to the Metal 



Step 5: Customize the vehicle’s speed 
Right now, the speed of the vehicle is out of control! We need to change the code in order to 
adjust this. 
1. Add​ * Time.deltaTime​ and run your game  - New Concept:​ Math symbols in C# 
2. Add ​* 20​ and run your game  - New Function:​ Time.deltaTime 

void​ ​Update​()
{
​// Move the vehicle forward
transform.Translate(Vector3.forward​ * Time.deltaTime * 20​);

 
Step 6: Add RigidBody components to objects 
Right now, the vehicle goes right through the box! If we want it to be more realistic, we need to 
add physics. 
1. Select the ​Vehicle​, then in the hierarchy click ​Add  - New Concept:​ Rigidbody Component 
Component​ and select ​RigidBody  - New Concept:​ Collider Component 
2. Select the ​Obstacle​, then in the hierarchy click ​Add  - Tip:​ Adjust the mass of the vehicle and 
the obstacle, and test the collision 
Component​ and select ​RigidBody 
results 
3. In the RigidBody component properties, increase 
the ​mass​ of vehicle and obstacle to be about what 
they would be in ​kilograms​ and test again 

 
 

© Unity 2019 Lesson 1.2​ - Pedal to the Metal 



Step 7: Duplicate and position the obstacles 
Last but not least, we should duplicate the obstacle and make the road more treacherous for 
the vehicle. 
1. Click and drag your obstacle to the ​bottom of the  - New Technique:​ Duplicate 
list​ in the hierarchy  (Ctrl/Cmd+D) 
2. Press ​Ctrl/Cmd+D​ to duplicate the obstacle and  - Tip:​ Try using top-down view to make 
this easier 
move it down the ​Z axis  
- Tip:​ Try using the inspector to space 
3. Repeat this a few more times to create more  your obstacles exactly 25 apart 
obstacles 
4. After making a few duplicates, select one in the 
hierarchy and ​hold ctrl​ ​+ click ​to select multiple 
obstacles, then ​duplicate​ those 

 
 
Lesson Recap 
New  ● Vehicle moves down the road at a constant speed 
Functionality  ● When the vehicle collides with obstacles, they fly into the air 

New Concepts  ● C# Scripts  


and Skills  ● Start vs Update  
● Comments 
● Methods  
● Pass parameters 
● Time.deltaTime 
● Multiply (*) operator 
● Components  
● Collider and RigidBody  

Next Lesson  ● We’ll add some code to our camera, so that it follows the player as they 
drive along the road. 

 
 

© Unity 2019 Lesson 1.2​ - Pedal to the Metal 


 
 
 

1.3​ H​ igh Speed Chase  


 
Steps:  Example of project by end of lesson 
Step 1: Add a speed variable for your vehicle 

Step 2: Create a new script for the camera 

Step 3: Add an offset to the camera position 

Step 4: Make the offset into a Vector3 variable 

Step 5: Edit the playmode tint color 


   
 
Length:  50 minutes 

Overview:   Keep your eyes on the road! In this lesson you will code a new C# script for 
your camera, which will allow it to follow the vehicle down the road and give 
the player a proper view of the scene. In order to do this, you’ll have to use a 
very important concept in programming: variables​. 

Project  The camera will follow the vehicle down the road through the scene, allowing 
Outcome:  the player to see where it’s going.  

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Declare variables properly and understand that variables can be different 
data types (float, Vector3, GameObject)  
- Initialize/assign variables through code or through the inspector to set 
them with appropriate values 
- Use appropriate access modifiers (public/private) for your variables in 
order to make them easier to change in the inspector 

   

© Unity 2019 Lesson 1.3​ - High Speed Chase 



Step 1: Add a speed variable for your vehicle 
We need an easier way to change the vehicle’s speed and allow it to be accessed from the 
inspector. In order to do so what we need is something called a variable. 
1. In PlayerController.cs, add ​public float ​speed​ =  - New Concept:​ Floats and Integers  
5.0f;​ at the top of the c
​ lass  - New Concept:​ Assigning Variables 
2. Replace the ​speed​ ​value​ in the Translate method  - New Concept:​ Access Modifiers 
with the ​speed​ ​variable​, then test 
3. Save​ the script, then edit the speed value in the 
inspector​ to get the speed you want 

public​ ​float​ speed = 20;

void​ ​Update​()
{
transform.Translate(Vector3.forward * Time.deltaTime *​ ​20​ speed​);

 
Step 2: Create a new script for the camera 
The camera is currently stuck in one position. If we want it to follow the player, we have to 
make a new script for the camera. 
1. Create a new ​C# script​ called F
​ ollowPlayer​ and  - Warning:​ Remember to capitalize your 
attach it to the ​camera  script name correctly and rename it as 
2. Add ​public GameObject player;​ to the top of the  soon as the script is created!  
- Warning:​ It’s really easy to forget to 
script 
assign the player variable in the 
3. Select the ​Main Camera, then​, d ​ rag​ the player  inspector 
object onto the ​empty player variable i​ n the  - Don’t worry:​ The camera will be under 
Inspector  the car... weird! We will fix that soon 
4. In ​Update()​, assign the camera’s position to the 
player’s position, then test 

public​ GameObject player;

void​ ​Update​()
{
​transform.position = player.transform.position;
}
 
   

© Unity 2019 Lesson 1.3​ - High Speed Chase 



Step 3: Add an offset to the camera position 
We need to move the camera’s position above the vehicle so that the player can have a decent 
view of the game. 
1. In the line in the Update method add ​+ new  - New Concept:​ Vector3 in place of 
Vector3(0, 5, -7)​, then test  coordinates  
- Tip:​ You need “new Vector3()” because 
3 numbers in a row could mean 
anything 
- New Concept:​ FixedUpdate  
- Warning:​ Remember to update your 
comments and maintain their 
accuracy! 

public​ GameObject player;

void​ ​Update​()
{
transform.position = player.transform.position ​+ ​new​ Vector3(0, 5, -7)​;

 
Step 4: Make the offset into a Vector3 variable 
We’ve fixed the camera’s position, but we may want to change it later! We need an easier way to 
access the offset. 
1. At the top of F
​ ollowPlayer.cs​, declare ​private  - Don’t worry:​ Pay no mind to the read 
Vector3 offset;   only warning  
2. Copy the ​new Vector3()​ ​code and a​ ssign​ it to that  - Tip:​ Whenever possible, make 
variables! You never want hard values 
variable 
in the middle of your code 
3. Replace​ the original code with the ​offset​ variable 
4. Test​ and s
​ ave 

public​ GameObject player;


private​ Vector3 offset = ​new​ Vector3(0, 5, -7);

void​ ​Update​()
{
transform.position = player.transform.position ​+ ​new​ Vector3(0, 5, -7)
offset​;

   

© Unity 2019 Lesson 1.3​ - High Speed Chase 



Step 5: Edit the playmode tint color 
If we’re going to be creating and editing variables, we need to make sure we don’t accidentally 
try to make changes when in “Play mode” 
1. From the top menu, g ​ o to Edit > Preferences  - Tip:​ Try editing a variable in play mode, 
(​Windows​) or ​Unity > Preferences​ (​Mac​)   then stopping - it will revert 
2. In the left menu, choose ​Colors​, then edit the  - Warning:​ Don’t go crazy with the colors 
or it will be distracting 
“​Playmode tint​” color to have a s ​ light​ color 
3. Play​ your project to test it, then close your 
preferences 

 
 
Lesson Recap 
New  ● Camera follows the vehicle down the road at a set offset distance 
Functionality 

New Concepts  ● Variables  


and Skills  ● Data types  
● Access Modifiers 
● Declare and initialize variables  

Next Lesson  ● In the next lesson, we’ll add our last lines of code to take control of our car 
and be able to drive it around the scene. 
 
 

© Unity 2019 Lesson 1.3​ - High Speed Chase 


 
 
 

1.4​ ​ S​ tep into the Driver’s Seat 


 
Steps:  Example of project by end of lesson 
Step 1: Allow the vehicle to move left/right 

Step 2: Base left/right movement on input 

Step 3: Take control of the vehicle speed 

Step 4: Make vehicle rotate instead of slide 

Step 5: Clean your code and hierarchy 


   
 
Length:  50 minutes 

Overview:   In this lesson, we need to hit the road and gain control of the vehicle. In order 
to do so, we need to detect when the player is pressing the arrow keys, then 
accelerate and turn the vehicle based on that input. Using new methods, 
Vectors, and variables, you will allow the vehicle to move forwards or 
backwards and turn left to right. 

Project  When the player presses the up/down arrows, the vehicle will move forward 
Outcome:  and backward. When the player presses the left/right arrows, the vehicle will 
turn. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Gain user input with Input.GetAxis, allowing the player to move in different 
ways 
- Use the Rotate function to rotate an object around an axis 
- Clean and organize your hierarchy with Empty objects 

   

© Unity 2019 Lesson 1.4​ - Step into the Driver’s Seat 



Step 1: Allow the vehicle to move left/right 
Until now, the vehicle has only been able to move straight forward along the road. We need it to 
be able to move left and right to avoid the obstacles. 
1. At the top of PlayerController.cs, add a ​public float  - New Function:​ Vector3.right  
turnSpeed;​ variable 
2. In ​FixedUpdate()​, add  
transform.Translate(Vector3.right * 
Time.deltaTime * turnSpeed); 
3. Run your game and use the ​turnSpeed​ ​variable 
slider​ to move the vehicle left and right 

public​ ​float​ turnSpeed;

void​ ​Update​()
{
transform.Translate(Vector3.forward * Time.deltaTime * speed);
​transform.Translate(Vector3.right * Time.deltaTime * turnSpeed);

 
Step 2: Base left/right movement on input 
Currently, we can only control the vehicle’s left and right movement in the inspector. We need to 
grant some power to the player and allow them to control that movement for themselves. 
1. In ​PlayerController.cs​, add a new ​public float  - New:​ Input.GetAxis  
horizontalInput​ variable  - Tip:​ Edit > Project Settings > Input and 
2. In ​FixedUpdate​, assign h​ orizontalInput =  expand the Horizontal Axis to show 
everything about it 
Input.GetAxis("Horizontal");​, then test to see it in 
- Warning:​ Spelling is important in string 
inspector  parameters. Make sure you spell and 
3. Add the ​horizontalInput​ variable to your left/right  capitalize “Horizontal” correctly! 
Translate method​ to gain control of the vehicle 
4. In the inspector, edit the t​ urnSpeed​ and s
​ peed 
variables to tweak the feel 

public​ ​float​ horizontalInput;

void​ ​Update​()
{
​horizontalInput = Input.GetAxis(​"Horizontal"​);

​transform.Translate(Vector3.forward * Time.deltaTime * speed);


transform.Translate(Vector3.right * Time.deltaTime * turnSpeed ​* horizontalInput​);
}
 

© Unity 2019 Lesson 1.4​ - Step into the Driver’s Seat 



Step 3: Take control of the vehicle speed 
We’ve allowed the player to control the steering wheel, but we also want them to control the gas 
pedal and brake. 
1. Declare a new public ​forwardInput​ variable  - Tip:​ It can go backwards, too!  
2. In ​FixedUpdate​, assign f​ orwardInput =  - Warning:​ This is slightly confusing with 
Input.GetAxis("Vertical");  forwardInput and vertical axis 
3. Add the ​forwardInput​ variable to the ​forward 
Translate method​, then test  

​ loat​ horizontalInput;
public​ f
public​ f​ loat​ forwardInput;

void​ ​Update​()
{
horizontalInput = Input.GetAxis(​"Horizontal"​);
​forwardInput = Input.GetAxis(​"Vertical"​);

transform.Translate(Vector3.forward * Time.deltaTime * speed ​* forwardInput​);


transform.Translate(Vector3.right * Time.deltaTime * turnSpeed * horizontalInput);
}
 
Step 4: Make vehicle rotate instead of slide 
There’s something weird about the vehicle’s movement… it’s slides left to right instead of 
turning. Let’s allow the vehicle to turn like a real car! 
1. In ​FixedUpdate​, call ​transform.Rotate(Vector3.up​,  - New:​ transform.Rotate  
horizontalInput)​, then test   - Tip:​ You can always trust the official 
2. Delete​ the line of code that ​translates Right​, then  Unity scripting API documentation 
test  
3. Add ​* turnSpeed * Time.deltaTime​, then test 

void​ ​Update​()
{
horizontalInput = Input.GetAxis(​"Horizontal"​);
forwardInput = Input.GetAxis(​"Vertical"​);

transform.Translate(Vector3.forward * Time.deltaTime * speed * forwardInput);


​transform.Rotate(Vector3.up, turnSpeed * horizontalInput * Time.deltaTime);
​transform.Translate(Vector3.right * Time.deltaTime * turnSpeed * horizontalInput);
}

   

© Unity 2019 Lesson 1.4​ - Step into the Driver’s Seat 



Step 5: Clean your code and hierarchy 
We added lots of new stuff in this lesson. Before moving on and to be more professional, we 
need to clean our scripts and hierarchy to make them more organized. 
1. In the hierarchy, ​Right-click > Create Empty​ and  - New:​ Empty Object  
rename it “​Obstacles​”, then ​drag​ all the obstacles  - Tip:​ You don’t actually need to type 
into it  “private”, it defaults to that 
- Tip:​ Comments are important, 
2. Initialize​ variables with values in P ​ layerController​, 
especially for your future self 
then make all variables p ​ rivate​ (except for the 
player​ variables) 
3. Use ​//​ to add ​comments​ to each section of code 
 

public​ private​ ​float​ speed ​= 20.0f​;


public​ ​private​ ​float​ turnSpeed ​= 45.0f​;
public​ ​private​ ​float​ horizontalInput;
public​ ​private​ ​float​ forwardInput;

void​ ​Update​() {
horizontalInput = Input.GetAxis(​"Horizontal"​);
forwardInput = Input.GetAxis(​"Vertical"​);
​// Moves the car forward based on vertical input
transform.Translate(Vector3.forward * Time.deltaTime * speed * forwardInput);
​// Rotates the car based on horizontal input
​transform.Rotate(Vector3.up, turnSpeed * horizontalInput * Time.deltaTime);
}

 
Lesson Recap 
New  ● When the player presses the up/down arrows, the vehicle will move forward 
Functionality  and backward 
● When the player presses the left/right arrows, the vehicle turns  

New Concepts  ● Empty objects  


and Skills  ● Get user input 
● Translate vs Rotate 

Next Lesson  ● We made our first project! We learned alot about how unity works, we wrote 
our first lines of code, and we made a driving game where our player has 
full control over this vehicle! 
 

© Unity 2019 Lesson 1.4​ - Step into the Driver’s Seat 


 
 
 

Challenge 1  
Plane Programming  

 
 
Challenge   Use the skills you learned in the driving simulation to fly a plane around 
Overview:   obstacles in the sky. You will have to get the user’s input from the up and 
down arrows in order to control the plane’s pitch up and down. You will also 
have to make the camera follow alongside the plane so you can keep it in 
view.  

Challenge  - The plane moves forward at a constant rate 


Outcome:  - The up/down arrows tilt the nose of the plane up and down 
- The camera follows along beside the plane as it flies 

Challenge  In this challenge, you will reinforce the following skills/concepts: 


Objectives:  - Using the Vector3 class to move and rotate objects along/around an axis 
- Using Time.deltaTime in the Update() method to move objects properly 
- Moving and rotating objects in scene view to position them the way you want 
- Assigning variables in the inspector and initializing them in code 
- Implementing Input variables to control the movement/rotation of objects 
based on User input  

Challenge  - Open​ your P ​ rototype 1 ​project 


Instructions:  - Download​ the "​Challenge​ 1 Starter Files" from the Tutorial Materials section, 
then double-click on it to ​Import 
- In​ the ​Project Window > Assets > Challenge 1 > I​ nstructions​ folder, use the 
Outcome video as a guide to complete the challenge 
 
 
 
 
 
 
   

© Unity 2019 Challenge 1​ - Plane Programming 



 

Challenge  Task  Hint 


1  The plane is going  Make the plane go forward  Vector3.back​ makes an object 
backwards  move backwards, ​Vector3.forward 
makes it go forwards 

2  The plane is going too  Slow the plane down to a  If you multiply a value by 
fast  manageable speed  Time.deltaTime​, it will change it 
from 1x/frame to 1x/second 

3  The plane is tilting  Make the plane tilt only if the  In PlayerControllerX.cs, in Update(), 
automatically   user presses the up/down  the v​ erticalInput​ value is 
arrows  assigned, but it’s never actually used 
in the ​Rotate() ​call 

4  The camera is ​in front  Reposition it so it’s beside  For the camera’s position, try ​X=30,
of ​the plane  the plane  Y=0, Z=10​ and for the camera’s 
rotation, try ​X=0, Y=-90, Z=0 

5  The camera is not  Make the camera follow the  In FollowPlayerX.cs, neither the plane 
following the plane  plane  nor offset variables are assigned a 
value - assign the ​plane​ variable in 
the camera’s inspector and assign 
the​ offset = new Vector3(0,
30, 10)​ in the code 

     
Bonus Challenge  Task  Hint 
X  The plane’s propeller  Create a script that spins the  There is a “Propeller” child object of 
does not spin  plane’s propeller  the plane - you should create a new 
“SpinPropellerX.cs” script and make 
it rotate every frame around the Z 
axis. 
   

© Unity 2019 Challenge 1​ - Plane Programming 



 

Challenge Solution 
1  In PlayerControllerX.cs, in Update, change V
​ ector3.back​ to ​Vector3.forward 

  // move the plane forward at a constant rate


transform.Translate(Vector3​.back​.forward​ * speed);

2  In PlayerControllerX.cs, in Update, add ​* Time.deltaTime t​ o the Translate call 

  // move the plane forward at a constant rate


transform.Translate(Vector3.forward * speed ​* Time.deltaTime​);

3  In PlayerControllerX.cs, include the ​verticalInput​ variable to the Rotate method: 

  // tilt the plane up/down based on up/down arrow keys


transform.Rotate(Vector3.right * rotationSpeed ​* verticalInput​ * Time.deltaTime);
  

4  Change the camera’s position to (30, 0, 10) and its rotation, to (0, -90, 0) 

5  To assign the ​plane​ variable, select ​Main Camera  To assign the ​offset variable, a
​ dd the value 
in the hierarchy, then drag the P​ lane o
​ bject onto  as a new Vector3 at the top of 
the “Plane” variable in the inspector  FollowPlane.cs: 

  private​ Vector3 offset ​= ​new​ Vector3(30,


0, 10)​; 

 
 
 
   
© Unity 2019 Challenge 1​ - Plane Programming 

 

Bonus Challenge Solution 


X1  Create a new Script called “SpinPropellerX.cs” and attach it to the “Propellor” object (which is 
a child object of the Plane): 

X2  In RotatePropellerX.cs, add a new propellorSpeed variable and Rotate the propeller on the Z 
axis 

  private​ ​float​ propellorSpeed = 1000;

void​ ​Update​() {
​transform.Rotate(Vector3.forward, propellorSpeed * Time.deltaTime);
}

 
 

© Unity 2019 Challenge 1​ - Plane Programming 


 
 
 

Unit 1 Lab  
Project Design Document 
 
Steps:  Example of progress by end of lab 
Step 1: Understand what a Personal Project is 

Step 2: Review Design Doc examples 

Step 3: Complete your Project Concept V1 

Step 4: Complete your Project Timeline 

Step 5: Complete your MVP sketch 


   
 
Length:  60 minutes 

Overview:   In this first ever Lab session, you will begin the preliminary work required to 
successfully create a personal project in this course. First, you’ll learn what a 
personal project is, what the goals for it are, and what the potential 
limitations are. Then you will take the time to come up with an idea and 
outline it in detail in your Design Document, including a timeline for when you 
hope to complete certain features. Finally, you will take some time to draw a 
sketch of your project to help you visualize it and share your idea with others. 

Project  The Design Document will be filled out, including the concept, the timeline, 
Outcome:  and a preliminary sketch of the minimum viable product. 

Learning  By the end of this lab, you will be able to: 


Objectives:  - Come up with an idea for a project with a scope appropriate to your time 
and available resources 
- Think through a project’s concept in order to better understand its 
requirements 
- Plan out a project’s milestones with due dates to better understand the 
production cycle and to hold yourself more accountable 
- Create a simple sketch / storyboard in order to better communicate your 
ideas 

   

© Unity 2019 Lab 1 ​- Project Design Document 



Step 1: Understand what a Personal Project is 
Before we get started on our personal projects, we should make sure we understand our 
primary goals. 
Explain  What ​Personal Projects (​ PP’s) are: 
● Projects they will be working on on their own with less direct instruction 
● A chance to create a project they really care about with their own creative choices 
● An opportunity to apply and solidify skills they learned in lessons and challenges 

Demo  The C
​ ore Functionality​ and skills they will learn from each of the 5 Units by showcasing 
completed versions of each Prototype: 
1. Driving Simulation: ​player control t​ hrough user input 
2. Feed the Animals: b ​ asic gameplay​ by spawning random objects on an interval 
and trying to collect them, avoid them, or fire projectiles at them 
3. Run and Jump: ​sound and effects,​ and animation (of background or player) 
4. Sumo Battle: ​gameplay mechanics​, powerups and/or increasing difficulty 
5. Quick Click: ​user interface​ with title screen, game over screen, and score display 

Unit 1  Unit 2  Unit 3  Unit 4  Unit 5 

       

Explain  Goal / Evaluation​ of the PP’s are based on: 


● Completeness​ - how much of what you set out to complete did you actually finish 
● Uniqueness / Application​ - how much did you add new design and dev features, 
extending and applying your skills in novel and creative ways 
NOTE - These two priorities are at odds and it’s up to you to find the balance 

Explain  You just need a ​Minimum Viable Product (an MVP) -​ doesn’t have to be polished 
● Definition: a product with just enough features to satisfy early customers, and to 
provide feedback for future product development 
● This will allow them to focus on the core of the project and not get distracted by 
flashy features and graphics that don’t matter as much 

Warning  There will be a​ temptation to try and do too much​ that is completely different from what 
anything in the course (e.g. “I want to make “Madden + Facebook + Google!”) 
● There’s l​ ots ​of time to try and do really ambitious crazy projects in the future, but 
for now on this first project, try to stick closely to the core functionality you’re 
learning 
● The ​only​ limitation is time - with enough time, they could make anything! 

Discuss  Make sure students understand what the Personal Project is, allowing them to ask 
questions 

© Unity 2019 Lab 1 ​- Project Design Document 



Step 2: Review Design Doc examples 
Now that we have some idea of what a Personal Project is, let’s look a couple examples 
1. Click on the link to open the “​Project Design Doc  - Warning​: y​ ou will need to be signed 
[EXAMPLE]​” and read through the ​Project Concept   into a Google account to be able to 
2. Click on the link to open a new “​Project Design  make a copy of the Google Doc version 
- Tip:​ Search YouTube for “gameplay” of 
Doc” a​ s either a ​Google Doc Copy, Word Doc​ or 
the classic game you want 
PDF  - Explanation:​ Notice that sections 
3. Think through how you would fill out a design doc  correspond to what you’ll be learning 
for other games  with each unit/prototype 

 
 
Step 3: Complete your Project Concept V1 
Now that we’ve seen some examples, let’s try to come up with our own project concept. 
1. Add your ​name​ and d ​ ate​ in  - Explanation:​ In the Course Library, you’ve got human 
the top-right corner  characters, animals, vehicles, foods, sports balls, other 
2. Fill in the blanks​ for your  random things, but you can always use “primitives” as 
project concept   placeholders in a MVP, then go to the Unity Asset store to 
3. Share​ your project concept  get real graphics 
with someone else to make  - Tip:​ This is good opportunity to catch yourself if you’re 
sure it makes sense to them  being too ambitious 
- Don’t worry:​ This is just a best guess right now, if you want 
to change your project completely next lab, you could 

 
 

© Unity 2019 Lab 1 ​- Project Design Document 



Step 4: Complete your Project Timeline 
Now that we know the basic concept of our project, let’s figure out how we’re going to get it 
done. 
1. Fill in​ milestone  - Warning:​ This is a MVP, so don’t be afraid to put objects on backlog 
descriptions​ based  that you’ll get to in version 2  
on your schedule for  - Explanation:​ In Lab 2 you will be setting up your project, in Lab 3 you 
the course, including  will do basic player movement, in Lab 4 you will add basic gameplay, 
self-imposed due  and Lab 5 you will add graphics - that would be a good start in filling 
dates  this out 
2. Add features that  - Tip:​ This will depend heavily on the schedule you’re following for this 
will ​not​ be included  course - you should leave a significant amount of time to work on it 
in your MVP to the  at the end when you’ve completed all 5 units 
“​Backlog​”  - Don’t worry:​ It will be hard to do this accurately, since you don’t 
know how long things take - this can change 
- Don’t worry:​ You don’t need to use all milestones - can add more or 
leave blank rows you are not using 
- Tip: ​These should be worded as “Completed functionality” - as in: 
“Frog can move side-to-side based on left/right arrow keys” 

 
 
   

© Unity 2019 Lab 1 ​- Project Design Document 



Step 5: Complete your MVP sketch 
To help visualize our minimum viable product, it’s always helpful to have a sketch. 
1. Look at sketch in the ​example   - Warning:​ Do not spend forever on this - it’s just a 
2. Using Google Docs, some other online  sketch - use circles, squares, and arrows 
simple drawing program, or pencil and  - Explanation:​ This should just be a sketch of your 
paper, draw a sketch of your MVP and  MVP - what you hope to accomplish by the end 
add it to your doc  of the course - n
​ ot​ the fully fledged product 

 
 
 
Lesson Recap 
New Progress  ● Completed your project concept and production timeline 

New Concepts  ● Personal Projects 


and Skills  ● Design Documents 
● Project Timelines,  
● Project Milestones and Backlogs 
● Minimum Viable Products 
 
 
 

© Unity 2019 Lab 1 ​- Project Design Document 


 
 
 

Quiz ​ ​Unit 1  


 
QUESTION    CHOICES 
 

1  Which Unity window contains a list of all the game    a. Scene view 
objects currently in your scene?  b. Project window 
c. Hierarchy 
    d. Inspector 
 
2  True or False:    a. True 
Visual Studio is not a part of Unity. You could use a  b. False 
different code editor to edit your C# scripts if you 
wanted to. 

   
 
3  What best describes the difference between the below    a. The second car’s X location 
images, where the car is in the second image is further  value is higher than the first 
along the road?  car’s 
b. The second car’s Y location 
value is higher than the first 
car’s 
c. The second car’s Z location 
value is higher than the first 
car’s 
d. The second car’s Transform 
  value is higher than the first 
car’s. 
 
 
4  In what order do you put the words when you are    a. [data type] [access modifier] 
declaring a new variable?   [variable value] [variable name]  
b. [access modifier] [data type] 
  public​ ​float​ speed = 20.0f;  [variable name] [variable value] 
c. [data type] [access modifier] 
[variable name] [variable value] 
d. [variable name] [data type] 

© Unity 2019 Quiz​ - Unit 1 



[access modifier] [variable 
value] 
 
5  Which of the following variables would be visible in the    a. speed 
Inspector?  b. turnSpeed 
c. speed & turnSpeed 
    public​ ​float​ speed; d. horizontalInput & forwardInput 
float​ turnSpeed = 45.0f;
private​ ​float​ horizontalInput;
private​ ​float​ forwardInput; 

 
6  What is a possible value for the horizontalInput variable?    a. -10 
b. 0.52 
  horizontalInput = Input.GetAxis(​"Horizontal"​);  c. “Right” 
d. Vector3.Up 
 
7  What is true about the following two lines of code?    a. They will both move an object 
at the same speed 
  transform.Translate(Vector3.forward); b. They will both move an object 
transform.Translate(1, 0, 0);  in the same direction 
c. They will both move an object 
along the same axis 
d. They will both rotate an object, 
but along different axes 
 
8  Which of the following lines of code is using standard    a. Line A 
Unity naming conventions?`  b. Line B 
c. Line C 
  /* a */​ ​Public Float​ Speed = 40.0f; d. Line D  
/* b */​ ​public​ ​float​ Speed = 40.0f;
/* c */​ ​public​ ​float​ speed = 40.0f;
/* d */​ ​public​ ​float​ speed = 40.0f;

 
9  Which comment would best describe the code below?    a. // Rotates around the Y axis 
based on left/right arrow keys 
  horizontalInput = Input.GetAxis(​"Horizontal"​); b. // Rotates around the Z axis 
transform.Rotate(Vector3.up, horizontalInput);   based on up/down arrow keys 
c. // Rotates in an upward 
direction based on left/right 
© Unity 2019 Quiz​ - Unit 1 

arrow keys 
d. // Moves object up/down 
based on the the left/right 
arrow keys 
 
10  The image below shows the preferences window that    a. The red box 
allows you to change which script editing tool (or IDE)  b. The blue box 
you want to use. Where would you click to choose an  c. The green box 
alternative code editing tool? 

 
 
 

   

© Unity 2019 Quiz​ - Unit 1 


Quiz ​ A​ nswer Key 


 
#    ANSWER  EXPLANATION 
   
1    C  The Hierarchy window contains a list of every GameObject in the current 
Scene. As objects are added and removed in the Scene, they will appear and 
disappear from the Hierarchy as well. 

2    B  True. Visual Studio is just one of many editors you could use to edit your 
code, including editors like Atom, Sublime, or even a basic Text Editor. 

3    C  You can tell which axis the car has moved along using the XYZ directional 
gizmo in the top-right, which shows the blue axis pointing forwards down the 
road. 

4    B  Variables are always declared in the order:  


[access modifier] - public, private, etc  
[data type] - float, int, GameObject, etc  
[variable name] - speed, turnSpeed, player, offset, etc  
[variable value] - 1.0f, 2, new Vector3(0, 1, 0), etc 

5    A  “public float speed” would be visible because it has the “public” modifier 
applied to it 

6    B  Input.GetAxis returns a float value between -1 and 1, which means 0.52 is a 


possible value 

7    A  Vector3.forward is the equivalent of (0, 0, 1), which has the same magnitude 
as (1, 0, 0), even though they’re in different directions, so they would both 
move an object at the same speed, but along different axes 

8    D  “public float speed = 40.0f;” uses the correct naming conventions because all 
three of these terms should start with lowercase letters 

9    A  Vector3.up is the Y axis and it’s using the Horizontal input value, so it would 
rotate around the Y axis when the user presses the left/right arrows 

10    A  You would click on the Red box to change the “External Script Editor” from 
Visual Studio to another tool. 
 

© Unity 2019 Quiz​ - Unit 1 


 
 
 

2.1​ ​ P​ layer Positioning 


 
Steps: 
Example of project by end of lesson 
Step 1: Create a new Project for Prototype 2 

Step 2: Add the Player, Animals, and Food 

Step 3: Get the user’s horizontal input 

Step 4: Move the player left-to-right 

Step 5: Keep the player inbounds 

Step 6: Clean up your code and variables 


 
 
 
Length:  60 minutes 

Overview:   You will begin this unit by creating a new project for your second Prototype 
and getting basic player movement working. You will first choose which 
character you would like, which types of animals you would like to interact 
with, and which food you would like to feed those animals. You will give the 
player basic side-to-side movement just like you did in Prototype 1, but then 
you will use if-then statements to keep the Player in bounds.  

Project  The player will be able to move left and right on the screen based on the 
Outcome:  user’s left and right key presses, but will not be able to leave the play area on 
either side. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Adjust the scale of an object proportionally in order to get it to the size you 
want 
- More comfortably use the GetInput function in order to use user input to 
control an object 
- Create an if-then statement in order to implement basic logic in your 
project, including the use of greater than (>) and less than (<) operators 
- Use comments and automatic formatting in order to make their code more 
clean and readable to other programmers 

   

© Unity 2019 Lesson 2.1​ - Player Positioning 



Step 1: Create a new Project for Prototype 2 
The first thing we need to do is create a new project and import the Prototype 2 starter files. 
1. Open ​Unity Hub​ and create a ​New​ project named  - Don’t worry:​ Unit 2 has far more 
“​Prototype 2​” in your course directory   assets than Unit 1, so the package 
2. Click on the ​link ​to access the Prototype 2 starter  might take a while to import.  
files, then ​import​ them into Unity 
3. Open the P ​ rototype 2 scene​ and ​delete​ the 
SampleScene without saving 
4. In the top-right of the Unity Editor, change your 
Layout from ​Default​ to your custom layout 

 
 
Step 2: Add the Player, Animals, and Food 
Let’s get all of our objects positioned in the scene, including the player, animals, and food. 
1. If you want, drag a different ​material​ from C​ ourse  - New Technique:​ Adjusting Scale  
Library > Materials​ onto the Ground object   - Warning:​ Don’t choose people for 
2. Drag 1 ​Human​, 3 A​ nimals​, and 1 ​Food​ object into  anything but the player, they don’t have 
walking animations 
the Hierarchy 
- Tip:​ Remember, dragging objects into 
3. Rename the human “​Player​”, then ​reposition​ the  the hierarchy puts them at the origin 
animals and food so you can see them 
4. Adjust the XYZ s​ cale​ of the food so you can easily 
see it from above 

 
   
© Unity 2019 Lesson 2.1​ - Player Positioning 

Step 3: Get the user’s horizontal input 
If we want to move the Player left-to-right, we need a variable tracking the user’s input. 
1. In your ​Assets​ folder, create a “​Scripts​” folder, and  - Warning:​ Make sure to create your 
a “​PlayerController​” script inside  Scripts folder inside of the assets 
2. Attach​ the script to the Player and open it  folder  
- Don’t worry:​ We’re going to get VERY 
3. At the top of PlayerController.cs, declare a new 
familiar with this process 
public float horizontalInput   - Warning:​ If you misspell the script 
4. In ​Update()​, set ​horizontalInput =  name, just delete it and try again. 
Input.GetAxis(“Horizontal”)​, then test to make 
sure it works in the inspector  

public​ ​float​ horizontalInput;

void​ ​Update​()
{
​horizontalInput = Input.GetAxis(​"Horizontal"​);

 
 
Step 4: Move the player left-to-right 
We have to actually use the horizontal input to translate the Player left and right. 
1. Declare a new ​public float speed = 10.0f;   - Tip:​ You can look at your old scripts 
2. In ​Update()​, Translate the player side-to-side  for code reference  
based on ​horizontalInput​ and s ​ peed 

​ loat​ horizontalInput;
public​ f
public​ f​ loat​ speed = 10.0f;

void​ ​Update​()
{
horizontalInput = Input.GetAxis(​"Horizontal"​);
​transform.Translate(Vector3.right * horizontalInput * Time.deltaTime * speed);
}

   

© Unity 2019 Lesson 2.1​ - Player Positioning 



Step 5: Keep the player inbounds 
We have to prevent the player from going off the side of the screen with an if-then statement. 
1. In ​Update()​, write an​ if-statement c​ hecking if the  - Tip:​ Move the player in scene view to 
player’s left X position is l​ ess than​ a certain value  determine the x positions of the left 
2. In the if-statement, set the player’s position to its  and right bounds  
- New Concept:​ If-then statements 
current position, but with a ​fixed X location 
- New Concept:​ Greater than > and Less 
Than < operators 
void​ U ​ pdate​() {
​if​ (transform.position.x < -10) {
​transform.position = ​new​ Vector3(-10, transform.position.y, transform.position.z);
​}

 
Step 6: Clean up your code and variables 
We need to make this work on the right side, too, then clean up our code. 
1. Repeat this process for the r​ ight side ​of the  - Warning:​ Whenever you see hardcoded 
screen  values in the body of your code, try to 
2. Declare new x​ Range​ variable, then replace the  replace it with a variable  
- Warning:​ Watch your greater than / 
hardcoded values with them 
less than signs! 
3. Add ​comments​ to your code 

public​ ​float​ xRange = 10;

void​ ​Update​()
{
​// Keep the player in bounds
​if​ (transform.position.x < ​-10​ ​-xRange​)
{
transform.position = ​new​ Vector3(​-10​ ​-xRange​, transform.position.y, transform.position.z);
}
​if​ (transform.position.x > xRange)
​{
​transform.position = ​new​ Vector3(xRange, transform.position.y, transform.position.z);
​}
}
 
   

© Unity 2019 Lesson 2.1​ - Player Positioning 



Lesson Recap 
New  ● The player can move left and right based on the user’s left and right key 
Functionality  presses 
● The player will not be able to leave the play area on either side 

New Concepts  ● Adjust object scale 


and Skills  ● If-statements 
● Greater/Less than operators 

Next Lesson  ● We’ll learn how to create and throw endless amounts of food to feed our 
animals! 
 
 

© Unity 2019 Lesson 2.1​ - Player Positioning 


 
 
 

2.2​ ​ F​ ood Flight 


 
Steps: 
Step 1: Make the projectile fly forwards  Example of project by end of lesson 
Step 2: Make the projectile into a prefab 

Step 3: Test for spacebar press 

Step 4: Launch projectile on spacebar press 

Step 5: Make animals into prefabs 

Step 6: Destroy projectiles offscreen 

Step 7: Destroy animals offscreen   


 
 
Length:  70 minutes 

Overview:   In this lesson, you will allow the player to launch the projectile through the 
scene. First you will write a new script to send the projectile forwards. Next 
you will store the projectile along with all of its scripts and properties using 
an important new concept in Unity called Prefabs. The player will be able to 
launch the projectile prefab with a tap of the spacebar. Finally, you will add 
boundaries to the scene, removing any objects that leave the screen.  

Project  The player will be able to press the Spacebar and launch a projectile prefab 
Outcome:  into the scene, which destroys itself when it leaves the game’s boundaries. 
The animals will also be removed from the scene when they leave the game 
boundaries. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Transform a game object into a prefab that can be used as a template 
- Instantiate Prefabs to spawn them into the scene 
- Override Prefabs to update and save their characteristics 
- Get user input with GetKey and KeyCode to test for specific keyboard 
presses 
- Apply components to multiple objects at once to work as efficiently as 
possible 

   
© Unity 2019 Lesson 2.2​ - Food Flight 

Step 1: Make the projectile fly forwards 
The first thing we must do is give the projectile some forward movement so it can zip across 
the scene when it’s launched by the player. 
1. Create a new “​MoveForward​” script, ​attach​ it to the  - Don’t worry:​ You should all be super 
food object, then open it  familiar with this method now… getting 
2. Declare a new ​public float speed​ variable​;  easier, right? 
3. In ​Update()​, add 
transform.Translate(Vector3.forward * 
Time.deltaTime * speed);​, then ​save 
4. In the ​Inspector​, set the projectile’s ​speed​ variable, 
then test 

public​ ​float​ speed = 40;

void​ ​Update​() {
transform.Translate(Vector3.forward * Time.deltaTime * speed);

 
Step 2: Make the projectile into a prefab 
Now that our projectile has the behavior we want, we need to make it into a prefab it so it can 
be reused anywhere and anytime, with all its behaviors included. 
1. Create a new “​Prefabs​” folder, drag your food into  - New Concept:​ Prefabs  
it, and choose O​ riginal Prefab  - New Concept:​ Original vs Variant 
2. In PlayerController.cs, declare a new ​public  Prefabs 
- Tip:​ Notice that this your projectile 
GameObject projectilePrefab;​ variable 
already has a move script if you drag it 
3. Select​ the Player in the hierarchy, then ​drag​ the  in 
object from your Prefabs folder onto the new 
Prefab Variant box​ in the inspector 
4. Try ​dragging​ the projectile into the scene at 
runtime to make sure they fly 

   

© Unity 2019 Lesson 2.2​ - Food Flight 



Step 3: Test for spacebar press 
Now that we have a projectile prefab assigned to PlayerController.cs, the player needs a way to 
launch it with the space bar. 
1. In PlayerController.cs, in ​Update()​, add an  - Tip:​ Google a solution. Something like 
if-statement​ checking for a spacebar press:  “How to detect key press in Unity”  
if (Input.GetKeyDown(KeyCode.Space)) {  - New Functions:​ Input.GetKeyDown, 
GetKeyUp, GetKey 
2. Inside the if-statement, add a comment saying 
- New Function:​ KeyCode 
that you should ​// Launch a projectile from the 
player   

void​ U ​ pdate​()
{
​if​ (Input.GetKeyDown(KeyCode.Space))
​{
​// Launch a projectile from the player
​}

 
Step 4: Launch projectile on spacebar press 
We’ve created the code that tests if the player presses spacebar, but now we actually need 
spawn a projectile when that happens 
1. Inside the if-statement, use the ​Instantiate  - New Concept:​ Instantiation 
method to spawn a projectile at the player’s 
location with the prefab’s rotation 

if​ (Input.GetKeyDown(KeyCode.Space))
{
​// Launch a projectile from the player
Instantiate(projectilePrefab, transform.position, projectilePrefab.transform.rotation);

   

© Unity 2019 Lesson 2.2​ - Food Flight 



Step 5: Make animals into prefabs 
The projectile is now a prefab, but what about the animals? They need to be prefabs too, so 
they can be instantiated during the game. 
1. Rotate​ all animals on the Y axis by ​180 degrees​ to  - Tip:​ You can change all animals at 
face down  once by selecting all them in the 
2. Select​ all three animals in the hierarchy and ​Add  hierarchy while holding Cmd/Ctrl  
- Tip:​ Adding a Component from 
Component > ​Move Forward  
inspector is same as dragging it on 
3. Edit their ​speed values​ and ​test​ to see how it  - Warning:​ Remember, anything you 
looks  change while the game is playing will 
4. Drag all three animals into the ​Prefabs folder​,  be reverted when you stop it 
choosing “Original Prefab” 
5. Test​ by dragging prefabs into scene view during 
gameplay 

 
 
Step 6: Destroy projectiles offscreen 
Whenever we spawn a projectile, it drifts past the play area into eternity. In order to improve 
game performance, we need to destroy them when they go out of bounds. 
1. Create “​DestroyOutOfBounds​” script and apply it  - Warning:​ Too many objects in the 
to the ​projectile  hierarchy will slow the game  
2. Add a new ​private float topBound ​variable and  - Tip:​ Google “How to destroy 
gameobject in Unity” 
initialize it ​= 30; 
- New Function:​ Destroy 
3. Write code to destroy if out of top bounds ​if  - New Technique:​ Override prefab 
(transform.position.z > topBound) { 
Destroy(gameObject); } 
4. In the Inspector O ​ verrides​ drop-down, click A
​ pply 
all​ to apply it to prefab 

private​ ​float​ topBound = 30;

void​ U ​ pdate​() {
​if​ (transform.position.z > topBound) {
​Destroy(gameObject); }​} 

© Unity 2019 Lesson 2.2​ - Food Flight 



Step 7: Destroy animals offscreen 
If we destroy projectiles that go out of bounds, we should probably do the same for animals. 
We don’t want critters getting lost in the endless abyss of Unity Editor... 
1. Create a new ​private float lowerBound​ variable  - New Function:​ Else-if statement  
and initialize it = -10;  - Warning:​ Don’t make topBound too 
2. Create e ​ lse-if statement​ to check if objects are  tight or you’ll destroy the animals 
before they before they can spawn 
beneath ​lowerBound​: 
else if (transform.position.z > topBound) 
3. Apply​ the script to all of the animals, then 
Override​ the prefabs 

​ loat​ topBound = 30;


private​ f
private​ f​ loat​ lowerBound = -10;

void​ U ​ pdate​() {
​if​ (transform.position.z > topBound)
{
Destroy(gameObject);
} ​else if (transform.position.z < lowerBound) {
​Destroy(gameObject);
​}

 
 
Lesson Recap 
New  ● The player can press the Spacebar to launch a projectile prefab, 
Functionality  ● Projectile and Animals are removed from the scene if they leave the screen 

New Concepts  ● Create Prefabs 


and Skills  ● Override Prefabs 
● Test for Key presses 
● Instantiate objects 
● Destroy objects  
● Else-if statements 

Next Lesson  ● Instead of dropping all these animal prefabs onto the scene, we’ll create a 
herd of animals roaming the plain! 
 
 

© Unity 2019 Lesson 2.2​ - Food Flight 


 
 
 

2.3​ ​ R​ andom Animal Stampede 


 
Steps:  Example of project by end of lesson 
Step 1: Create a spawn manager 

Step 2: Spawn an animal if S is pressed 

Step 3: Spawn random animals from array 

Step 4: Randomize the spawn location 

Step 5: Change the perspective of the camera 


   
 
Length:  50 minutes 

Overview:   Our animal prefabs walk across the screen and get destroyed out of bounds, 
but they don’t actually appear in the game unless we drag them in! In this 
lesson we will allow the animals to spawn on their own, in a random location 
at the top of the screen. In order to do so, we will create a new object and a 
new script to manage the entire spawning process.  

Project  When the user presses the S key, a randomly selected animal will spawn at a 
Outcome:  random position at the top of the screen, walking towards the player. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Create an empty object with a script attached  
- Use arrays to create an accessible list of objects or values 
- Use integer variables to determine an array index 
- Randomly generate values with Random.Range in order to randomize 
objects in arrays and spawn positions 
- Change the camera’s perspective to better suit your game 

   

© Unity 2019 Lesson 2.3​ - Random Animal Stampede 



Step 1: Create a spawn manager 
If we are going to be doing all of this complex spawning of objects, we should have a dedicated 
script to manage the process, as well as an object to attach it to. 
1. In the hierarchy, create an ​empty object​ called “​Spawn  - Tip:​ Empty objects can be 
Manager​”   used to store objects or used 
2. Create a new script called “​SpawnManager​”, attach it to the  to store scripts  
- Warning:​ You can use 
Spawn Manager​, and open it 
spaces when naming your 
3. Declare new p ​ ublic GameObject[ ] animalPrefabs;   empty object, but make sure 
4. In the inspector, change the A​ rray size​ to match your animal  your script name uses 
count, then ​assign​ your animals by ​dragging t​ hem in  PascalCase! 
- New Concept:​ Arrays 

 
 
Step 2: Spawn an animal if S is pressed 
We’ve created an array and assigned our animals to it, but that doesn’t do much good until we 
have a way to spawn them during the game. Let’s create a temporary solution for choosing and 
spawning the animals. 
1. In ​Update()​, write an if-then statement to  - New Concept:​ Array Indexes  
instantiate​ a new animal prefab at the top of the  - Tip:​ Array indexes start at 0 instead of 
screen if ​S i​ s pressed  1. An array of 3 animals would look like 
[0, 1, 2] 
2. Declare a new ​public int animalIndex​ and 
- New Concept:​ Integer Variables 
incorporate it in the I​ nstantiate c
​ all, then test  - Don’t worry:​ We’ll declare a new 
editing the value in the Inspector  variable for the Vector3 and index later 

public​ GameObject[] animalPrefabs;


public​ ​int​ animalIndex;

void​ U ​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.S)) {
​Instantiate(animalPrefabs[animalIndex], ​new​ Vector3(0, 0, 20),
​animalPrefabs[animalIndex].transform.rotation);
​}
}

© Unity 2019 Lesson 2.3​ - Random Animal Stampede 



Step 3: Spawn random animals from array 
We can spawn animals by pressing S, but doing so only spawns an animal at the array index we 
specify. We need to randomize the selection so that S can spawn a random animal based on 
the index, without our specification. 
1. In the if-statement checking if S is pressed,  - Tip:​ Google “how to generate a 
generate a random ​int animalIndex​ between 0 and  random integer in Unity”  
the length of the array  - New Function:​ Random.Range 
- New Function:​ .Length 
2. Remove the global ​animalIndex​ variable, since it is 
- New Concept:​ Global vs Local 
only needed locally in the i​ f-statement   variables 

public​ GameObject[] animalPrefabs;


public​ i
​ nt​ animalIndex;

void​ U ​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.S)) {
​int​ animalIndex = Random.Range(0, animalPrefabs.Length);
Instantiate(animalPrefabs[animalIndex], ​new​ Vector3(0, 0, 20),
animalPrefabs[animalIndex].transform.rotation); }} 
 
Step 4: Randomize the spawn location 
We can press S to spawn random animals from animalIndex, but they all pop up in the same 
place! We need to randomize their spawn position, so they don’t march down the screen in a 
straight line. 
1. Replace​ the X value for the Vector3 with  - Tip:​ Random.Range for floats is 
Random.Range(-20, 20)​, then test  inclusive of all numbers in the range, 
2. Within the ​if-statement​, make a new local V ​ ector3  while Random.Range for integers is 
exclusive!  
spawnPos​ variable  
- Tip:​ Keep using variables to clean your 
3. At the top of the class, create ​private float  code and make it more readable 
variables for ​spawnRangeX​ and s ​ pawnPosZ 

​ loat​ spawnRangeX = 20;


private​ f
private​ f​ loat​ spawnPosZ = 20;

void​ U ​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.S)) {
​// Randomly generate animal index and spawn position
​Vector3 spawnPos =​ ​new​ Vector3​(​Random.Range​(-spawnRangeX, spawnRangeX),
​0, spawnPosZ);
​int​ animalIndex = Random.Range(0, animalPrefabs.Length);
Instantiate(animalPrefabs[animalIndex],​ spawnPos​,
animalPrefabs[animalIndex].transform.rotation); }}

© Unity 2019 Lesson 2.3​ - Random Animal Stampede 



Step 5: Change the perspective of the camera 
Our Spawn Manager is coming along nicely, so let’s take a break and mess with the 
camera.Changing the camera’s perspective might offer a more appropriate view for this 
top-down game. 
1. Toggle between ​Perspective​ and I​ sometric​ view in  - New:​ Orthographic vs Perspective 
Scene view to appreciate the difference  Camera Projection  
2. Select the ​camera​ and change the P​ rojection​ from  - Tip:​ Test the game in both views to 
appreciate the difference 
“Perspective” to “Orthographic” 

 
 
Lesson Recap 
New  ● The player can press the S to spawn an animal 
Functionality  ● Animal selection and spawn location are randomized 
● Camera projection (perspective/orthographic) selected 

New Concepts  ● Spawn Manager 


and Skills  ● Arrays 
● Keycodes 
● Random generation 
● Local vs Global variables 
● Perspective vs Isometric projections 

Next Lesson  ● Using collisions to feed our animals! 


 
 

© Unity 2019 Lesson 2.3​ - Random Animal Stampede 


 
 
 

2.4​ ​ C​ ollision Decisions 


 
Steps:  Example of project by end of lesson 
Step 1: Make a new method to spawn animals 

Step 2: Spawn the animals at timed intervals 

Step 3: Add collider and trigger components 

Step 4: Destroy objects on collision 

Step 5: Trigger a “Game Over” message 


   
 
Length:  50 minutes 

Overview:   Our game is coming along nicely, but there are are some critical things we 
must add before it’s finished. First off, instead of pressing S to spawn the 
animals, we will spawn them on a timer so that they appear every few 
seconds. Next we will add colliders to all of our prefabs and make it so 
launching a projectile into an animal will destroy it. Finally, we will display a 
“Game Over” message if any animals make it past the player. 

Project  The animals will spawn on a timed interval and walk down the screen, 
Outcome:  triggering a “Game Over” message if they make it past the player. If the 
player hits them with a projectile to feed them, they will be destroyed. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Repeat functions on a timer with InvokeRepeating 
- Write custom functions to make your code more readable 
- Edit Box Colliders to fit your objects properly 
- Detect collisions and destroy objects that collide with each other 
- Display messages in the console with Debug Log 

   

© Unity 2019 Lesson 2.4​ - Collision Decisions 



Step 1: Make a new method to spawn animals 
Our Spawn Manager is looking good, but we’re still pressing S to make it work! If we want the 
game to spawn animals automatically, we need to start by writing our very first custom 
function. 
1. In ​SpawnManager.cs​, create a new ​void  - New Concept:​ Custom Void Functions  
SpawnRandomAnimal() {}​ function beneath  - New Concept:​ Compartmentalization / 
Update()  Abstraction 
2. Cut and paste the code from the ​if-then statement 
to the ​new function 
3. Call ​SpawnRandomAnimal();​ if ​S​ is pressed 

void​ U ​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.S)) {
​SpawnRandomAnimal();
​Vector3 spawnpos ​… ​(Cut and Pasted Below)​ }}

void​ ​SpawnRandomAnimal​() {
​Vector3 spawnpos = ​new​ Vector3(Random.Range(-xSpawnRange,
​xSpawnRange), 0, zSpawnPos);
​int​ animalIndex = Random.Range(0, animalPrefabs.Length);
​Instantiate(animalPrefabs[animalIndex], ​new​ Vector3(0, 0, 20) spawnpos,
​animalPrefabs[animalIndex].transform.rotation);​ }
 
Step 2: Spawn the animals at timed intervals 
We’ve stored the spawn code in a custom function, but we’re still pressing S! We need to spawn 
the animals on a timer, so they randomly appear every few seconds. 
1. In ​Start()​, use ​InvokeRepeating​ to spawn the  - Tip:​ Google “Repeating function in 
animals based on an interval, then t​ est​.  Unity”  
2. Remove the​ if-then statement​ that tests for ​S  - New Function:​ InvokeRepeating 
being pressed 
3. Declare new p ​ rivate startDelay​ a
​ nd​ ​spawnInterval 
variables then playtest and tweak variable values 

​ loat​ startDelay = 2;
private​ f
private​ f​ loat​ spawnInterval = 1.5f;

void​ ​Start​() {
​InvokeRepeating(​"​SpawnRandomAnimal​"​, startDelay, spawnInterval);​ }

void​ U​ pdate​() {
if​ (Input.GetKeyDown(KeyCode.S)) {
​SpawnRandomAnimal​(); }​ }
 
© Unity 2019 Lesson 2.4​ - Collision Decisions 

Step 3: Add collider and trigger components 
Animals spawn perfectly and the player can fire projectiles at them, but nothing happens when 
the two collide! If we want the projectiles and animals to be destroyed on collision, we need to 
give them some familiar components - “colliders.” 
1. Double-click on one of the a ​ nimal prefabs​, then  - New Component:​ Box Colliders  
Add Component > Box Collider  - Warning:​ Avoid Box Collider 2D 
2. Click E​ dit Collider​, then ​drag​ the collider handles  - Tip:​ Use isometric view and the 
gizmos to cycle around and edit the 
to encompass the object 
collider with a clear perspective 
3. Check the “​Is Trigger​” checkbox  - Tip:​ For the Trigger to work, at least 
4. Repeat this process for each of the a ​ nimals​ and  one of the objects needs a rigidbody 
the ​projectile  component 
5. Add a ​RigidBody component​ to the projectile and 
uncheck “use gravity”  

 
 
Step 4: Destroy objects on collision 
Now that the animals and the projectile have Box Colliders with triggers, we need to code a new 
script in order to destroy them on impact. 
1. Create a new ​DetectCollisions.cs​ script, add it to  - New Concept:​ Overriding Functions  
each animal prefab, then o ​ pen​ it  - New Function:​ OnTriggerEnter 
2. Before the final }​ ​ add ​OnTriggerEnter​ function  - Tip:​ The “other” in OnTriggerEnter 
refers to the collider of the other object 
using ​autocomplete 
- Tip:​ Use VS’s Auto-Complete feature 
3. In ​OnTriggerEnter​, put ​Destroy(gameObject)​;,​ then  for OnTriggerEnter and any/all override 
test  functions 
4. In ​OnTriggerEnter​, put ​Destroy(other.gameObject); 

void​ ​OnTriggerEnter​(Collider other) {  


​Destroy(gameObject);
​Destroy(other.gameObject); } 
 

© Unity 2019 Lesson 2.4​ - Collision Decisions 



Step 5: Trigger a “Game Over” message 
The player can defend their field against animals for as long as they wish, but we should let 
them know when they’ve lost with a “Game Over” message if any animals get past the player. 
1. In DestroyOutOfBounds.cs, in the ​else-if condition  - New Functions:​ Debug.Log, 
that checks if the animals reach the bottom of the  LogWarning, LogError  
screen, add a Game Over messsage:  - Tip:​ Tweak some values to adjust the 
difficulty of your game. It might too 
Debug.Log(“Game Over!”)  
easy! 
2. Clean up your code with ​comments 
3. If using Visual Studio, Click ​Edit > Advanced > 
Format document​ to fix any indentation issues  
(On a ​Mac​, click ​Edit > Format > Format Document) 

void​ U ​ pdate​() {
​if​ (transform.position.z > topBound)
{
Destroy(gameObject);
} ​else​ ​if​ (transform.position.z < lowerBound)
{
​Debug.Log(​"Game Over!"​);
Destroy(gameObject);
}

 
 
Lesson Recap 
New  ● Animals spawn on a timed interval and walk down the screen  
Functionality  ● When animals get past the player, it triggers a “Game Over” message 
● If a projectile collides with an animal, both objects are removed 

New Concepts  ● Create custom methods/functions 


and Skills  ● InvokeRepeating() to repeat code 
● Colliders and Triggers  
● Override functions 
● Log Debug messages to console 
 
 

© Unity 2019 Lesson 2.4​ - Collision Decisions 


 
 
 

Challenge 2  
Play Fetch   

 
 
Challenge   Use your array and random number generation skills to program this 
Overview:   challenge where balls are randomly falling from the sky and you have to send 
your dog out to catch them before they hit the ground. To complete this 
challenge, you will have to make sure your variables are assigned properly, 
your if-statements are programmed correctly, your collisions are being 
detected perfectly, and that objects are being generated randomly. 

Challenge  - A random ball (of 3) is generated at a random x position above the screen 
Outcome:  - When the user presses spacebar, a dog is spawned and runs to catch the 
ball 
- If the dog collides with the ball, the ball is destroyed 
- If the ball hits the ground, a “Game Over” debug message is displayed 
- The dogs and balls are removed from the scene when they leave the screen 

Challenge  In this challenge, you will reinforce the following skills/concepts: 


Objectives:  - Assigning variables and arrays in the inspector 
- Editing colliders to the appropriate size 
- Testing xyz positions with greater/less than operators in if-else statements 
- Randomly generating values and selecting objects from arrays 

Challenge  - Open​ your P ​ rototype 2 ​project 


Instructions:  - Download​ the "​Challenge​ 2 Starter Files" from the Tutorial Materials section, 
then double-click on it to ​Import 
- In​ the ​Project Window > Assets > Challenge 1 > I​ nstructions​ folder, use the 
"Challenge 2 - Instructions" and “Outcome” video as a guide to complete the 
challenge 
 
   

 

Challenge  Task  Hint 


1  Dogs are spawning at  Make the balls spawn from  Click on the Spawn Manager object 
the top of the screen  the top of the screen  and look at the “Ball Prefabs” array 

2  The player is spawning  Make the player spawn dogs   Click on the Player object and look at 
green balls instead of  the “Dog Prefab” variable 
dogs 

3  The balls are  The balls should only be  Check out the box collider on the dog 
destroyed if anywhere  destroyed when coming into  prefab 
near the dog  direct contact with a dog 

4  Nothing is being  Balls should be destroyed  In the DestroyOutOfBounds script, 


destroyed off screen  when they leave the bottom  double-check the lowerLimit and 
of the screen and dogs  leftLimit variables, the greater than vs 
should be destroyed when  less than signs, and which position 
they leave the left side of the  (x,y,z) is being tested 
screen 

5  Only one type of ball is  Ball 1, 2, and 3 should be  In the SpawnRandomBall() method, 
being spawned   spawned randomly  you should declare a new random i​ nt 
index​ variable, then incorporate that 
variable into the Instantiate call 

     
     
Bonus Challenge  Task  Hint 
X  The spawn interval is  Make the spawn interval a  Set the spawnInterval value to a new 
always the same  random value between 3  random number between 3 and 5 
seconds and 5 seconds  seconds in the SpawnRandomBall 
method 

Y  The player can “spam”  Only allow the player to  Search for ​Time.time​ in the Unity 
the spacebar key  spawn a new dog after a  Scripting API and look at the 
  certain amount of time has  example. And don’t worry if you can’t 
  passed  figure it out - this is a ​very difficult 
  challenge. 
 
 
 
 
 
 

© Unity 2019 Challenge 2​ - Play Fetch 


Challenge Solution 
1  Select the Spawn Manager object and expand the “Ball Prefabs” array, then drag the ​Ball 1, 2, 
3 ​prefabs from ​ Assets > Challenge 2 > Prefabs ​onto E
​ lement 0, 1, 2 

2  Select the Player object and drag the D


​ og ​prefab from ​ Assets > Challenge 2 > Prefabs o
​ nto the 
“Dog Prefab” variable 
 

3  Double-click on the Dog prefab, then in the Box Collider component, click ​Edit Collider​, and 
reduce the collider to be the same size as the dog 

 
 

4  In DestroyOutOfBoundsX.cs, make the leftLimit a negative value, change the greater than to a 
less than when testing the x position, and test the y value instead of the z for the bottom limit 
  ​ loat​ leftLimit = ​-​30;
private​ f
private​ f​ loat​ bottomLimit = -5;

void​ U​ pdate​() {
​if​ (transform.position.x ​> ​ ​<​ leftLimit) {
Destroy(gameObject);
} ​else​ ​if​ (transform.position.​z ​ y​ < bottomLimit) {
Destroy(gameObject);
}
}

© Unity 2019 Challenge 2​ - Play Fetch 



5  In the SpawnRandomBall() method, declare a new random ​int index v​ ariable between 0 and 
the length of the Array, then incorporate that index variable into the the Instantiate call 
  void​ ​SpawnRandomBall​ ()
{
​// Generate random ball index and random spawn position
​int​ index = Random.Range(0, ballPrefabs.Length);
Vector3 spawnPos = ​new​ Vector3(Random.Range(spawnXLeft, spawnXRight), spawnPosY, 0);

​// instantiate ball at random spawn location


Instantiate(ballPrefabs[​0 ​index​], spawnPos, ballPrefabs[​0 i
​ ndex​].transform.rotation);

 
 
   

© Unity 2019 Challenge 2​ - Play Fetch 



 

Bonus Challenge Solution 


X1  In SpawnManagerX.cs, in SpawnRandomBall(), randomly set ​spawnInterval​ using 
Random.Range() 

  void​ ​SpawnRandomBall​ ()
{
​spawnInterval = Random.Range(2, 4);
...
}

Y1  In PlayerControllerX.cs, declare and initialize new fireRate and nextFire variables. Your 
“fireRate” will represent the time the player has to wait in seconds, and the nextFire variable 
will indicate the time (in seconds since the game started) at which the player will be able to 
fire again (starting at 0.0) 

  public​ GameObject dogPrefab;


private​ ​float​ fireRate = 1; ​// time the player has to wait to fire again
private​ ​float​ nextFire = 0; ​// time since start after which player can fire
again

Y2  In the if-statement checking if the player pressed spacebar, add a new condition to check that 
Time.time (the time in seconds since the game started) is ​greater​ than nextFire (which 
represents the time after which the player is allowed to fire. If so, nextFire should be ​reset​ to 
the current time plus the fireRate.  

  // On spacebar press​, if enough time has elapsed since last fire​, send dog
if​ (Input.GetKeyDown(KeyCode.Space) ​&& Time.time > nextFire​)
{
​nextFire = Time.time + fireRate; ​// reset nextFire to current time +
fireRate
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
}
 
 

© Unity 2019 Challenge 2​ - Play Fetch 


 
 
 

Unit 2 Lab  
New Project with Primitives  
 
Steps: 
Example of progress by end of lab 
Step 1: Create a new Unity Project 

Step 2: Create a background plane 

Step 3: Create primitive Player and material 

Step 4: Position camera based on project type 

Step 5: Enemies, obstacles, and projectiles 

Step 6: Export a Unity Package backup file 


 
 
 
Length:  60 minutes 

Overview:   You will create and set up the project that will soon transform into your very 
own Personal Project. For now, you will use “primitive” shapes (such as 
spheres, cubes, and planes) as placeholders for your objects so that you can 
add functionality as efficiently as possible without getting bogged down by 
graphics. To make it clear which object is which, you will also give each 
object a unique colored material.  

Project  All key objects are in the scene as primitive objects with the camera 
Outcome:  positioned properly for your project type. 

Learning  By the end of this lab, you will be able to: 


Objectives:  - Create a simple plane as a background for your project 
- Position the camera, background, and player appropriately depending on 
the type of project you are creating 
- Create primitive shapes to serve as placeholders for your gameobjects  
- Create new colored materials and apply them to distinguish gameobjects 

   

© Unity 2019 Lab 2​ - New Project with Primitives 



Step 1: Create a new Unity Project  
Just like we did with the Prototype, the first thing we need to do is create a new blank project  
1. Open​ U​ nity Hub​ and click ​New   - Tip:​ If there are multiple people with 
2. Name​ the project “[​Your Name] - Personal Project​”,  the same name using the computer, 
select the correct ​version of Unity​, make sure the  might want to add last initial 
- Don’t worry: T ​ here will just be a Main 
location is set to the new “​Create with Code​” 
camera and directional light in there  
folder, and that you are using the ​3D ​template 
3. Click C
​ reate Project​, wait for Unity to open, then 
select your custom L ​ ayout 
4. In the Project window, ​Assets > Scenes​, rename 
“​SampleScene​” to “My Game” 

 
Step 2: Create a background plane 
To orient yourself in the scene and not feel like you’re floating around in mid-air, it’s always 
good to start by adding a background / ground object 
1. In the Hierarchy, ​Right-click > 3D Object > P​ lane​ to add a  - Explanation:​ Working with 
plane to your scene   primitives​ - these are simple 
2. In the Plane’s Inspector, in the top-right of the Transform  objects that allow you to work 
faster 
component, click on the ​Gear icon > Reset  
3. Increase the X​ YZ scale​ of the plane to (​5, 1, 5​) 
4. Adjust your position in Scene view so you have a good 
view of the Plane 

© Unity 2019 Lab 2​ - New Project with Primitives 



Step 3: Create primitive Player and material 
Now that we have the empty plane object set up, we can add the star of the show: the player 
object 
1. In the Hierarchy, ​Right-click > 3D Object > S ​ phere​, ​then  - Tip​: Using primitives doesn’t let 
rename it “​Player​”  graphics distract you and get in 
2. In Assets, ​Right-click > Create > F​ older​ named  the way of core features,  
- Explanation:​ Albedo is a reference 
“​Materials​” 
to astronomical light reflection 
3. Inside “Materials”, ​Right-click > Create > ​Material​ and  properties - but it’s basically just 
rename it “​Blue​”  the material’s color 
4. In Blue’s Inspector, click on the A​ lbedo color ​box and  - Warning:​ Stick with blue right now 
change it to a blue  so it’s easy to follow - you’ll be 
5. Drag​ the material from your Assets onto the Player  replacing it later 
object 

 
 
Step 4: Position camera based on project type 
Now that we have the player in there, we need the best view of it, depending on our type of 
project 
1. For a​ top-down​ game, position the camera at (​0, 10, 0​)  - Tip:​ Side view looks like top 
directly over the player and rotate it 9​ 0​ degrees on the X​   view, but it’ll make a big diff 
axis  when you apply gravity 
2. For a ​side-view​ game, rotate the P​ lane​ by ​-90​ degrees on  - Don’t worry:​ You might not 
the ​X axis  know exact view yet - just go 
3. For a​ third-person​ view game, move the camera up on the  with what’s in your design 
Y and Z axes​ and increase its r​ otation on the X axis  doc 

Top-down view  Side-view  Isometric view 

     

© Unity 2019 Lab 2​ - New Project with Primitives 



Step 5: Enemies, obstacles, and projectiles 
Now that we know how to make primitives, let’s go ahead and make one for each object in our 
project 
1. In the Hierarchy, create new C​ ubes​, S
​ pheres​, and  - Tip:​ If you plan on having variants of 
Capsules​ for all other main objects, r​ enaming  certain objects (e.g. multiple animals), 
them, ​repositioning​ them, and s​ caling​ them  create dark/light shades of the same 
color 
2. In your Materials folder, create ​new materials​ for as 
- Tip:​ Good to make enemies red - easy 
many colors as you have unique objects, editing 
if everyone uses the same 
their color to match their name, then ​apply​ those 
conventions 
materials to your objects 
3. Position all of your objects in locations relative to 
each other that make sense 

 
 
Step 6: Export a Unity Package backup file 
Since we’re going to be putting our hearts and souls into this project, it’s always good to make 
backups 
1. Save​ your Scene  - Explanation:​ The “include dependencies” 
2. In the Project window, Right-click on the  checkbox will include any files that are 
“Assets” folder > ​Export Package​, then click  tied to / used by anything else we’re 
Export  exporting 
3. Create a ​new “​Backups​” folder​ in your Personal  - Tip:​ This is the same file type that you 
Project folder, then s
​ ave​ it with your name and  imported​ at the start of Prototype 1 
the version number (e.g. 
Carl_V0.1.unitypackage”) 

   

© Unity 2019 Lab 2​ - New Project with Primitives 



Lesson Recap 
New Progress  ● New project for your Personal Project 
● Camera positioned and rotated based on project type 
● All key objects in scene with unique materials 

New Concepts  ● Primitives 


and Skills  ● Create new materials 
● Export Unity packages 

 
 
 

© Unity 2019 Lab 2​ - New Project with Primitives 


 
 
 

Quiz ​ ​Unit 2  


 
QUESTION    CHOICES 
 

1  If it says, “​Hello there!​” in the console, what was the    a. Debug(“Hello there!”); 
code used to create that message?  b. Debug.Log("Hello there!"); 
c. Debug.Console(“Hello there!”); 
  d. Debug.Log(Hello there!); 
 
 
2  If you want to destroy an object when its h
​ ealth reaches    a. health > 0 
0​, what code would be best in the blank below?  b. health.0  
c. health < 1 
  private​ ​int​ health = 0; d. health < 0 

void​ U​ pdate​() {
​if​ (__________) {
Destroy(gameObject);
}
}  

 
3  The code below creates an error that says, “error    a. On line 1, change 
CS1503: Argument 1: cannot convert from  “GameObject[]” to 
'UnityEngine.GameObject[]' to 'UnityEngine.Object'”.   “GameObject” 
What could you do to remove the errors?  b. On line 1, change 
“enemyPrefabs” to 
1. public​ GameObject[] enemyPrefabs; “enemyPrefabs[0]” 
2. c. On line 3, change “Start()” to 
3. ​ tart​()
void​ S “Update()” 
4. { d. On line 5, change 
5. Instantiate(enemyPrefabs); “enemyPrefabs” to 
6. }  “enemyPrefabs[0]” 
e. Either A or D 
f. Both A and D 
g. Both B and C 
 
 
 
© Unity 2019 Quiz​ - Unit 2 

 
4  Which comment best describes the following code?    a. // If player collides with 
another object, destroy player 
  public​ ​class​ ​PlayerController​ : ​MonoBehaviour b. // If enemy collides with 
{ another object, destroy the 
​// Comment object 
​private​ ​void​ ​OnTriggerEnter​(Collider other) { c. // If player collides with a 
Destroy(other.gameObject); trigger, destroy trigger 
} d. // If player collides with 
} another object, destroy the 
object 
 
5  If you want to move the character ​up​ c
​ ontinuously​ as    a. GetKey(KeyCode.UpArrow) 
the player presses the u
​ p arrow​, what code would be  b. GetKeyDown(UpArrow) 
best in the two blanks below:  c. GetKeyUp(KeyCode.Up) 
d. GetKeyHeld(Vector3.Up) 
  if​ (Input.__________(__________))
{
transform.Translate(Vector3.up);

 
6  Read the documentation from the Unity Scripting API    a. randomFloat = 100.0f; 
and the code below. Which of the following are possible  randomInt = 0; 
values for the randomFloat and randomInt variables?   b. randomFloat = 100.0f; 
randomInt = 100; 
  c. randomFloat = 50.5f; 
randomInt = 100; 
d. randomFloat = 0.0f; 
randomInt = 50.5; 

 
 
float​ randomFloat = Random.Range(0, 100);
int​ randomInt = Random.Range(0, 100);

© Unity 2019 Quiz​ - Unit 2 



 
7  Your game is running and you see an error in the    a. Line 2 
console that says there was an “error at  b. Line 3 
Assets/Scripts/SpawnManager.cs:5.  c. Line 4 
IndexOutOfRangeException: Index was outside the  d. Line 5 
bounds of the array.” Which line of code needs to be 
edited to fix this? 
1. public​ GameObject[] randomObjects;
2.
3. void​ ​SpawnRandomObject​() {
4. int​ objectIndex = Random.Range(0, 3);
5. Instantiate(randomObjects[objectIndex]);
6. } 

 
8  If you have made changes to a prefab in the scene and    a. The “Create” drop-down at the 
you want to apply those changes to all prefabs, what  top of the Hierarchy 
should you click?  b. The “Open” button at the top of 
the Inspector 
c. The “Override” drop-down at 
the top of the Inspector 
d. The “Add Component” button 
at the bottom of the Inspector 

 
 
9  Read the documentation from the Unity Scripting API    a. InvokeRepeating(“Spawn, 0.5f, 
below. Which of the following is a correct use of the  1.0f”); 
InvokeRepeating method.  b. InvokeRepeating(“Spawn”, 0.5f, 
1.0f); 
  c. InvokeRepeating(“Spawn", 
gameObject, 1.0f); 
d. InvokeRepeating(0.5f, 1.0f, 
 
“Spawn”); 
 
 
 
 
 
 
 

© Unity 2019 Quiz​ - Unit 2 



 
10  You’re trying to create some logic that will tell the user    a. 4, 6, 1, 2, 5, 9, 7, 8, 3 
to speed up if they’re going too slow or to slow down if  b. 6, 1, 2, 5, 7, 8, 3, 4, 9 
they’re going too fast. How should you arrange the lines  c. 7, 8, 3, 4, 6, 5, 2, 1, 9 
of code below to accomplish that?  d. 7, 8, 3, 4, 6, 1, 2, 5, 9 
1. Debug.Log(speedUp); }
2. else if ​(speed > 60) {
3. private string​ speedUp = ​"Speed up!"​;
4. void​ ​Update​() {
5. Debug.Log(slowDown); }
6. if ​(speed < 10) {
7. private​ ​float​ speed;
8. private string​ slowDown = ​"Slow down!"​;
9. }
   

© Unity 2019 Quiz​ - Unit 2 


Quiz ​ A​ nswer Key 


 
#    ANSWER  EXPLANATION 
   
1    B  Debug.Log() prints messages to the console and can accept String 
parameters between quotation marks, such as “Hello there!” 

2    C  Since the “health” variable is an int, anything less than 1 would be “0”. The 
sign for “less than” is “<”.  

3    E  “GameObject[]” is a GameObject array. You cannot instantiate an array, but 


you c
​ an​ instantiate an object inside an array. So you could either remove the 
array and have Instantiate use an individual object (option A) or you could 
use an GameObject index of that Array (option D), but both would not work. 

4    D  Since it’s inside the PlayerController class, and it is destroying 


other​.g
​ ameObject​, it is destroying something that the player collides with. 

5    A  “Input.GetKey” tests for the user holding down a key (as opposed to 
KeyKeyDown, which test for a single press down of a Key).  

6    A  As it says in the documentation, Random.Range does n ​ ot​ include the 


maximum value for integers, but d​ oes​ include the maximum value for floats. 
This means that randomInt c​ annot​ be 100, but randomFloat can be. 

7    C  Line 4, which generates the objectIndex, must be generating an index value 


that is too high for the number of objects in the array. The best thing to do 
would be to change it to “Random.Range(0, randomObjects.Length); 

8    C  The “Override” drop-down will allow you to apply any changes you’ve made to 
your individual prefab to the original prefab object. 

9    B  According to the Scripting API, InvokeRepeating requires a string parameter, 


then two floats. 

10    D  All variables should be declared first, then the void method, then the 
if-condition telling them to speed up, then the else condition telling them to 
slow down. 
 

© Unity 2019 Quiz​ - Unit 2 


 
 
 

3.1​ J​ ump Force 


 
Steps: 
Step 1: Open prototype and change background 

Step 2: Choose and set up a player character  Example of project by end of lesson 
Step 3: Make player jump at start 

Step 4: Make player jump if spacebar pressed 

Step 5: Tweak the jump force and gravity 

Step 6: Prevent player from double-jumping 

Step 7: Make an obstacle and move it left 

Step 8: Create a spawn manager   

Step 9: Spawn obstacles at intervals 


 
 
Length:  90 minutes 

Overview:   The goal of this lesson is to set up the basic gameplay for this prototype. We 
will start by creating a new project and importing the starter files. Next we 
will choose a beautiful background and a character for the player to control, 
and allow that character to jump with a tap of the spacebar. We will also 
choose an obstacle for the player, and create a spawn manager that throws 
them in the player’s path at timed intervals.  

Project  The character, background, and obstacle of your choice will be set up. The 
Outcome:  player will be able to press spacebar and make the character jump, as 
obstacles spawn at the edge of the screen and block the player’s path. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Use GetComponent to manipulate the components of GameObjects 
- Influence physics of game objects with ForceMode.Impulse 
- Tweak the gravity of your project with Physics.gravity 
- Utilize new operators and variables like &&  
- Use Bool variables to control the number of times something can be done 
- Constrain the RigidBody component to halt movement on certain axes 
© Unity 2019 Lesson 3.1​ - Jump Force 

Step 1: Open prototype and change background 
The first thing we need to do is set up a new project, import the starter files, and choose a 
background for the game. 
1. Open ​Unity Hub​ and create a new “​Prototype 3​”  - New Concept:​ Sprites / Sprite 
project in your course directory   Renderer  
2. Click on the ​link​ to access the Prototype 3 starter  - Tip:​ Browse all of the Player and 
Background options before choosing 
files, then ​download and import​ them into Unity 
either - some work better with others 
3. Open the Prototype 3 scene and ​delete​ the ​Sample 
Scene​ without saving 
4. Select the ​Background object​ in the hierarchy, then 
in the ​Sprite Renderer​ ​component > Sprite, s
​ elect 
the​ _City, _Nature, or _Town image 

 
 
Step 2: Choose and set up a player character 
Now that we’ve started the project and chosen a background, we need to set up a character for 
the player to control. 
1. From ​Course Library > Characters​, ​Drag​ a  - Don’t worry:​ We will get the player and 
character into the hierarchy, ​rename​ i​ t​ “Player”,  the background moving soon  
then ​rotate it​ on the Y axis to face to the right  - Warning:​ Keep isTrigger UNCHECKED! 
- Tip:​ Use isometric view and the 
2. Add a ​Rigid Body​ component  
gizmos to cycle around and edit the 
3. Add a ​box collider​, then ​edit​ the collider bounds  collider with a clear perspective 
4. Create a new “​Scripts​” folder in Assets, create a 
“​PlayerController​” script inside, and ​attach​ it to the 
player 

© Unity 2019 Lesson 3.1​ - Jump Force 



Step 3: Make player jump at start 
Until now, we’ve only called methods on the entirety of a gameobject or the transform 
component. If we want more control over the force and gravity of the player, we need to call 
methods on the player’s Rigidbody component, specifically. 
1. In ​PlayerController.cs​, declare a new ​private  - New Function:​ GetComponent  
Rigidbody playerRb;​ variable  - Tip:​ The playerRb variable could apply 
2. In ​Start()​, initialize ​rigidRb =  to anything, which is why we need to 
specify using GetComponent 
GetComponent<Rigidbody>(); 
3. In ​Start()​, use the AddForce method to make the 
player jump at the start of the game  

private​ Rigidbody playerRb;

void​ ​Start​()
{
​playerRb = GetComponent<Rigidbody>();
​playerRb.AddForce(Vector3.up * 1000);

 
 
Step 4: Make player jump if spacebar pressed 
We don’t want the player jumping at start - they should only jump when we tell it to by pressing 
spacebar. 
1. In ​Update()​ add an i​ f-then statement​ checking if  - Warning:​ Don’t worry about the slow 
the spacebar is pressed  jump double jump, or lack of 
2. Cut and paste​ the AddForce code from Start() into  animation, we will fix that later  
- Tip:​ Look at Unity documentation for 
the if-statement 
method overloads here 
3. Add the ​ForceMode.Impulse​ parameter to the  - New Function:​ ForceMode.Impulse 
AddForce​ call, then r​ educe ​force multiplier value  and optional parameters 

void​ ​Start​()
{
​playerRb = GetComponent<Rigidbody>();
​playerRb.AddForce(Vector3.up * 100);
}

void​ U ​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.Space)) {
​ ForceMode.Impulse​); }​ }
​playerRb.AddForce(Vector3.up * 10​0,

   

© Unity 2019 Lesson 3.1​ - Jump Force 



Step 5: Tweak the jump force and gravity 
We need give the player a perfect jump by tweaking the force of the jump, the gravity of the 
scene, and the mass of the character. 
1. Replace​ the hardcoded value with a new p ​ ublic float  - New Function:​ the students about 
jumpForce​ variable  something  
2. Add a new ​public float gravityModifier​ variable and in  - Warning:​ Don’t make 
gravityModifier too high - the player 
Start()​, add ​Physics.gravity *= gravityModifier;  
could get stuck in the ground 
3. In the inspector, tweak the g ​ ravityModifer​,​ jumpForce​,  - New Concept:​ Times-equals 
and ​Rigibody​ mass values to make it fun  operator *= 

private​ Rigidbody playerRb;


public​ ​float​ jumpForce;
public​ ​float​ gravityModifier;

void​ ​Start​() {
playerRb = GetComponent<Rigidbody>();
​Physics.gravity *= gravityModifier;​ }

void​ U​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.Space)) {
playerRb.AddForce(Vector3.up *​ ​10​ jumpForce​, ForceMode.Impulse); } } 
 
Step 6: Prevent player from double-jumping 
The player can spam the spacebar and send the character hurtling into the sky. In order to stop 
this, we need an if-statement that makes sure the player is grounded before they jump. 
1. Add a new​ public bool isOnGround ​variable and  - New Concept:​ Booleans  
set it equal to​ true  - New Concept:​ “And” operator (&&) 
2. In the if-statement making the player jump, set  - New Function:​ OnCollisionEnter 
- Tip:​ When assigning values, use one = 
isOnGround = false​, then ​test 
equal sign. When comparing values, 
3. Add a condition ​&& isOnGround​ to the  use == two equal signs 
if-statement 
4. Add a new ​void onCollisionEnter​ method, set 
isOnGround = true​ in that method, then ​test 

public​ ​bool​ isOnGround = ​true

void​ U ​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.Space)​ && isOnGround​) {
playerRb.AddForce(Vector3.up * 10 jumpForce, ForceMode.Impulse);
​isOnGround = ​false​;​ } }

private​ ​void​ O
​ nCollisionEnter​(Collision collision) {
​isOnGround = ​true​; } 

© Unity 2019 Lesson 3.1​ - Jump Force 



Step 7: Make an obstacle and move it left 
We’ve got the player jumping in the air, but now they need something to jump over. We’re going 
to use some familiar code to instantiate obstacles and throw them in the player’s path. 
1. From ​Course Library > Obstacles​, add an obstacle,  - Warning:​ Be careful choosing your 
rename it “​Obstacle​”, and p​ osition​ it where it  obstacle in regards to the background. 
should spawn  Some obstacles may blend in, making 
it difficult for the player to see what 
2. Apply a ​Rigid Body​ and ​Box Collider​ component, 
they’re jumping over.  
then ​edit​ the collider bounds to fit the obstacle  - Tip:​ Notice that when you drag it into 
3. Create a new “​Prefabs​” folder and drag it in to  hierarchy, it gets placed at the spawn 
create a new ​Original Prefab  location 
4. Create a new “​MoveLeft​” script, ​apply​ it to the 
obstacle, and o ​ pen​ it 
5. In MoveLeft.cs, write the code to T ​ ranslate​ it to 
the left according to the speed variable 
6. Apply the MoveLeft script to the ​Background 

private​ ​float​ speed = 30;

void​ ​Update​() {
​transform.Translate(Vector3.left * Time.deltaTime * speed);

 
Step 8: Create a spawn manager 
Similar to the last project, we need to create an empty object Spawn Manager that will 
instantiate obstacle prefabs. 
1. Create a new “​Spawn Manager​” empty object, then  - Don’t worry:​ We’re just instantiating on 
apply a new ​SpawnManager.cs​ script to it  Start for now, we will have them 
2. In ​SpawnManager.cs​, declare a new ​public  repeating later 
- Tip:​ You’ve done this before! Feel free 
GameObject obstaclePrefab;​, then ​assign​ your 
to reference code from the last project 
prefab to the new variable in the inspector 
3. Declare a new ​private Vector3 spawnPos​ at your 
spawn location 
4. In ​Start()​, ​Instantiate​ a new obstacle prefab, then 
delete​ your prefab from the scene and test 

public​ GameObject obstaclePrefab;


private​ Vector3 spawnPos = ​new​ Vector3(25, 0, 0);

void​ ​Start​() {
​Instantiate(obstaclePrefab, spawnPos, obstaclePrefab.transform.rotation);​ } 

   
© Unity 2019 Lesson 3.1​ - Jump Force 

Step 9: Spawn obstacles at intervals 
Our spawn manager instantiates prefabs on start, but we must write a new function and utilize 
InvokeRepeating if it to spawn obstacles on a timer. Lastly, we must modify the character’s 
RigidBody so it can’t be knocked over. 
1. Create a new ​void SpawnObstacle​ method, then  - New Concept:​ RigidBody constraints 
move the ​Instantiate​ call inside it 
2. Create new ​float variables​ for s​ tartDelay​ ​and 
repeatRate 
3. Have your obstacles spawn on i​ ntervals​ using the 
InvokeRepeating()​ method 
4. In the Player Rigid Body component, expand 
Constraints​, then ​Freeze​ all but the Y position 

​ loat​ startDelay = 2;
private​ f
private​ f​ loat​ repeatRate = 2;

void​ ​Start​() {
​InvokeRepeating(​"SpawnObstacle"​, startDelay, repeatRate);
​Instantiate(obstaclePrefab, spawnPos, obstaclePrefab.transform.rotation);​ }

void​ ​SpawnObstacle​ () {
​Instantiate(obstaclePrefab, spawnPos, obstaclePrefab.transform.rotation);​ } 
 
Lesson Recap 
New  ● Player jumps on spacebar press 
Functionality  ● Player cannot double-jump 
● Obstacles and Background move left 
● Obstacles spawn on intervals 

New Concepts  ● GetComponent 


and Skills  ● ForceMode.Impulse 
● Physics.Gravity 
● Rigidbody constraints 
● Rigidbody variables 
● Booleans 
● Multiply/Assign (“*) Operator 
● And (&&) Operator 
● OnCollisionEnter() 

Next Lesson  ● We’re going to fix that weird effect we created by moving the background 
left by having it actually constantly scroll using code! 
 

© Unity 2019 Lesson 3.1​ - Jump Force 


 
 
 

3.2​ M
​ ake the World Whiz By 
 
Steps: 
Step 1: Create a script to repeat background  Example of project by end of lesson 
Step 2: Reset position of background 

Step 3: Fix background repeat with collider 

Step 4: Add a new game over trigger 

Step 5: Stop MoveLeft on gameOver 

Step 6: Stop obstacle spawning on gameOver 

Step 7: Destroy obstacles that exit bounds   


 
 
Length:  70 minutes 

Overview:   We’ve got the core mechanics of this game figured out: The player can tap 
the spacebar to jump over incoming obstacles. However, the player appears 
to be running for the first few seconds, but then the background just 
disappears! In order to fix this, we need to repeat the background seamlessly 
to make it look like the world is rushing by! We also need the game to halt 
when the player collides with an obstacle, stopping the background from 
repeating and stopping the obstacles from spawning. Lastly, we must 
destroy any obstacles that get past the player. 

Project  The background moves flawlessly at the same time as the obstacles, and the 
Outcome:  obstacles will despawn when they exit game boundaries. With the power of 
script communication, the background and spawn manager will halt when 
the player collides with an obstacle. Colliding with an obstacle will also 
trigger a game over message in the console log, halting the background and 
the spawn manager. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Use tags to label game objects and call them in the code 
- Use script communication to access the methods and variables of other 
scripts 

   
© Unity 2019 Lesson 3.2​ - Make the World Whiz By 

Step 1: Create a script to repeat background 
We need to repeat the background and move it left at the same speed as the obstacles, to 
make it look like the world is rushing by. Thankfully we already have a move left script, but we 
will need a new script to make it repeat. 
1. Create a new script called ​RepeatBackground.cs  - Tip:​ Think through what needs to be 
and attach it to the B
​ ackground Object  done: when the background moves 
half of its length, move it back that 
distance  

 
 
Step 2: Reset position of background 
In order to repeat the background and provide the illusion of a world rushing by, we need to 
reset the background object’s position so it fits together perfectly. 
1. Declare a new variable ​private Vector3 startPos;  - Don’t worry:​ We’re setting it at 40 for 
2. In ​Start()​, set the s
​ tartPos​ v​ ariable to its actual  now, just to test basic functionality. 
starting position by assigning it ​ =  You could probably get it right with trial 
and error… but what would happen if 
transform.position; 
you changed the size? 
3. In ​Update()​, write an ​if-statement​ to reset position 
if it moves a certain distance 

private​ Vector3 startPos;

void​ ​Start​() {
​startPos = transform.position;​ }

void​ U ​ pdate​() {
​if​ (transform.position.x < startPos.x - 50) {
​transform.position = startPos; } ​}
 

© Unity 2019 Lesson 3.2​ - Make the World Whiz By 



Step 3: Fix background repeat with collider 
We’ve got the background repeating every few seconds, but the transition looks pretty 
awkward. We need make the background loop perfectly and seamlessly with some new 
variables. 
1. Add a ​Box Collider​ component to the B ​ ackground  - Don’t worry:​ We’re only adding a 
2. Declare a new ​private float repeatWidth​ variable  box collider to get the size of the 
3. In ​Start()​, get the width of the ​box collider​, divided by 2  background  
- New Function:​ .size.x 
4. Incorporate the ​repeatWidth​ variable into the ​repeat 
function  

private​ Vector3 startPos;


private​ ​float​ repeatWidth;

void​ ​Start​() {
startPos = transform.position;
​repeatWidth = GetComponent<BoxCollider>().size.x / 2​; }

void​ U​ pdate​() {
​if​ (transform.position.x < startPos.x -​ ​50​ repeatWidth​) {
transform.position = startPos; } } 
 
Step 4: Add a new game over trigger 
When the player collides with an obstacle, we want to trigger a “Game Over” state that stops 
everything In order to do so, we need a way to label and discern all game objects that the 
player collides with. 
1. In the inspector, add a “​Ground​” tag to the ​Ground​ and an  - New Concept:​ Tags  
“​Obstacle​” tag to the ​Obstacle prefab  - Warning:​ New tags will NOT be 
2. In PlayerController, declare a new p ​ ublic bool gameOver;  automatically added after you 
create them. Make sure to add 
3. In ​OnCollisionEnter​, add the i​ f-else statement​ to test if 
them yourself once they are 
player collided with the “Ground” or an “Obstacle”  created. 
4. If they collided with the “Ground”, set ​isOnGround = true​,  - Tip:​ No need to say gameOver 
and if they collide with an “Obstacle”, set ​gameOver = true  = false, since it is false by 
default 

public​ ​bool​ gameOver = ​false​;

private​ ​void​ ​OnCollisionEnter​(Collision collision) {


​isOnGround = ​true​;
​if​ (collision.gameObject.CompareTag(​"Ground"​)) {
​isOnGround = ​true​;
​} ​else​ ​if​ (collision.gameObject.CompareTag(​"Obstacle"​)) {
​gameOver = ​true​;
​Debug.Log(​"Game Over!"​); }

© Unity 2019 Lesson 3.2​ - Make the World Whiz By 



}

Step 5: Stop MoveLeft on gameOver 


We’ve added a gameOver bool that seems to work, but the background and the objects 
continue to move when they collide with an obstacle. We need the MoveLeft script to 
communicate with the PlayerController, and stop once the player triggers gameOver. 
1. In ​MoveLeft.cs​, declare a new p ​ rivate  - New Concept:​ Script Communication  
PlayerController playerControllerScript;  - Warning:​ Make sure to spell the 
2. In ​Start()​, initialize it by finding the ​Player​ and  “Player” tag correctly 
getting the PlayerController component 
3. Wrap the ​translate method​ in an ​if-statement 
checking if game is not over 

​ loat​ speed = 30;


private​ f
private​ PlayerController playerControllerScript;

void​ ​Start​() {
​playerControllerScript =
​GameObject.Find(​"Player"​).GetComponent<PlayerController>();​ }

​ pdate​() {
void​ U
​if (playerControllerScript.gameOver == ​false​) {
transform.Translate(Vector3.left * Time.deltaTime * speed);​ }​ } 
 
Step 6: Stop obstacle spawning on gameOver 
The background and the obstacles stop moving when gameOver == true, but the Spawn 
Manager is still raising an army of obstacles! We need to communicate with the Spawn 
Manager script and tell it to stop when the game is over. 
1. In ​SpawnManager.cs​, get a reference to the   
playerControllerScript​ using the same technique you did in 
MoveLeft.cs 
2. Add a condition to only instantiate objects if g
​ ameOver​ ​== false 

private​ PlayerController playerControllerScript;

void​ ​Start​() {
InvokeRepeating(​"SpawnObstacle"​, startDelay, repeatRate);
​playerControllerScript =
​GameObject.Find(​"Player"​).GetComponent<PlayerController>();​ }

void​ S ​ pawnObstacle​ () {
​if​ (playerControllerScript.gameOver == ​false​) {
Instantiate(obstaclePrefab, spawnPos, obstaclePrefab.transform.rotation);
}​ } 
© Unity 2019 Lesson 3.2​ - Make the World Whiz By 

Step 7: Destroy obstacles that exit bounds 
Just like the animals in Unit 2, we need to destroy any obstacles that exit boundaries. Otherwise 
they will slide into the distance… forever! 
1. In ​MoveLeft​, in U
​ pdate()​; write an if-statement to  - Tip: ​Reference your code from 
Destroy​ Obstacles if their position is less than a  MoveLeft 
leftBound​ variable 
2. Add any ​comments​ you need to make your code 
more ​readable 

private​ ​float​ leftBound = -15;

void​ U​ pdate​() {
​if​ (playerControllerScript.gameOver == ​false​) {
transform.Translate(Vector3.left * Time.deltaTime * speed); }

​if​ (transform.position.x < leftBound && gameObject.CompareTag(​"Obstacle"​)) {


​Destroy(gameObject); }​ } 

 
Lesson Recap 
New  ● Background repeats seamlessly 
Functionality  ● Background stops when player collides with obstacle 
● Obstacle spawning stops when player collides with obstacle 
● Obstacles are destroyed off-screen 

New Concepts  ● Repeat background 


and Skills  ● Get Collider width 
● Script communication 
● Equal to (==) operator 
● Tags 
● CompareTag() 

Next Lesson  ● Our character, while happy on the inside, looks a little too rigid on the 
outside, so we’re going to do some work with animations 
 
 

© Unity 2019 Lesson 3.2​ - Make the World Whiz By 


 
 
 

3.3​ D​ on’t Just Stand There 


 
Steps: 
Example of project by end of lesson 
Step 1: Explore the player’s animations 

Step 2: Make the player start off at a run 

Step 3: Set up a jump animation 

Step 4: Adjust the jump animation 

Step 5: Set up a falling animation 

Step 6: Keep player from unconscious jumping 


 
 
 
Length:  60 minutes 

Overview:   The game is looking great so far, but the player character is a bit… lifeless. 
Instead of the character simply sliding across the ground, we’re going to give 
it animations for running, jumping, and even death! We will also tweak the 
speed of these animations, timing them so they look perfect in the game 
environment. 

Project  With the animations from the animator controller, the character will have 3 
Outcome:  new animations that occur in 3 different game states. These states include 
running, jumping, and death, all of which transition smoothly and are timed to 
suit the game. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Manage basic animation states in the Animator Controller 
- Adjust the speed of animations to suit the character or the game 
- Set a default animation and trigger others with anim.SetTrigger 
- Set a permanent state for “Game Over” with anim.SetBool 

   

© Unity 2019 Lesson 3.3​ - Don’t Just Stand There 



Step 1: Explore the player’s animations 
In order to get this character moving their arms and legs, we need to explore the Animation 
Controller. 
1. Double-click on the Player’s ​Animation Controller​,  - New Concept:​ Animator Controller 
then explore the different ​Layers​, double-clicking  - New Concept:​ States and Conditions 
on ​States​ to see their animations and ​Transitions 
to see their conditions 

 
 
   

© Unity 2019 Lesson 3.3​ - Don’t Just Stand There 



Step 2: Make the player start off at a run 
Now that we’re more comfortable with the animation controller, we can tweak some variables 
and settings to make the player look like they’re really running. 
1. In the ​Parameters tab​, change the ​Speed_f  - Tip:​ Notice how it transitions from idle 
variable to 1.0  to walk to Run - looks awkward - that’s 
2. Right-click​ on ​Run_Static > Set as Layer Default  why need to make run default 
State 
3. Single-click​ the the Run_Static state and adjust 
the ​Speed​ value in the inspector to match the 
speed of the b ​ ackground 

 
   

© Unity 2019 Lesson 3.3​ - Don’t Just Stand There 



Step 3: Set up a jump animation 
The running animation looks good, but very odd when the player leaps over obstacles. Next up, 
we need to add a jumping animation that puts a real spring in their step.  
1. In ​PlayerController.cs​, declare a new ​private Animator  - New Function:​ anim.SetTrigger  
playerAnim;   - Tip:​ SetTrigger is helpful when 
2. In ​Start()​, set ​playerAnim = GetComponent<Animator>();  you just want something to 
happen once then return to 
3. In the ​if-statement​ for when the player jumps, trigger 
previous state (like a jump 
the jump:  animation) 
animator.SetTrigger(“Jump_trig”); 

private​ Animator playerAnim;

void​ ​Start​() {
playerRb = GetComponent<Rigidbody>();
​playerAnim = GetComponent<Animator>();
Physics.gravity *= gravityModifier; }

void​ U ​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.Space) && isOnGround) {
playerRb.AddForce(Vector3.up * 10 jumpForce, ForceMode.Impulse);
isOnGround = ​false​;
​playerAnim.SetTrigger(​"Jump_trig"​);​ } } 
 
Step 4: Adjust the jump animation 
The running animation plays, but it’s not perfect yet, we should tweak some of our character’s 
physics-related variables to get this looking just right. 
1. In the Animator window, click on the ​Running_Jump​ state,   
then in the inspector and​ reduce its Speed​ value to slow 
down the animation 
2. Adjust the player’s m
​ ass​, jump f​ orce​, and g
​ ravity​ modifier 
to get your jump just right 

© Unity 2019 Lesson 3.3​ - Don’t Just Stand There 



Step 5: Set up a falling animation 
The running and jumping animations look great, but there’s one more state that the character 
should have an animation for. Instead of continuing to sprint when it collides with an object, the 
character should fall over as if it has been knocked out. 
1. In the ​condition​ that player collides with Obstacle,  - New Function:​ anim.SetBool  
set the D​ eath​ ​bool​ to ​true  - New Function:​ anim.SetInt 
2. In the same ​if-statement​, set the ​DeathType 
integer to 1 

public​ ​bool​ gameOver = ​false​;

private​ ​void​ ​OnCollisionEnter​(Collision collision other) {


​if​ (other.gameObject.CompareTag(​"Ground"​)) {
isOnGround = ​true​;
} ​else​ ​if​ (other.gameObject.CompareTag(​"Obstacle"​)) {
Debug.Log(​"Game Over"​)
gameOver = ​true​;
​playerAnim.SetBool(​"Death_b"​, ​true​);
​playerAnim.SetInteger(​"DeathType_int"​, 1);​ } } 
 
 
Step 6: Keep player from unconscious jumping 
Everything is working perfectly, but there’s one small disturbing bug to fix: the player can jump 
from an unconscious position, making it look like the character is being defibrillated. 
1. To prevent the player from jumping while  - New Concept:​ ! “Does not” and != 
unconscious, add ​&& !gameOver​ to the ​jump  “Does not equal” operators  
condition  - Tip:​ gameOver != true is the same as 
gameOver == false 

void​ U​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.Space) && isOnGround​ && !gameOver​) {
playerRb.AddForce(Vector3.up * 10 jumpForce, ForceMode.Impulse);
isOnGround = ​false​;
animator.SetTrigger(​"Jump_trig"​); } } 
 
   

© Unity 2019 Lesson 3.3​ - Don’t Just Stand There 



Lesson Recap 
New  ● The player starts the scene with a fast-paced running animation 
Functionality  ● When the player jumps, there is a jumping animation 
● When the player crashes, the player falls over 

New Concepts  ● Animation Controllers 


and Skills  ● Animation States, Layers, and Transitions 
● Animation parameters 
● Animation programming 
● SetTrigger(), SetBool(), SetInt() 
● Not (!) operator 

Next Lesson  ● We’ll really polish this game up to make it look nice using particles and 
sound effects! 
 

© Unity 2019 Lesson 3.3​ - Don’t Just Stand There 


 
 
 

3.4​ P​ articles and Sound Effects 


 
Steps: 
Example of project by end of lesson 
Step 1: Customize an explosion particle 

Step 2: Play the particle on collision 

Step 3: Add a dirt splatter particle 

Step 4: Add music to the camera object 

Step 5: Declare variables for Audio Clips 

Step 6: Play Audio Clips on jump and crash 


 
 
 
Length:  60 minutes 

Overview:   This game is looking extremely good, but it’s missing something critical: 
Sound effects and Particle effects! Sounds and music will breathe life into an 
otherwise silent game world, and particles will make the player’s actions 
more dynamic and eye-popping. In this lesson, we will add cool sounds and 
particles when the character is running, jumping, and crashing. 

Project  Music will play as the player runs through the scene, kicking up dirt particles 
Outcome:  in a spray behind their feet. A springy sound will play as they jump and a 
boom will play as they crash, bursting in a cloud of smoke particles as they 
fall over. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Attach particle effects as children to game objects 
- Stop and play particle effects to correspond with character animation 
states 
- Work with Audio Sources and Listeners to play background music 
- Add sound effects to add polish to your project 

   

© Unity 2019 Lesson 3.4​ - Particles and Sound Effects 



Step 1: Customize an explosion particle 
The first particle effect we should add is an explosion for when the player collides with an 
obstacle. 
1. From the C ​ ourse​ ​Library > Particles​, drag  - New Concept:​ Particle Effects  
FX_Explosion_Smoke​ into the hierarchy, then use  - Warning:​ Don’t go crazy customizing 
the ​Play​ / ​Restart​ / ​Stop​ buttons to preview it  your particle effects, you could easily 
get sidetracked 
2. Play around with the ​settings​ to get your ​particle 
- New Concept:​ Child objects with 
system​ the way you want it  relative positions 
3. Make sure to ​uncheck​ t​ he P ​ lay on Awake​ setting  - Tip:​ Hovering over the settings while 
4. Drag the ​particle​ onto your player to make it a  editing your particle provides great 
child object​, then position it relative to the player  tool tips 

 
 
Step 2: Play the particle on collision 
We discovered the particle effects and found an explosion for the crash, but we need to assign 
it to the Player Controller and write some new code in order to play it. 
1. In ​PlayerController.cs​, declare a new ​public ParticleSystem  - New Function: 
explosionParticle;  particle.Play()  
2. In the Inspector, assign the e​ xplosion ​to the e
​ xplosion particle​ variable 
3. In the ​if-statement​ where the player collides with an obstacle, call 
explosionParticle.Play();​, then test and tweak the p ​ article properties 

public​ ParticleSystem explosionParticle;

private​ ​void​ ​OnCollisionEnter​(Collision collision other) {


​if​ (other.gameObject.CompareTag(​"Ground"​)) {
isOnGround = ​true​;
} ​else​ ​if​ (other.gameObject.CompareTag(​"Obstacle"​)) {
... ​explosionParticle.Play();​ } }

© Unity 2019 Lesson 3.4​ - Particles and Sound Effects 



Step 3: Add a dirt splatter particle 
The next particle effect we need is a dirt splatter, to make it seem like the player is kicking up 
ground as they sprint through the scene. The trick is that the particle should only play when the 
player is on the ground. 
1. Drag F ​ X_DirtSplatter​ as the Player’s ​child object​, reposition  - New Function: 
it, rotate it, and edit its settings  particle.Stop()  
2. Declare a new p ​ ublic ParticleSystem dirtParticle;​, then 
assign​ it in the Inspector 
3. Add ​dirtParticle.Stop();​ when the player jumps or collides 
with an ​obstacle 
4. Add ​dirtParticle.Play();​ when the player lands on the ​ground 

public​ ParticleSystem dirtParticle

void​ U​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.Space) && isOnGround && !gameOver) {
... ​dirtParticle.Stop();​ } }

private​ ​void​ ​OnCollisionEnter​(Collision collision other) {


​if​ (other.gameObject.CompareTag(​"Ground"​)) { ... ​dirtParticle.Play();
} ​else​ ​if​ (other.gameObject.CompareTag(​"Obstacle"​)) { ... ​dirtParticle.Stop();​ } } 
 
Step 4: Add music to the camera object 
Our particle effects are looking good, so it’s time to move on to sounds! In order to add music, 
we need to attach sound component to the camera. After all, the camera is the eyes AND the 
ears of the scene. 
1. Select the Main ​Camera​ object, then A​ dd  - New Concept:​ Audio Listener and 
Component > Audio Source  Audio Sources  
2. From ​Library > Sound​, drag a ​music clip​ onto the  - Tip:​ Music shouldn’t appear to come 
from a particular location in 3D space, 
AudioClip​ variable in the inspector 
which is why we’re adding it directly to 
3. Reduce the ​volume​ so it will be easier to hear  the camera 
sound effects 
4. Check the L​ oop​ checkbox 

   

© Unity 2019 Lesson 3.4​ - Particles and Sound Effects 



Step 5: Declare variables for Audio Clips 
Now that we’ve got some nice music playing, it’s time to add some sound effects. This time 
audio clips will emanate from the player, rather than the camera itself. 
1. In ​PlayerController.cs​, declare a new ​public  - Tip:​ Adding sound effects is not as 
AudioClip jumpSound;​ and a new ​public AudioClip  simple as adding music, because we 
crashSound;  need to trigger the events in our code 
2. From ​Library > Sound​, drag a clip onto each new 
sound​ variable in the inspector 

 
   

© Unity 2019 Lesson 3.4​ - Particles and Sound Effects 



Step 6: Play Audio Clips on jump and crash 
We’ve assigned audio clips to the jump and the crash in PlayerController. Now we need to play 
them at the right time, giving our game a full audio experience 
1. Add an ​Audio Source​ component to the p
​ layer  - Don’t worry:​ Declaring a new 
2. Declare a new ​private AudioSource playerAudio;  AudioSource variable is just like 
and initialize it as p
​ layerAudio =  declaring a new Animator or RigidBody 
GetComponent<AudioSource>(); 
3. Call ​playerAudio.PlayOneShot(jumpSound, 1.0f); 
when the character j​ umps 
4. Call ​playerAudio.PlayOneShot(crashSound, 1.0f); 
when the character c ​ rashes 

private​ AudioSource playerAudio;

void​ ​Start​() {
... ​playerAudio = GetComponent<AudioSource>();​ }

void​ U​ pdate​() {
​if​ (Input.GetKeyDown(KeyCode.Space) && isOnGround && !gameOver) {
... ​playerAudio.PlayOneShot(jumpSound, 1.0f);​ } }

private​ ​void​ ​OnCollisionEnter​(Collision collision other) {


...
} ​else​ ​if​ (other.gameObject.CompareTag(​"Obstacle"​))
{ ... ​playerAudio.PlayOneShot(crashSound, 1.0f);​ } } 

 
Lesson Recap 
New  ● Music plays during the game 
Functionality  ● Particle effects at the player’s feet when they run 
● Sound effects and explosion when the player hits an obstacle 

New Concepts  ● Particle systems  


and Skills  ● Child object positioning 
● Audio clips and Audio sources  
● Play and stop sound effects 
 
 

© Unity 2019 Lesson 3.4​ - Particles and Sound Effects 


 
 
 
 

Challenge 3  
Balloons & Booleans 

 
 
Challenge  Apply your knowledge of physics, scrolling backgrounds, and special effects 
Overview:   to a balloon floating through town, picking up tokens while avoiding 
explosives. You will have to do a lot of troubleshooting in this project because 
it is riddled with errors.  

Challenge  - The balloon floats upwards as the player holds spacebar 


Outcome:  - The background seamlessly repeats, simulating the balloon’s movement 
- Bombs and Money tokens are spawned randomly on a timer  
- When you collide with the Money, there’s a particle and sound effect 
- When you collide with the Bomb, there’s an explosion and the background 
stops  

Challenge  In this challenge, you will reinforce the following skills/concepts: 


Objectives:  - Declaring and initializing variables with the GetComponent method 
- Using booleans to trigger game states 
- Displaying particle effects at a particular location relative to a gameobject 
- Seamlessly scrolling a repeating background  

Challenge  - Open​ your P ​ rototype 3 ​project 


Instructions:  - Download​ the "​Challenge​ 3 Starter Files" from the Tutorial Materials section, 
then double-click on it to ​Import 
- In​ the ​Project Window > Assets > Challenge 3 > I​ nstructions​ folder, use the 
"Challenge 3 - Instructions" and Outcome video as a guide to complete the 
challenge 
 
   

© Unity 2019 Challenge 3​ - Balloons, Bombs & Booleans 



 

Challenge  Task  Hint 


1  The player can’t  The balloon should float up  There is a “NullReferenceExcepton” 
control the balloon  as the player presses  error on the player’s rigidBody 
spacebar  variable - it has to be assigned in 
Start() using the G​ etComponent<> 
method 

2  The background only  The background should move  In MoveLeftX.cs, the objects should 
moves when the game  at start, then ​stop​ when the  only Translate to the left if the game 
is over  game is over  is ​NOT​ over 

3  No objects are being  Make bombs or money  There is an error message saying, 
spawned   objects spawn every few  “Trying to Invoke method: 
seconds  SpawnManagerX.​PrawnsObject 
couldn't be called” - spelling matters 

4  Fireworks appear to  Make the fireworks display at  The fireworks particle is a child 
the side of the balloon  the balloon’s position  object of the Player - but its location 
still has to be set at the same 
location 

5  The background is not  Make the background repeat  The ​repeatWidth​ variable should be 
repeating properly  seamlessly  half of the background’s w​ idth​, not 
half of its ​height 

     
     
Bonus Challenge  Task  Hint 
X  The balloon can float  Prevent the player from  Add a boolean to check if the balloon 
way too high  floating their balloon too high   isLowEnough​, then only allow the 
player to add upwards force if that 
boolean is true 

Y  The balloon can drop  Make the balloon appear to  Figure out a way to test if the balloon 
below the ground  bounce off of the ground,  collides with the ground object, then 
preventing it from leaving the  add an impulse force upward if it 
bottom of the screen. There  does 
should be a sound effect 
when this happens, too! 
 
 
   

© Unity 2019 Challenge 3​ - Balloons, Bombs & Booleans 



 

Challenge Solution 
1  In PlayerControllerX.cs, in Start(), assign p
​ layerRb​ just like the playerAudio variable: 

  playerAudio = GetComponent<AudioSource>();
playerRb = GetComponent<Rigidbody>();

2  In MoveLeftX.cs, the objects should only Translate to the left if the game is NOT over - it’s 
currently checking if the game IS over: 
  if​ (​! ​playerControllerScript.gameOver) {
transform.Translate(Vector3.left * speed * Time.deltaTime, Space.World);
}

3  In SpawnManagerX.cs, in Start(), the InvokeRepeating method is using an incorrect spelling of 


“SpawnObjects” - correct the spelling error 

  void​ ​Start​() {
​ pawnObjects​"​, spawnDelay, spawnInterval);
InvokeRepeating(​"​PrawnsObjectS
...
}

4  Select the Fireworks child object and reposition it to the same location as the Player 

5  In RepeatBackgroundX.cs, in Start(), the repeatWidth should be dividing the X size (width) of 
the box collider by 2, not the Y size (height) 

  repeatWidth = GetComponent<BoxCollider>().size.​y​ x​ / 2; 


 
 
 
 
 
© Unity 2019 Challenge 3​ - Balloons, Bombs & Booleans 

Bonus Challenge Solution 


X1  In PlayerControllerX.cs create a boolean to track whether the player is low enough to float 
upwards, then in Update(), set it to ​false​ if the player is above a certain Y value and, else, set it 
to ​true  

  public​ ​bool​ isLowEnough;

void​ U​ pdate​() {
​if​ (transform.position.y > 13) {
isLowEnough = ​false​;
} ​else​ {
isLowEnough = ​true​;
}
}

X2  In the if-statement testing for the player pressing spacebar, add a condition testing that the 
isLowEnough​ boolean is true: 

  if​ (Input.GetKey(KeyCode.Space) ​&& isLowEnough​ && !gameOver) {


playerRb.AddForce(Vector3.up * floatForce
}

Y1  Add a tag to the Ground object so that you can easily test for a collision with it 

Y2  In PlayerControllerX.cs, in the OnCollisionEnter method, add a third else-if checking if the 
balloon collided with the ground during the game, and if so, to add an impulse force upwards 

  private​ ​void​ ​OnCollisionEnter​(Collision other) {


...
} ​else​ ​if​ (other.gameObject.CompareTag(​"Ground"​) && !gameOver)
{
playerRb.AddForce(Vector3.up * 10, ForceMode.Impulse);
}

© Unity 2019 Challenge 3​ - Balloons, Bombs & Booleans 



Y3  To add a sound effect, declare a new AudioClip variable and assign it in the inspector, then use 
the PlayOneShot method when the player collides with the ground. 

  public​ AudioClip moneySound;


public​ AudioClip explodeSound;
public​ AudioClip bounceSound;

private​ ​void​ ​OnCollisionEnter​(Collision other) {


...
} ​else​ ​if​ (other.gameObject.CompareTag(​"Ground"​) && !gameOver)
{
rigidBody.AddForce(Vector3.up * 10, ForceMode.Impulse);
​playerAudio.PlayOneShot(bounceSound, 1.5f);
}

 
 

© Unity 2019 Challenge 3​ - Balloons, Bombs & Booleans 


 
 
 

Unit 3 Lab  
Player Control 
 

Steps:  Example of progress by end of lab 

Step 1: Create PlayerController and plan your code 

Step 2: Basic movement from user input 

Step 3: Constrain the Player’s movement 

Step 4: Code Cleanup and Export Backup 


   
 
Length:  60 minutes 

Overview:   In this lesson, you program the player’s basic movement, including the code 
that limits that movement. Since there are a lot of different ways a player can 
move, depending on the type of project you’re working on, you will not be 
given step-by-step instructions on how to do it. In order to do this, you will 
need to do research, reference other code, and problem-solve when things go 
wrong. 

Project  The player will be able to move around based on user input, but ​not​ be able to 
Outcome:  move where they shouldn’t.  

Learning  By the end of this lab, you will be able to: 


Objectives:  - Program the type of player movement you want based on user input 
- Restrict player movement in the manner that is appropriate, depending on 
the needs of the project 
- Troubleshoot issues and find workarounds related to player movement 

   

© Unity 2019 Lab 3​ - Player Control 



Step 1: Create PlayerController and plan your code  
Regardless of what type of movement your player has, it’ll definitely need a PlayerController 
script 
1. Select your Player and add a  - Tip: ​Rigidbody is usually helpful - also detect 
Rigidbody ​component (with or without  triggers 
gravity enabled)  - Tip: ​Think about all the movement we’ve done so 
2. In your Assets folder, create a new  far: 
“​Scripts​” folder  - Prototype 1 - forward/back and rotate based 
3. Inside the new “Scripts” folder, create  on up/down and left/right arrows 
a new “​PlayerController​” C# script   - Challenge 1 - plane moving constantly, rotated 
4. Attach​ it to the player, then ​open​ it  direction based on arrows 
5. Determine what type of programming  - Prototype 2 - side-to-side movement and 
will be required for your Player  spacebar to fire a projectile 
- Challenge 2 - No player movement, but 
projectile launch on spacebar 
- Prototype 3 - background move, and player 
jumps on spacebar press 
- Challenge 3 - background move and player 
floats up when spacebar down 
- Don’t worry:​ If you want your player to move like 
the ball in Prototype 4, just use basic alternative for 
now 
 

References to the various types of movement programmed up to this point in the course 
 

 
 
By the end of this step, you should have a new Script open and a solid plan for what will go in it. 
 
 
   
© Unity 2019 Lab 3​ - Player Control 

Step 2: Basic movement from user input 
The first thing we’ll program is the player’s very basic movement based on user input 
1. Declare a new ​private float speed​ variable  - Explanation:​ Rigidbody movement with 
2. If using physics, declare a new R ​ igidbody  AddForce is different than Translate - 
playerRb variable​ for it and initialize it in Start()  looks more similar to real world movement 
with force being applied  
3. If using arrow keys, declare new ​verticalInput 
- Don’t worry:​ If your player is colliding with 
and/or ​horizontalInput​ variables   the ground or other objects in weird ways - 
4. If basing your movement off a key press,  we’ll fix that soon 
create the i​ f-statement​ to test for the  - Tip:​ You can look through your old code 
KeyCode  for references to how you did things 
5. Use either the T ​ ranslate​ method or ​AddForce 
method (if using physics) to move your 
character 

By the end of this step, the player should be able to move the way that you want based on user 
input.
 
 
   

© Unity 2019 Lab 3​ - Player Control 



Step 3: Constrain the Player’s movement 
No matter what kind of movement your player has, it needs to be limited for gameplay 
1. If your player is colliding with objects they shouldn’t  - Tip:​ Check the Global/Local 
(including the ground), check the “​Is trigger​” box in the  checkbox above scene view to see 
Collider component  the rotation of the player 
2. If your player’s position or rotation should be  - Tip:​ Look back at Prototype 2 for 
constrained, expand the ​constraints​ in the Rigidbody  the if-then statement to keep the 
component and constrain certain axes  player on screen  
3. If your Player can go o ​ ff the screen​, write an  - Tip:​ Look back at Prototype 3 and 
if-statement​ checking and resetting the position  Challenge 3 for examples of 
4. If the Player can double-jump or fly off-screen, create a  booleans to prevent 
boolean variable ​that limits the user’s ability to do so  double-jumping or going too high 
5. If your player should be constrained by physical 
barriers along the outside of the play area, create more 
primitive ​Planes​ or C
​ ubes​ and scale them to form 
walls  

 
 
By the end of this step, the player’s movement should be constrained in such a way that makes your 
game playable.  

 
   

© Unity 2019 Lab 3​ - Player Control 



Step 4: Code Cleanup and Export Backup 
Now that we have the basic functionality working, let’s clean up our code and make a backup. 
1. Create new​ Empty​ game objects and nest objects  - Tip:​ You always want to keep your 
inside them to ​organize​ your hierarchy  Update() functions clean or they can 
2. Clean up your Update methods by moving the  become overwhelming - it should be 
blocks of code into new void functions (e.g.  easy to see what actions are 
“​MovePlayer​()” or “​ConstrainPlayerPosition​()”)  happening every frame 
3. Add comments to make your code more readable 
4. Test​ to make sure everything still works, then s​ ave 
your scene 
5. Right-click on your ​Assets folder > E
​ xport Package 
then save a new version in your ​Backups​ folder 

// Move the player left/right and up/down based on arrow keys


void​ ​MovePlayer​() {
...
}

// Prevent the player from leaving the screen top/bottom


void​ ​ConstrainPlayerPosition​() {
...
}

By the end of this step, your code should be commented, organized, and backed up.
 
Lesson Recap 
New Progress  ● Player can move based on user input 
● Player movement is constrained to suit the requirements of the game 

New Concepts  ● Program in C# independently 


and Skills  ● Troubleshoot issues independently 

 
 
 

© Unity 2019 Lab 3​ - Player Control 


 
 
 

Quiz ​ ​Unit 3  


 
QUESTION    CHOICES 
 

1  You are trying to STOP spawning enemies when the    a. The “p” should be capitalized in 
player has died and have created the two scripts below  “playerController.isAlive” 
to do that. However, there is an error on the underlined  b. The “bool” in the 
code, “isAlive” in the EnemySpawner script. What is  PlayerController class needs a 
causing that error?  “public” access modifier 
c. The if-statement cannot be in 
the Update method 
d. “isAlive” must start with a 
capital “I” (“IsAlive”) 

  public​ c​ lass​ ​PlayerController​ : ​MonoBehaviour​ {


​bool​ isAlive;
...
}

public​ ​class​ ​EnemySpawner​ : ​MonoBehaviour​ {


​void​ ​Start​() {
playerController = GameObject.Find(​"Player"​).GetComponent<PlayerController>();
}
​void​ ​Update​() {
​if​ (playerController.​isAlive​ == ​false​) {
StopSpawning();
}
}
}

 
2  Match the following animation methods with its set of    a. 1A, 2B, 3C 
parameters  b. 1A, 2C, 3B 
c. 1B, 2A, 3C 
1. anim.SetBool(______); A. “Celebrate”   d. 1C, 2A, 3B 
2. anim.SetTrigger(_____); B. “Alive”, true
3. anim.SetInt(_____); C. “ThrowType”, 2

© Unity 2019 Quiz​ - Unit 3 



 
3  Given the animation controller / state machine below,    a. setFloat(“Speed_f”, 0.3f); 
which code will make the character transition from the  b. setInt(“Speed_f”, 1); 
“Idle” state to the “Walk” state.  c. setTrigger(“Speed_f”); 
d. setFloat(“Speed_f”, 0.1f); 

 
 
4  Which of these is the correct way to get a reference to    a. Line A 
an AudioSource component on a GameObject?  b. Line B 
c. Line C 
A. audio = GetComponent<AudioSource>();   d. Line D 
B. audio = GetComponent(AudioSource)<>;
C. audio = AudioSource.GetComponent<>();
D. audio = GetComponent.Audio<Source>;

 
5  When you run a project with the code below, you get the    a. The Player object does not 
following error: “NullReferenceException: Object  have a collider 
reference not set to an instance of an object.” What is  b. The Enemy object does not 
most likely the problem?  have a Rigidbody component 
c. The “Start” method should 
  public​ ​class​ ​Enemy​ : ​MonoBehaviour​ {   actually be “Update” 
​void​ ​Start​() { d. There is no object named 
player = GameObject.Find(​"Player"​); “Player” in the scene 
}
​void​ ​OnTriggerEnter​(Collider other) {
​if​ (player.transform.position.z > 10) {
Destroy(other.gameObject);
}
}
}

© Unity 2019 Quiz​ - Unit 3 



 
6  Which of the following conditions properly tests that the    a. Line A 
game is NOT over and the player IS on the ground  b. Line B 
c. Line C 
A. if​ (gameOver == ​false​ AND isOnGround) d. Line D 
B. if​ (gameOver && isOnGround == ​true​)
C. if​ (gameOver != ​true​ && isOnGround)
D. if​ (gameOver != ​false​ && isOnGround == ​true​)

 
7  By default, what will be the first state used by this    a. “Any State” 
Animation Controller?   b. “NotCrouched” 
c. “Death” 
d. “Crouch_Up” 

       
8  Which of the following variable declarations observes    a. 2 and 4 
Unity’s standard naming conventions (especially as it  b. 3 and 6 
relates to capitalization)?  c. 4 and 5 
d. 1 and 5 
1. private​ Animator anim;  
2. private​ player Player;
3. Float​ JumpForce = 10.0f;
4. bool​ gameOver = ​True​;
5. private​ Vector3 startPos;
6. Public​ gameObject ObstaclePrefab;

© Unity 2019 Quiz​ - Unit 3 



 
9  Which of the following is most likely the condition for    a. Jump_b is true 
the transition between “Run” and “Walk” shown below?  b. Speed_f is Less than 0.5 
c. Speed_f is Greater than 0.5 
d. Animation_int is Less than 10 

A.

B.

C.

D.

 
10  Which of the following do you think makes the most    a. Image A 
sense for a simple movement state machine?   b. Image B 
c. Image C 

   

A.

B.

C.

© Unity 2019 Quiz​ - Unit 3 


Quiz ​ A​ nswer Key 


 
#    ANSWER  EXPLANATION 
   
1    B  In order to access a variable from another class, that variable needs to be 
“public”. By default, if there is no access modifier, variables are private and 
cannot be accessed by another class 

2    C  SetInt would require an integer parameter, SetBool would require a boolean 


parameter, and SetTrigger only requires the trigger name/id 

3    A  You can see in the inspector that the condition for this transition is that 
“Speed_f is greater than 0.25”. You can tell it’s a float because it uses 
decimal points and it must be higher than 0.25. 

4    A  “GetComponent<AudioSource>();” is the correct way to use the 


GetComponent method 

5    D  If you try to “Find” an object that is not in the scene, you will get a 
“NullReferenceException” error. 

6    C  != means “does not equal to”, so “gameOver != true” is testing that the game 
is ​not​ over. If you just use the boolean’s name like “isOnGround,” this tests 
whether that boolean is true. The syntax for testing two conditions is “&&”. 

7    B  The default starting state is the one that the “Entry” state connects to. 

8    D  1. private Animator anim; - this is correct 


2. private player Player; - should be “private Player player” 
3. Float JumpForce = 10.0f; - should be “float jumpForce = 10.0f” 
4. bool gameOver = True; - should be “true” (lowercase “t”) 
5. private Vector3 startPos; - this is correct 
6. Public gameObject ObstaclePrefab; - should be “public GameObject 
obstaclePrefab” 

9    B  If you are transitioning from Running to Walking, that most likely is a result of 
reducing speed, so checking if “Speed_f is ​less​ than 0.5” is most likely 

10    A  You should start with “Idle” as the default state, then be able to transition 
between any of the states (Idling, Walking, Running). There should definitely 
be a transition between Walk and Run. 
 

© Unity 2019 Quiz​ - Unit 3 


 
 
 

4.1​ W
​ atch Where You’re Going 
 
Steps: 
Example of project by end of lesson 
Step 1: Create project and open scene 

Step 2: Set up the player and add a texture 

Step 3: Create a focal point for the camera 

Step 4: Rotate the focal point by user input 

Step 5: Add forward force to the player 

Step 6: Move in direction of focal point 


 
 
 
Length:  60 minutes 

Overview:   First thing’s first, we will create a new prototype and download the starter 
files! You’ll notice a beautiful island, sky, and particle effect... all of which can 
be customized! Next you will allow the player to rotate the camera around 
the island in a perfect radius, providing a glorious view of the scene. The 
player will be represented by a sphere, wrapped in a detailed texture of your 
choice. Finally you will add force to the player, allowing them to move 
forwards or backwards in the direction of the camera. 

Project  The camera will evenly rotate around a focal point in the center of the island, 
Outcome:  provided a horizontal input from the player. The player will control a textured 
sphere, and move them forwards or backwards in the direction of the 
camera’s focal point. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Apply Texture wraps to objects 
- Attaching a camera to its focal point using parent-child relationships 
- Transform objects based on local XYZ values 

   

© Unity 2019 Lesson 4.1​ - Watch Where You’re Going 



Step 1: Create project and open scene 
You’ve done it before, and it’s time to do it again... we must start a new project and import the 
starter files. 
1. Open ​Unity Hub​ and create “​Prototype 4​” in your  - Don’t worry:​ You can change texture 
course directory  of floating island and the color of the 
2. Click on the link to access the Prototype 4 s ​ tarter  sky later  
- Don’t worry:​ We’re in 
files​, then ​download and import​ them into Unity 
isometric/orthographic view for a 
3. Open the P ​ rototype 4 scene​ and delete the  reason: It just looks nicer when we 
Sample Scene​ without saving  rotate around the island 
4. Click R ​ un​ to see the p
​ article effects 

 
 
Step 2: Set up the player and add a texture 
We’ve got an island for the game to take place on, and now we need a sphere for the player to 
control and roll around.  
1. In the ​Hierarchy​, c
​ reate 3D Object > S ​ phere   - New Concept: 
2. Rename it “​Player​”, reset its ​position​ and increase its XYZ ​scale  Texture wraps 
to 1.5 
3. Add a ​RigidBody​ component to the ​Player  
4. From the L ​ ibrary > Textures​, drag a ​texture​ onto the ​sphere 

© Unity 2019 Lesson 4.1​ - Watch Where You’re Going 



Step 3: Create a focal point for the camera 
If we want the camera to rotate around the game in a smooth and cinematic fashion, we need 
to pin it to the center of the island with a focal point. 
1. Create a new ​Empty Object​ and rename it “​Focal Point​”,   - Don’t worry:​ This whole “focal 
2. Reset its position to the origin (0, 0, 0), and make the  point” business may be 
Camera a ​child object​ of it  confusing at first, but it will make 
sense once you see it in action  
3. Create a new “​Scripts​” folder, and a new 
- Tip:​ Try rotating the Focal point 
“​RotateCamera​” script inside it   around the Y axis and see the 
4. Attach​ the “RotateCamera” script to the F ​ ocal Point   camera rotate around in scene 
view 

 
 
Step 4: Rotate the focal point by user input 
Now that the camera is attached to the focal point, the player must be able to rotate it - and the 
camera child object - around the island with horizontal input. 
1. Create the code to rotate the camera based on  - Tip:​ Horizontal input should be 
rotationSpeed​ and h​ orizontalInput  familiar, we used it all the way back in 
2. Tweak the r​ otation speed​ value to get the speed  Unit 1! Feel free to reference your old 
code for guidance. 
you want 

public​ ​float​ rotationSpeed;

void​ ​Update​()
{
​float​ horizontalInput = Input.GetAxis(​"Horizontal"​);
​transform.Rotate(Vector3.up, horizontalInput * rotationSpeed * Time.deltaTime);

   

© Unity 2019 Lesson 4.1​ - Watch Where You’re Going 



Step 5: Add forward force to the player 
The camera is rotating perfectly around the island, but now we need to move the player. 
1. Create a new “​PlayerController​” script, apply it to the  - Tip:​ Moving objects with 
Player​, and open it  RigidBody and Addforce should 
2. Declare a new ​public float speed​ variable and initialize it  be familiar, we did it back in Unit 
3! Feel free to reference old code.  
3. Declare a new ​private Rigidbody playerRb​ and initialize 
- Don’t worry:​ We don’t have 
it in ​Start()  control over its direction yet - 
4. In ​Update()​, declare a new f​ orwardInput​ variable based  we’ll get to that next 
on ​“Vertical” i​ nput  
5. Call the ​AddForce()​ method to move the player forward 
based ​forwardInput 

private​ Rigidbody playerRb;


public​ ​float​ speed;

void​ ​Start​() {
​playerRb = GetComponent<Rigidbody>();​ }

void​ ​Update​() {
​float​ forwardInput = Input.GetAxis(​"Vertical"​);
​playerRb.AddForce(Vector3.forward * speed * forwardInput);​ } 
 
Step 6: Move in direction of focal point 
We’ve got the ball rolling, but it only goes forwards and backwards in a single direction! It 
should instead move in the direction the camera (and focal point) are facing. 
1. Declare a new ​private GameObject focalPoint;​ a ​ nd  - New Concept:​ Global vs Local XYZ  
initialize it in ​Start()​: ​focalPoint =  - Tip:​ Global XYZ directions relate to the 
GameObject.Find("Focal Point");  entire scene, whereas local XYZ 
directions relate to the object in 
2. In the ​AddForce​ call, Replace ​Vector3.forward​ with 
question 
focalPoint.transform.forward 

private​ GameObject focalPoint;

void​ ​Start​() {
rb = GetComponent<Rigidbody>();
​focalPoint = GameObject.Find(​"Focal Point"​);​ }

void​ ​Update​() {
​float​ forwardInput = Input.GetAxis(​"Vertical"​);
playerRb.AddForce(​Vector3.forward​ ​focalPoint.transform.forward
* speed * Time.deltaTime); } 

 
© Unity 2019 Lesson 4.1​ - Watch Where You’re Going 

Lesson Recap 
New  ● Camera rotates around the island based on horizontal input 
Functionality  ● Player rolls in direction of camera based on vertical input 

New Concepts  ● Texture Wraps 


and Skills  ● Camera as child object 
● Global vs Local coordinates 
● Get direction of other object 

Next Lesson  ● In the next lesson, we’ll add more challenge to the player, by creating 
enemies that chase them in the game. 
 
 

© Unity 2019 Lesson 4.1​ - Watch Where You’re Going 


 
 
 

4.2​ F​ ollow the Player 


 
Steps: 
Example of project by end of lesson 
Step 1: Add an enemy and a physics material 

Step 2: Create enemy script to follow player 

Step 3: Create a lookDirection variable 

Step 4: Create a Spawn Manager for the enemy 

Step 5: Randomly generate spawn position 

Step 6: Make a method return a spawn point 


 
 
 
Length:  60 minutes 

Overview:   The player can roll around to its heart’s content… but it has no purpose. In 
this lesson, we fill that purpose by creating an enemy to challenge the player! 
First we will give the enemy a texture of your choice, then give it the ability to 
bounce the player away... potentially knocking them off the cliff. Lastly, we 
will let the enemy chase the player around the island and spawn in random 
positions. 

Project  A textured and spherical enemy will spawn on the island at start, in a random 
Outcome:  location determined by a custom function. It will chase the player around the 
island, bouncing them off the edge if they get too close. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Apply Physics Materials to make game objects bouncy 
- Normalize vectors to point the enemy in the direction of the player 
- Randomly spawn with Random.Range on two axes 
- Write more advanced custom functions and variables to make your code 
clean and professional 

   

© Unity 2019 Lesson 4.2​ - Follow the Player 



Step 1: Add an enemy and a physics material 
Our camera rotation and player movement are working like a charm. Next we’re going to set up 
an enemy and give them them some special new physics to bounce the player away!  
1. Create a new ​Sphere​, rename it “​Enemy​” reposition  - Don’t worry:​ If your game is lagging, 
it, and drag a ​texture​ onto it  uncheck the “Active” checkbox for 
2. Add a new ​RigidBody​ component and adjust its  your clouds  
- New Concept:​ Physics Materials 
XYZ ​scale​, then test 
- New Concept:​ Bounciness property 
3. In a new “​Physics Materials​” f​ older, ​Create >  and Bounce Combine 
Physics Material,​ then name it “​Bouncy​” 
4. Increase the B ​ ounciness​ to “1”, change ​Bounce 
Combine​ to “Multiply”, apply it to your player and 
enemy, then ​test 

   

© Unity 2019 Lesson 4.2​ - Follow the Player 



Step 2: Create enemy script to follow player 
The enemy has the power to bounce the player away, but only if the player approaches it. We 
must tell the enemy to follow the player’s position, chasing them around the island. 
1. Make a new “​Enemy​”​ script and attach it to the  - Tip:​ Imagine we’re generating this new 
Enemy  vector by drawing an arrow from the 
2. Declare 3 new variables for ​Rigidbody enemyRb;​,  enemy to the player. 
- Tip:​ We should start thinking ahead 
GameObject player;​, and ​public float speed; 
and writing our variables in advance. 
3. Initialize ​enemyRb = GetComponent Rigidbody>();  Think… what are you going to need? 
and ​player = GameObject.Find("Player");  - Tip:​ When normalized, a vector keeps 
4. In ​Update()​, AddForce towards in the direction  the same direction but its length is 1.0, 
between the Player and the Enemy  forcing the enemy to try and keep up 

public​ ​float​ speed;


private​ Rigidbody enemyRb;
private​ GameObject player;

void​ ​Start​() {
​enemyRb = GetComponent<Rigidbody>();
​player = GameObject.Find(​"Player"​);​ }

void​ ​Update​() {
​enemyRb.AddForce((player.transform.position
​- transform.position).normalized * speed);​ }
 
Step 3: Create a lookDirection variable 
The enemy is now rolling towards the player, but our code is a bit messy. Let’s clean up by 
adding a variable for the new vector. 
1. In ​Update()​, declare a new V
​ ector3 lookDirection​ variable  - Tip:​ As always, adding 
2. Set V​ ector3 lookDirection = (player.transform.position -  variables makes the code more 
transform.position).normalized;  readable  
3. Implement the ​lookDirection​ variable in the ​AddForce​ call 

void​ ​Update​() {
​Vector3 lookDirection = ​(player.transform.position
​- transform.position).normalized​;

enemyRb.AddForce(​lookDirection ​(player.transform.position
​- transform.position).normalized​ ​* speed); } 

   

© Unity 2019 Lesson 4.2​ - Follow the Player 



Step 4: Create a Spawn Manager for the enemy 
Now that the enemy is acting exactly how we want, we’re going to turn it into a prefab so it can 
be instantiated by a Spawn Manager.  
1. Drag E ​ nemy​ into the Prefabs folder to create a new ​Prefab​,   
then delete E ​ nemy​ from scene 
2. Create a new “​Spawn Manager​” o ​ bject​, attach a new 
“​SpawnManager​” ​script​, and open it 
3. Declare a new ​public GameObject enemyPrefab v​ ariable then 
assign the prefab in the i​ nspector 
4. In ​Start()​, instantiate a new ​enemyPrefab​ at a predetermined 
location 

public​ GameObject enemyPrefab;

void​ ​Start​()
{
​Instantiate(enemyPrefab, ​new​ Vector3(0, 0, 6),
enemyPrefab.transform.rotation);​ } 

 
Step 5: Randomly generate spawn position 
The enemy spawns at start, but it always appears in the same spot. Using the familiar Random 
class, we can spawn the enemy in a random position. 
1. In SpawnManager.cs, in ​Start()​, create new ​randomly  - Tip:​ Remember, we used 
generated​ X and Z  Random.Range all the way back 
2. Create a new ​Vector3 randomPos​ v​ ariable with those  in Unit 2! Feel free to reference 
old code.  
random X and Z positions 
3. Incorporate the new ​randomPos​ variable into the 
Instantiate​ call 
4. Replace the hard-coded v ​ alues​ with a ​spawnRange 
variable 
5. Start​ and ​Restart​ your project to make sure it’s working 

public​ GameObject enemyPrefab;


private​ ​float​ spawnRange = 9;

void​ ​Start​() {
​float​ spawnPosX = Random.Range(​-9, 9 ​-spawnRange, spawnRange);
​float​ spawnPosZ = Random.Range(​-9, 9 ​-spawnRange, spawnRange);
​Vector3 randomPos = new Vector3(spawnPosX, 0, spawnPosZ);
Instantiate(enemyPrefab, randomPos, enemyPrefab.transform.rotation); } 

© Unity 2019 Lesson 4.2​ - Follow the Player 



Step 6: Make a method return a spawn point 
The code we use to generate a random spawn position is perfect, and we’re going to be using it 
a lot. If we want to clean the script and use this code later down the road, we should store it in a 
custom function. 
1. Create a new function V ​ ector3  - Tip:​ This function will come in handy 
GenerateSpawnPosition() { }  later, once we randomize a spawn 
2. Copy and Paste the ​spawnPosX​ and s ​ pawnPosZ  position for the powerup  
- New Concept:​ Functions that return a 
variables into the new method 
value 
3. Add the line to ​return randomPos;​ in your new  - Tip:​ This function is different from 
method  “void” calls, which do not return a 
4. Replace the code in your ​Instantiate call​ with your  value. Look at “GetAxis” in 
new function name: G ​ enerateSpawnPosition()   PlayerController for example - it 
returns a float 

void​ ​Start​() {
Instantiate(enemyPrefab, ​GenerateSpawnPosition()
​new​ Vector3(spawnPosX, 0, spawnPosZ)​, enemyPrefab.transform.rotation);
​float​ spawnPosX = Random.Range(-spawnRange, spawnRange);
​float​ spawnPosZ = Random.Range(-spawnRange, spawnRange);​ }

private​ Vector3 ​GenerateSpawnPosition​ () {


​float​ spawnPosX = Random.Range(-spawnRange, spawnRange);
​float​ spawnPosZ = Random.Range(-spawnRange, spawnRange);
​Vector3 randomPos = new Vector3(spawnPosX, 0, spawnPosZ);
​return​ ​randomPos;​ } 
 
 
Lesson Recap 
New  ● Enemy spawns at random location on the island 
Functionality  ● Enemy follows the player around  
● Spheres bounce off of each other  

New Concepts  ● Physics Materials 


and Skills  ● Defining vectors in 3D space 
● Normalizing values 
● Methods with return values 

Next Lesson  ● In our next lesson, we’ll create ways to fight back against these enemies 
using Powerups! 
 
 

© Unity 2019 Lesson 4.2​ - Follow the Player 


 
 
 

4.3​ P​ owerUp and CountDown 


 
Steps: 
Example of project by end of lesson 
Step 1: Choose and prepare a powerup 

Step 2: Destroy powerup on collision 

Step 3: Test for collision with a powerup 

Step 4: Apply extra knockback with powerup 

Step 5: Create Countdown Routine for powerup 

Step 6: Add a powerup indicator 


 
 
 
Length:  60 minutes 

Overview:   The enemy chases the player around the island, but the player needs a better 
way to defend themselves... especially if we add more enemies. In this 
lesson, we’re going to create a powerup that gives the player a temporary 
strength boost, shoving away enemies that come into contact! The powerup 
will spawn in a random position on the island, and highlight the player with 
an indicator when it is picked up. The powerup indicator and the powerup 
itself will be represented by stylish game assets of your choice. 

Project  A powerup will spawn in a random position on the map. Once the player 
Outcome:  collides with this powerup, the powerup will disappear and the player will be 
highlighted by an indicator. The powerup will last for a certain number of 
seconds after pickup, granting the player super strength that blasts away 
enemies. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Write informative debug messages with Concatenation and variables 
- Repeat functions with the power of IEnumerator and Coroutines 
- Use SetActive to make game objects appear and disappear from the scene 

   

© Unity 2019 Lesson 4.3​ - PowerUp and CountDown 



Step 1: Choose and prepare a powerup 
In order to add a completely new gameplay mechanic to this project, we will introduce a new 
powerup object that will give the player temporary superpowers.  
1. From the L​ ibrary​, drag a ​Powerup​ object into the scene,  - Warning:​ Remember, you still 
rename it “​Powerup​” and edit its ​scale​ & ​position  have to apply the tag after it 
2. Add a ​Box Collider​ to the powerup, click ​Edit Collider​ to  has been created. 
make sure it fits, then check the “​Is Trigger​” checkbox 
3. Create a new “​Powerup​” t​ ag​ and apply it to the ​powerup 
4. Drag the ​Powerup​ into the ​Prefabs​ ​folder​ to create a new 
“Original Prefab” 

 
 
Step 2: Destroy powerup on collision 
As a first step to getting the powerup working, we’ll make it disappear when the player hits it 
and set up a new boolean variable to track that the player got it. 
1. In ​PlayerController.cs​, add a n
​ ew  - Don’t worry:​ If this doesn’t work, make 
OnTriggerEnter()​ method  sure that the Powerup’s collider “Is 
2. Add an ​if-statement​ that destroys  trigger” and player’s collider is NOT  
- Tip:​ Make sure hasPowerup = true in 
other.CompareTag("Powerup")​ ​powerup​ on 
the inspector when you collide 
collision 
3. Create a new ​public bool hasPowerup;​ and set 
hasPowerup = true;​ when you ​collide​ with the 
Powerup 

public​ ​bool​ hasPowerup

private​ ​void​ ​OnTriggerEnter​(Collider other) {


​if​ (other.CompareTag(​"Powerup"​)) {
​hasPowerup = ​true​;
​Destroy(other.gameObject); } }

   

© Unity 2019 Lesson 4.3​ - PowerUp and CountDown 



Step 3: Test for collision with a powerup 
The powerup will only come into play in a very particular circumstance: when the player has a 
powerup AND they collide with an enemy - so we’ll first test for that very specific condition. 
1. Create a new “​Enemy​” tag and apply it to the  - Tip:​ OnTriggerEnter is good for stuff 
Enemy Prefab  like picking up powerups, but you 
2. In ​PlayerController.cs​, add the O
​ nCollisionEnter()  should use OnCollisionEnter when you 
want something to do with physics  
function 
- New Concept:​ Concatenation in Debug 
3. Create the ​if-statement​ with the ​double-condition  messages 
4. Create a ​Debug.Log​ to make sure it’s working   - Tip:​ When you concatenate a variable 
in a debug message, it will returns its 
VALUE not its name 

private​ ​void​ ​OnCollisionEnter​(Collision collision) {


​if​ (collision.gameObject.CompareTag(​"Enemy"​) && hasPowerup) {
​Debug.Log(​"Player collided with "​ + collision.gameObject
​+ ​" with powerup set to "​ + hasPowerup); } } 

 
Step 4: Apply extra knockback with powerup 
With the condition for the powerup set up perfectly, we are now ready to program the actual 
powerup ability: when the player collides with an enemy, the enemy should go flying! 
1. In ​OnCollisionEnter() d
​ eclare a new ​local variable  - Tip:​ Reference the code in Enemy.cs 
to get the Enemy’s ​Rigidbody​ component  that makes the enemy follow the 
2. Declare a new variable to get the d ​ irection​ away  player. In a way, we’re reversing that 
code in order to push the enemy away. 
from the ​player 
- Don’t worry:​ No need to use 
3. Add an ​impulse force​ to the e​ nemy  .Normalize, since they’re colliding 
4. Replace​ the hard-coded value with a new 
powerupStrength​ variable 

private​ ​float​ powerupStrength = 15.0f;

private​ ​void​ ​OnCollisionEnter​(Collision collision) {


​if​ (collision.gameObject.CompareTag(​"Enemy"​) && hasPowerup) {

​Rigidbody enemyRigidbody = collision.gameObject.GetComponent<Rigidbody>();


​Vector3 awayFromPlayer = (collision.gameObject.transform.position
​- transform.position);

Debug.Log(​"Player collided with "​ + collision.gameObject


+ ​" with powerup set to "​ + hasPowerup);
​enemyRigidbody.AddForce(awayFromPlayer
​*​ 10​ powerupStrength, ForceMode.Impulse);​ } }

   
© Unity 2019 Lesson 4.3​ - PowerUp and CountDown 

Step 5: Create Countdown Routine for powerup 
It wouldn’t be fair to the enemies if the powerup lasted forever - so we’ll program a countdown 
timer that starts when the player collects the powerup, removing the powerup ability when the 
timer is finished. 
1. Add a new ​IEnumerator  - New Concept:​ IEnumerator 
PowerupCountdownRoutine () {}  - New Concept:​ Coroutines 
2. Inside the ​PowerupCountdownRoutine​, wait 7  - Tip:​ WaitForSeconds() 
seconds, then ​disable​ the powerup 
3. When player c ​ ollides​ with powerup, start the 
coroutine 

private​ ​void​ ​OnTriggerEnter​(Collider other) {


​if​ (other.CompareTag(​"Powerup"​)) {
hasPowerup = ​true​;
Destroy(other.gameObject);
​StartCoroutine(PowerupCountdownRoutine());​ } }

IEnumerator ​PowerupCountdownRoutine​() {
​yield​ return new ​WaitForSeconds​(7); hasPowerup = ​false​; } 
 
   

© Unity 2019 Lesson 4.3​ - PowerUp and CountDown 



Step 6: Add a powerup indicator 
To make this game a lot more playable, it should be clear when the player does or does not 
have the powerup, so we’ll program a visual indicator to display this to the user. 
1. From the L ​ ibrary​, drag a ​Powerup​ o
​ bject​ into the scene, rename it  - New Function: 
“​Powerup Indicator​”, and edit its ​scale  SetActive  
2. Uncheck​ the “​Active​” checkbox in the inspector  - Tip:​ Make sure the 
indicator is turning on 
3. In ​PlayerController.cs​, declare a new ​public GameObject 
and off before making 
powerupIndicator v​ ariable, then assign the ​Powerup Indicator  it follow the player 
variable in the inspector 
4. When the player collides with the powerup, set the indicator object 
to ​Active​, then set to I​ nactive​ when the powerup expires 
5. In ​Update()​, set the Indicator position to the player’s position + an 
offset value 

public​ GameObject powerupIndicator

void​ ​Update​() {
... ​powerupIndicator.transform.position = transform.position
​+ ​new​ Vector3(0, -0.5f, 0);​ }

private​ ​void​ ​OnTriggerEnter​(Collider other) {


​if​ (other.CompareTag(​"Powerup"​)) {
... ​powerupIndicator.gameObject.SetActive(​true​);​ } }

IEnumerator ​PowerupCountdownRoutine​() {
... ​powerupIndicator.gameObject.SetActive(​false​);​ } 

 
Lesson Recap 
New  ● When the player collects a powerup, a visual indicator appears 
Functionality  ● When the player collides with an enemy while they have the powerup, the 
enemy goes flying 
● After a certain amount of time, the powerup ability and indicator disappear 

New Concepts  ● Debug concatenation 


and Skills  ● Local component variables 
● IEnumerators and WaitForSeconds() 
● Coroutines 
● SetActive(true/false) 

Next Lesson  ● We’ll start generating waves of enemies for our player to fend off! 
 
 

© Unity 2019 Lesson 4.3​ - PowerUp and CountDown 


 
 
 

4.4​ F​ or-Loops For Waves 


 
Steps:  Example of project by end of lesson 
Step 1: Write a for-loop to spawn 3 enemies 

Step 2: Give the for-loop a parameter 

Step 3: Destroy enemies if they fall off 

Step 4: Increase enemyCount with waves 

Step 5: Spawn Powerups with new waves 


   
 
Length:  60 minutes 

Overview:   We have all the makings of a great game; A player that rolls around and 
rotates the camera, a powerup that grants super strength, and an enemy that 
chases the player until the bitter end. In this lesson we will wrap things up by 
putting these pieces together! 
First we will enhance the enemy spawn manager, allowing it to spawn 
multiple enemies and increase their number every time a wave is defeated. 
Lastly we will spawn the powerup with every wave, giving the player a chance 
to fight back against the ever-increasing horde of enemies. 

Project  The Spawn Manager will operate in waves, spawning multiple enemies and a 
Outcome:  new powerup with each iteration. Every time the enemies drop to zero, a new 
wave is spawned and the enemy count increases. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Repeat functions with For-loops 
- Increment integer values in a loop with the ++ operator 
- Target objects in a scene with FindObjectsOfType 
- Return the length of an array as an integer with .Length 

   

© Unity 2019 Lesson 4.4​ - For-Loops For Waves 



Step 1: Write a for-loop to spawn 3 enemies 
We should challenge the player by spawning more than one enemy. In order to do so, we will 
repeat enemy instantiation with a loop. 
1. In SpawnManager.cs, in ​Start()​, replace single  - New Concept:​ For-loops  
Instantiation​ with a ​for-loop​ that spawns 3  - Don’t worry:​ Loops are a bit confusing 
enemies  at first, but they make sense 
eventually. Loops are powerful tools 
2. Move the for-loop to a new v​ oid 
that programmers use often 
SpawnEnemyWave()​ function, then call that  - New Concept:​ ++ Increment Operator 
function from ​Start() 

void​ ​Start​() {
​SpawnEnemyWave();
​for​ (​int​ i = 0; i < 3; i++) {
​Instantiate(enemyPrefab, GenerateSpawnPosition(),
​enemyPrefab.transform.rotation); }​ }

void​ ​SpawnEnemyWave​() {
​for​ (​int​ i = 0; i < 3; i++) {
​Instantiate(enemyPrefab, GenerateSpawnPosition(),
​enemyPrefab.transform.rotation); }​ } 
 
 
Step 2: Give the for-loop a parameter 
Right now, SpawnEnemyWave spawns exactly 3 enemies, but if we’re going to dynamically 
increase the number of enemies that spawn during gameplay, we need to be able to pass 
information to that method. 
1. Add a parameter ​int enemiesToSpawn​ to the  - New Concept:​ Custom methods with 
SpawnEnemyWave​ function   parameters  
2. Replace i​ < __​ with​ ​i < enemiesToSpawn  - Tip:​ GenerateSpawnPosition returns a 
value, SpawnEnemyWave does not. 
3. Add this new variable to the function call in ​Start()​: 
SpawnEnemyWave takes a parameter, 
SpawnEnemyWave(___);   GenerateSpawnPosition does not. 

void​ ​Start​() {
SpawnEnemyWave(​3​); }

void​ ​SpawnEnemyWave​(​int​ enemiesToSpawn​) {


​for​ (​int​ i = 0; i <​ ​3​ enemiesToSpawn​; i++) {
Instantiate(enemyPrefab, GenerateSpawnPosition(),
enemyPrefab.transform.rotation); } }
 
   

© Unity 2019 Lesson 4.4​ - For-Loops For Waves 



Step 3: Destroy enemies if they fall off 
Once the player gets rid of all the enemies, they’re left feeling a bit lonely. We need to destroy 
enemies that fall, and spawn a new enemy wave once the last one is vanquished! 
1. In Enemy.cs, d ​ estroy ​the enemies if their position  - New Function:​ FindObjectsOfType 
is less than a ​-Y value 
2. In SpawnManager.cs, declare a new ​public int 
enemyCount ​variable 
3. In ​Update()​, set ​enemyCount = 
FindObjectsOfType<Enemy>().Length; 
4. Write the ​if-statement​ that if ​enemyCount == 0 
then ​SpawnEnemyWave​, then delete it from ​Start()  

void​ ​Update​() {
... ​if​ (transform.position.y < -10) { Destroy(gameObject); }​ }

<------>
public​ ​int​ enemyCount

void​ ​Update​() {
​enemyCount = FindObjectsOfType<Enemy>().Length;
​if​ (enemyCount == 0) { SpawnEnemyWave(1); }​ } 
 
 
Step 4: Increase enemyCount with waves 
Now that we control the amount of enemies that spawn, we should increase their number in 
waves. Every time the player defeats a wave of enemies, more should rise to take their place. 
1. Declare a new ​public int waveCount = 1;​, then  - Tip:​ Incrementing with the ++ operator 
implement it in ​SpawnEnemyWave(waveCount);  is very handy, you may find yourself 
2. In the if-statement that tests if there are 0 enemies  using it in the future  
left, ​increment waveCount ​by 1 

public​ ​int​ waveCount = 1;

void​ ​Start​() {
SpawnEnemyWave(​3​ ​waveCount​); }

void​ ​Update​() {
enemyCount = FindObjectsOfType<Enemy>().Length;
​if​ (enemyCount == 0) { ​waveCount++;​ SpawnEnemyWave(​1​ ​waveCount​); } }

   

© Unity 2019 Lesson 4.4​ - For-Loops For Waves 



Step 5: Spawn Powerups with new waves 
Our game is almost complete, but we’re missing something. Enemies continue to spawn with 
every wave, but the powerup gets used once and disappears forever, leaving the player 
vulnerable. We need to spawn the powerup in a random position with every wave, so the player 
has a chance to fight back. 
1. In SpawnManager.cs, declare a new ​public  - Tip:​ Now that we have a very playable 
GameObject powerupPrefab v​ ariable, assign the  game, let’s test and tweak values  
prefab​ in the inspector and ​delete​ it from the 
scene 
2. In ​Start()​, I​ nstantiate​ a new Powerup 
3. Before the ​SpawnEnemyWave()​ call, ​Instantiate​ a 
new Powerup 

public​ GameObject powerupPrefab;

void​ ​Start​() {
... ​Instantiate(powerupPrefab, GenerateSpawnPosition(),
​powerupPrefab.transform.rotation);​ }

void​ ​Update​() {
... ​if​ (enemyCount == 0) { ... ​Instantiate(powerupPrefab,
​GenerateSpawnPosition(), powerupPrefab.transform.rotation);​ } } 
 
 
Lesson Recap 
New  ● Enemies spawn in waves 
Functionality  ● The number of enemies spawned increases after every wave is defeated 
● A new power up spawns with every wave 

New Concepts  ● For-loops 


and Skills  ● Increment (++) operator 
● Custom methods with parameters 
● FindObjectsOfType 
 
 

© Unity 2019 Lesson 4.4​ - For-Loops For Waves 


 
 
 
 

Challenge 4  
Soccer Scripting 

 
 
Challenge  Use the skills you learned in the Sumo Battle prototype in a completely 
Overview:   different context: the soccer field. Just like in the prototype, you will control a 
ball by rotating the camera around it and applying a forward force, but instead 
of knocking them off the edge, your goal is to knock them into the opposing 
net while they try to get into your net. Just like in the Sumo Battle, after every 
round a new wave will spawn with more enemy balls, putting your defense to 
the test. However, almost nothing in this project is functioning! It’s your job to 
get it working correctly. 

Challenge  - Enemies move towards your net, but you can hit them to deflect them away 
Outcome:  - Powerups apply a temporary strength boost, then disappear after 5 seconds 
- When there are no more enemy balls, a new wave spawns with 1 more 
enemy  

Challenge  In this challenge, you will reinforce the following skills/concepts: 


Objectives:  - Defining Vectors by subtracting one location in 3D space from another 
- Track the number of objects of a certain type in a scene to trigger certain 
events 
- Using Coroutines to perform actions based on a timed interval 
- Using for-loops and dynamic variables to run code a particular number of 
times 
- Resolving errors related to null references of unassigned variables 

Challenge  - Open​ your P ​ rototype 4 ​project 


Instructions:  - Download​ the "​Challenge​ 4 Starter Files" from the Tutorial Materials section, 
then double-click on it to ​Import 
- In​ the ​Project Window > Assets > Challenge 4 > I​ nstructions​ folder, use the 
resources as a guide to complete this challenge 
   

© Unity 2019 Challenge 4 ​- Soccer Scripting 



 

Challenge  Task  Hint 


1  Hitting an enemy  When you hit an enemy, it  In PlayerControllerX.cs, to get a 
sends it back towards  should send it ​away​ from the  Vector a
​ way​ from the player, you 
you  player  should subtract the [enemy position] 
minus the [player’s position] - not the 
reverse 

2  A new wave spawns  A new wave should spawn  In SpawnManagerX.cs, check that the 
when the player gets a  when all enemy balls have  enemyCount variable is being set 
powerup  been removed  correctly 

3  The powerup never  The powerup should only last  In PlayerControllerX.cs, the 
goes away  for a certain duration, then  PowerupCoolDown Coroutine code 
disappear  looks good, but this coroutine is 
never actually called with the 
StartCoroutine() method 

4  2 enemies are  One enemy should be  In SpawnManagerX.cs, the for-loop 


spawned in every  spawned in wave 1, two in  that spawns enemy should make use 
wave  wave 2, three in wave 3, etc  of the enemiesToSpawn parameter 

5  The enemy balls are  The enemy balls should go  There is an error in EnemyX.cs: 
not moving anywhere  towards the “Player Goal”  “NullReferenceException: Object 
object  reference not set to an instance of an 
object”. It looks like the playerGoal 
object is never assigned. 

     
Bonus Challenge  Task  Hint 
X  The player needs a  The player should get a  In PlayerController, add a simple 
turbo boost   speed boost whenever the  if-statement that adds an “impulse” 
player presses spacebar -  force if spacebar is pressed. To add a 
and a particle effect should  particle effect, first attach it as a child 
appear when they use it   object of the Focal Point. 

Y  The enemies never get  The enemies’ speed should  You’ll need to track and increase the 
more difficult  increase in speed by a small  enemy speed in SpawnManagerX.cs. 
amount with every new wave  Then in EnemyX.cs, reference that 
speed variable and set it in Start(). 
 
 
   

© Unity 2019 Challenge 4 ​- Soccer Scripting 



 

Challenge Solution 
1  In PlayerControllerX.cs, in OnCollisionEnter(), the ​awayFromPlayer​ Vector3 is in the opposite 
direction it should be.  

  Vector3 awayFromPlayer = transform.position ​-


other.gameObject.transform.position​;
= ​other.gameObject.transform.position -
transform.position;

2  In SpawnManagerX.cs, the ​enemyCount​ variable is counting the number of objects with a 


“Powerup” tag - it should be counting the number of objects with an “Enemy” tag 
  void​ ​Update​() {
enemyCount = GameObject.FindGameObjectsWithTag(​"​Powerup​ ​Enemy​"​).Length;
...
}

3  In PlayerControllerX.cs, in the OnTriggerEnter() method, you need to initiate the 


PowerupCooldown C ​ oroutine in order to begin the countdown process 

  private​ ​void​ ​OnTriggerEnter​(Collider other) {


​if​ (other.gameObject.CompareTag(​"Powerup"​)) {
...
​StartCoroutine(PowerupCooldown());
}
}

4  In SpawnManagerX.cs, the for-loop that spawns enemy should make use of the 
enemiesToSpawn​ parameter 
  ​ nemiesToSpawn​; i++) {
for​ (​int​ i = 0; i < ​2 e
Instantiate(enemyPrefab, GenerateSpawnPosition(), ...
}

5  In EnemyX.cs, the ​playerGoal​ variable is not initialized - initialize it in the Start() method 

  void​ ​Start​() {
enemyRb = GetComponent<Rigidbody>();
​playerGoal = GameObject.Find(​"Player Goal"​);
;​}
 
 

© Unity 2019 Challenge 4 ​- Soccer Scripting 


Bonus Challenge Solution 


X1  To add a turbo boost, In PlayerControllerX.cs, declare a new ​turboBoost​ float variable, then in 
Update(), add a simple if-statement that adds an “impulse” force in the direction of the focal 
point if spacebar is pressed: 

  private​ ​float​ turboBoost = 10;

void​ ​Update​() {
...
​if​ (Input.GetKeyDown(KeyCode.Space)) {
playerRb.AddForce(focalPoint.transform.forward * turboBoost, ForceMode.Impulse);
}
}

X2  Add the Smoke_Particle prefab as a child object of the focal point (next to the camera), then in 
PlayerControllerX.cs, declare a new turboSmoke particle variable and assign it in the inspector 

X3  In PlayerControllerX.cs, in the if-statement checking if the player presses spacebar, play the 
particle 

  if​ (Input.GetKeyDown(KeyCode.Space)) {
​playerRb.AddForce(focalPoint.transform.forward * turboBoost, ForceMode.Impulse);
​turboSmoke.Play();
}

Y1  In SpawnManagerX.cs, declare and initialize a new public ​enemySpeed​ variable, then increase 
it by a certain amount every time a wave is spawned: 

  ​ nt​ enemyCount;
public​ i
public​ f​ loat​ enemySpeed = 50;

void​ ​SpawnEnemyWave​(​int​ enemiesToSpawn) {


...
waveCount++;
​enemyCount += 25;
}

© Unity 2019 Challenge 4 ​- Soccer Scripting 



Y2  In EnemyX.cs, declare a new spawnManagerXScript variable, get a reference to it in Start(), 
then set the enemy’s s
​ peed​ variable to your new ​enemySpeed​ variable 

  private​ GameObject playerGoal;


private​ SpawnManagerX spawnManagerXScript;

void​ ​Start​() {
enemyRb = GetComponent<Rigidbody>();
playerGoal = GameObject.Find(​"Player Goal"​);
​spawnManagerXScript = GameObject.Find(​"Spawn Manager"​).GetComponent<SpawnManagerX>();
​speed = spawnManagerXScript.enemySpeed;
}

Y3  To test, make the s​ peed​ variable in EnemyX.cs public and check the enemies’ speed when they 
are spawned in different waves 

 
 

© Unity 2019 Challenge 4 ​- Soccer Scripting 


 
 
 

Unit 4 Lab  
Basic Gameplay 
 
Steps:  Example of progress by end of lab 
Step 1: Give objects basic movement 

Step 2: Destroy objects off-screen 

Step 3: Handle object collisions 

Step 4: Make objects into prefabs 

Step 5: Make SpawnManager spawn Prefabs 


   
 
Length:  60 minutes 

Overview:   In this lab, you will work with all of your non-player objects in order to bring 
your project to life with its basic gameplay. You will give your projectiles, 
pickups, or enemies their basic movement and collision detection, make 
them into prefabs, and have them spawned randomly by a spawn manager. 
By the end of this lab, you should have a glimpse into the core functionality 
of your game. 

Project  Non-player objects are spawned at appropriate locations in the scene with 
Outcome:  basic movement. When objects collide with each other, they react as 
intended, by either bouncing or being destroyed. 

Learning  By the end of this lab, you will be able to: 


Objectives:  - More comfortably program basic movement 
- More comfortably handle object collisions 
- More comfortably spawn object prefabs on timed intervals 

   

© Unity 2019 Lab 4​ - Basic Gameplay 



Step 1: Give objects basic movement 
Before you spawn objects into your scene, they should move the way you want. 
1. If relevant, add ​Rigidbody​ components to your  - Tip:​ Make sure you uncheck “use 
non-player objects  gravity” if you don’t want them to fall 
2. Create a ​new script​(s) for the objects that will be  - Tip:​ In the collider component, check 
instantiated during gameplay and attach them to  “is trigger” if you don’t want actual 
their respective objects (including projectiles or  collisions 
pickups) 
3. Program the b ​ asic movement ​for your objects and 
test that they work 

By the end of this step, all objects should basically move the way they should in the game.
 
Step 2: Destroy objects off-screen 
To make sure our hierarchy doesn’t get too cluttered, let’s make sure these objects get 
destroyed when they leave the screen. 
1. Either create a new script or add code to your  - Tip:​ Move your objects in scene view 
existing script to make sure objects are destroyed  to determine the xyz positions objects 
when they leave the screen  should be destroyed 

By the end of this step, objects should be removed from the hierarchy when they are no longer in 
play.
 
Step 3: Handle object collisions 
Now that you have all these moving objects, they’re bound to start colliding with each other - we 
need to program what should happen when everything collides. 
1. If relevant, edit the ​Rigidbody mass​ of your objects  - Don’t worry:​ If you collide with a 
2. If relevant, to change the way your objects collide,  powerup or pickup, the actual 
create a new ​Physics material​ for your objects  functionality does ​not​ need to be 
3. Add ​tags​ to your objects so you can accurately test  programmed, just the effect 
for which objects are colliding with which  - Tip:​ Should use OnTriggerEnter if 
4. Use ​OnCollisionEnter() ​(for Rigidbody collisions) or  objects are being destroyed - but 
OnTriggerEnter()​ (for trigger-based collisions) to  remember that “Is Trigger” must be 
Destroy​ or ​Log​ messages to the console what  checked for this to work! 
should happen when certain collisions occur 

By the end of this step, objects should destroy, bounce, or do nothing based on collisions.

   

© Unity 2019 Lab 4​ - Basic Gameplay 



Step 4: Make objects into prefabs  
Now that the objects are basically behaving the way they should, if they’re going to be 
instantiated during gameplay, they need to be prefabs 
1. In the Assets directory, create a new F​ older​ called  - Tip:​ When creating new prefabs, 
“​Prefabs​”  you have to drag them one at a 
2. Drag​ in each object to create a n
​ ew prefab​ for it  time 
3. After all objects have been turned into prefabs, ​delete  - Tip:​ Notice that their icons turn 
them from the scene  blue when they are prefabs 
4. Test​ the objects’ behavior by dragging them from the 
Prefabs folder into the scene while the game is running 

By the end of this step, all objects that will be spawned during gameplay should be prefabs and 
should no longer be in your scene.
 
Step 5: Make SpawnManager spawn Prefabs 
Now that we have all of our prefabs set up, we can create a spawn manager to spawn them at 
intervals and, if we want, in random locations. 
1. Create an Empty “Spawn Manager” object and attach a  - Tip:​ Name your variables 
new SpawnManager.cs script to it  “____Prefab” so you know it 
2. Create individual ​GameObject​ ​or GameObject array  requires a prefab value 
variables for your prefabs, then ​assign​ them in the  - Don’t worry:​ If it’s not perfect yet 
inspector  of if there are some minor bugs - 
3. Use the ​Instantiate()​, R
​ andom.Range()​, and the  just get the general idea working 
InvokeRepeating()​ methods to spawn objects at 
intervals (random objects, random locations, or both) 
4. Right-click on your ​Assets folder > E
​ xport Package​ then 
save a new version in your ​Backups​ folder 

By the end of this step, objects should be spawned automatically from the appropriate location.
 
 
   

© Unity 2019 Lab 4​ - Basic Gameplay 



Lesson Recap 
New Progress  ● Non-player objects prefabs have basic movement  
● Objects are destroyed when they leave the screen  
● Collisions between objects are handled appropriately 
● Objects are spawned at the appropriate locations on time-based intervals 

New Concepts  ● Creating basic gameplay for a project independently 


and Skills 

 
 
 

© Unity 2019 Lab 4​ - Basic Gameplay 


 
 
 

Quiz ​ ​Unit 4  


 
QUESTION    CHOICES 
 

1  You’re trying to write some code that creates a random    a. Change line 1 to “private float 
age between 1 and 100 and prints that age, but there is  age” 
an error. What would fix the error?  b. Add the word “int” to line 8, so 
it says “int age = …” 
1. private​ ​int​ age; c. On line 7, change the word 
2. “private” to “void” 
3. void​ ​Start​() { d. Add a new line after line 8 that 
4. Debug.Log(​GenerateRandomAge​()); says “return age;” 
5. }
6.
7. ​ nt​ ​GenerateRandomAge​() {
private​ i
8. age = Random.Range(1, 101);
9. } 

 
2  The following message was displayed in the console:    a. Option A 
“Monica has 20 dollars”. Which of lines in the  b. Option B 
PrintNames function produced it?  c. Option C 
d. Option D 

  string​[] names = ​new​ ​string​[] { ​"Steve"​, ​"Monica"​, ​"Eric"​ };


int​ money = 5;

void​ ​Start​() {
money *= 2;
PrintNames();
}

void​ ​PrintNames​ () {
​A. ​Debug.Log(​"Monica has "​ + money/2 + ​" dollars"​);
​B. ​Debug.Log(names[1] + ​" has "​ + money*2 + ​" dollars"​);
​C. ​Debug.Log(names[2] + ​" has "​ + money*4 + ​" dollars"​);
​D. ​Debug.Log(names[Monica] + ​" has "​ + money/2 + ​" dollars"​);
}

© Unity 2019 Quiz​ - Unit 4 



 
3  The code below produces “error CS0029: Cannot    a. On line 1, change “Vector3” to 
implicitly convert type 'float' to 'UnityEngine.Vector3'”.  “float” 
Which of the following would remove the error?  b. On line 3, change “=” to “+” 
c. Either A or B 
1. private​ Vector3 startingVelocity; d. None of the above  
2. void​ ​Start​() {
3. startingVelocity = 2.0f;
4. } 
 
4  Which of the following follows Unity’s naming    a. Line A 
conventions (especially as it relates to capitalization)?  b. Line B 
c. Line C 
A. float​ forwardInput = Input.GetAxis(​"Vertical"​); d. Line D 
B. float​ ForwardInput = input.GetAxis(​"Vertical"​);
C. Float​ forwardInput = Input.getAxis(​"Vertical"​);
D. float​ forwardInput = input.getAxis(​"vertical"​);

 
5  You are trying to assign the powerup variable in the    a. You cannot declare a powerup 
inspector, but it is not showing up in the Player  variable in the Player Controller 
Controller component. What is the problem?  Script 
b. You cannot assign 
  public​ ​class​ ​PlayerController​ : ​MonoBehaviour GameObject type variables in 
{ the inspector 
​private​ GameObject powerup; c. The powerup variable should 
}  be public instead of private 
d. The PlayerController class 
should be private instead of 
public 
 
6  Your game has just started and you see the error,    a. PlayerController variable in the 
“UnassignedReferenceException: The variable  playerIndicator script needs to 
playerIndicator of PlayerController has not been  be declared 
assigned.” What is likely the solution to the problem?  b. The playerIndicator variable 
needs to be made private 
  public​ ​class​ ​PlayerController​ : ​MonoBehaviour c. The PlayerController script 
{ must be assigned to the player 
​public​ GameObject playerIndicator; object 
​void​ ​Update​() { d. An object needs to be dragged 
playerIndicator.transform.position.y = 10; onto the playerIndicator 
} variable in the inspector 
}

© Unity 2019 Quiz​ - Unit 4 



 
7  You are trying to create a new method that takes a    a. Method A 
number and multiplies it by two. Which method would  b. Method B 
do that?  c. Method C 
d. Method D 
A. private float​ ​DoubleNumber​() { `
​return​ number *= 2;
}

B. private float​ ​DoubleNumber​(​float​ number) { `


​return​ number *= 2;
}

C. private void​ ​DoubleNumber​(​float​ number) {


​return​ number *= 2;
}

D. private void​ ​DoubleNumber​() {


​return​ number *= 2;
}

 
8  Which comment best describes the code below?    a. // If the player collides with an 
enemy, destroy the enemy 
  public​ ​class​ ​Enemy​ : ​MonoBehaviour b. // If the enemy collides with a 
{ spike, destroy the spike 
​// Comment c. // If the enemy collides with a 
​private​ ​void​ ​OnTriggerEnter​(Collider other) { spike, destroy the enemy 
​if​(other.CompareTag(​"Spike"​)) { d. // If the player collides with a 
Destroy(other.gameObject); spike, destroy the spike 
}
}
}

 
9  The code below produces the error, “error CS0029:    a. On line 1, change “collision” to 
Cannot implicitly convert type 'UnityEngine.GameObject'  “Rigidbody” 
to 'UnityEngine.Rigidbody'”. What could be done to fix  b. On line 2, change “gameObject” 
this issue?  to “Rigidbody” 
c. On line 3, delete “.gameObject” 
1. void​ ​OnCollisionEnter​(Collision collision) { d. On line 3, add 
2. ​if​(collision.gameObject.CompareTag(​"Enemy"​)) { “.GetComponent<Rigidbody>()” 
3. Rigidbody enemyRb = collision.gameObject; before the semicolon 
4. }
5. }

© Unity 2019 Quiz​ - Unit 4 



 
10  Which of the following statements about    a. A and B are correct 
functions/methods are correct:  b. Only B is correct 
c. B and C are correct 
A. Functions/methods must be passed at least one parameter  d. Only D is correct 
B. Functions/methods with a “void” return type cannot be  e. None are correct 
passed parameters 
C. A Function/method with an “int” return type could include 
the code, “return 0.5f;” 
D. If there was a function/method declared as “private void 
RenameObject(string newName)”, you could call that 
method with “RenameObject();” 
   

© Unity 2019 Quiz​ - Unit 4 


Quiz ​ A​ nswer Key 


 
#    ANSWER  EXPLANATION 
   
1    D  Since the method has an “int” return type “private ​int​ GenerateRandomAge()”, 
it must r​ eturn​ an int. 

2    B  Debug.Log(names[1] + " has " + money*2 + " dollars"); is correct. 


Arrays start with index 0, so “Monica” has the index value of “1” (names[1]). 
In start, money is multiplied by 2, making it 10, so “money*2” would give you 
the value of 20. 

3    A  Changing “Vector3” to “float” would work because you would just be 
multiplying a flat by another float. Changing “=” to “+” would not work 
because you can’t add a float to a Vector3. 

4    A  Lowercase “float”, camelCase variables, Capitalized class & method names 

5    C  Making a variable public will make it appear in the inspector. 

6    D  If the consoles says a variable is not assigned, you most likely forgot to 
assign that variable by dragging on object onto it in the inspector. 

7    B  Since it needs to “return” a value, it should have a return type of “private 


float​” ​as opposed to “private v​ oid.​” ​Since it needs to take a number, it needs 
a float parameter (“float number”). 
 

8    B  Since this is the “Enemy” class, we are testing for the enemy colliding with 
something. Since it destroys “​other.​gameObject”,​ it will destroy the spike. 

9    D  The code cannot convert a RigidBody type variable to a GameObject type 


variable, so you have to get the RigidBody component from the gameObject 

10    E  A. Functions/methods do not necessarily require parameters 


B. Functions/methods with a “void” return type ​can​ be passed 
parameters 
C. A Function/method with an “int” return type could not include the 
code, “return 0.5f;”, since 0.5f is a float 
D. If there was a function/method declared as “private void 
RenameObject(string newName)”, you would have to pass it a string 
parameter, such as RenameObject(“Steve”); 
 

© Unity 2019 Quiz​ - Unit 4 


 
 
 

5.1​ C​ licky Mouse 


 
Steps: 
Step 1: Create project and switch to 2D view  Example of project by end of lesson 
Step 2: Create good and bad targets 

Step 3: Toss objects randomly in the air 

Step 4: Replace messy code with new methods 

Step 5: Create object list in Game Manager 

Step 6: Create a coroutine to spawn objects 

Step 7: Destroy target with click and sensor   


 
 
Length:  60 minutes 

Overview:   It’s time for the final unit! We will start off by creating a new project and 
importing the starter files, then switching the game’s view to 2D. Next we will 
make a list of target objects for the player to click on: Three “good” objects 
and one “bad”. The targets will launch spinning into the air after spawning at 
a random position at the bottom of the map. Lastly, we will allow the player 
to destroy them with a click! 

Project  A list of three good target objects and one bad target object will spawn in a 
Outcome:  random position at the bottom of the screen, thrusting themselves into the 
air with random force and torque. These targets will be destroyed when the 
player clicks on them or they fall out of bounds. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Switch the game to 2D view for a different perspective 
- Add torque to the force of an object 
- Create a Game Manager object that controls game states as well as 
spawning 
- Create a List of objects and return their length with Count 
- Use While Loops to repeat code while something is true 
- Use OnMouseDown to enable the player to click on things 

   
© Unity 2019 Lesson 5.1​ - Clicky Mouse 

Step 1: Create project and switch to 2D view 
One last time… we need to create a new project and download the starter files to get things up 
and running. 
1. Open ​Unity Hub​ and create “​Prototype 5​” in your  - New Concept:​ 2D View  
course directory on correct version in 3D  - Demo:​ Notice in 2D view: You can’t 
2. Click on the link to access the Prototype 5 s ​ tarter  rotate around objects or move them in 
the Z direction 
files​, then ​download and import​ them into Unity 
3. Open the P ​ rototype 5 ​scene, then delete the 
sample scene​ without saving 
4. Click on the ​2D icon​ in Scene view to put Scene 
view in ​2D 
5. (optional) Change the texture and color of the 
background​ and the color of the ​borders  

 
 
   

© Unity 2019 Lesson 5.1​ - Clicky Mouse 



Step 2: Create good and bad targets 
The first thing we need in our game are three good objects to collect, and one bad object to 
avoid. It’ll be up to you to decide what’s good and what’s bad. 
1. From the L ​ ibrary​, drag 3 “good” objects and 1 “bad”  - Tip:​ The bigger the collider 
object into the Scene, rename them “​Good 1​”, “​Good 2​”,  boxes, the easier it will be to hit 
“​Good 3​”, and “​Bad 1​”  them  
- Tip:​ Try selecting multiple 
2. Add ​Rigid Body​ and B ​ ox Collider​ components, then make 
objects and applying 
sure that Colliders surround objects properly  scripts/components - very 
3. Create a new Scripts folder, a new “​Target.cs​” script  handy 
inside it, attach it to the T ​ arget objects 
4. Drag all 4 targets into the P ​ refabs folder​ to create 
“original prefabs”, then d ​ elete​ them from the scene 

 
Step 3: Toss objects randomly in the air 
Now that we have 4 target prefabs with the same script, we need to toss them into the air with 
a random force, torque, and position. 
1. In ​Target.cs​, declare a new p ​ rivate Rigidbody  - New Function:​ AddTorque 
targetRb;​ and initialize it in ​Start()  - Tip:​ Test with different values by 
2. In ​Start()​, add an ​upward force​ multiplied by a  dragging them in during runtime 
- Don’t worry:​ We’re going to fix all these 
randomized speed 
hard-coded values next 
3. Add a ​torque​ with randomized​ xyz values 
4. Set the ​position​ with a randomized​ X value  

private​ Rigidbody targetRb;

void​ ​Start​() {
​targetRb = GetComponent<Rigidbody>();
​targetRb.AddForce(Vector3.up * Random.Range(12, 16), ForceMode.Impulse);
​targetRb.AddTorque(Random.Range(-10, 10), Random.Range(-10, 10),
​Random.Range(-10, 10), ForceMode.Impulse);
​transform.position = ​new​ Vector3(Random.Range(-4, 4), -6);​ } 

   

© Unity 2019 Lesson 5.1​ - Clicky Mouse 



Step 4: Replace messy code with new methods 
Instead of leaving the random force, torque, and position making our Start() function messy and 
unreadable, we’re going to store each of them in brand new clearly named custom methods. 
1. Declare and initialize new private float variables for ​minSpeed,   
maxSpeed, maxTorque,​ ​xRange, a ​ nd​ y​ SpawnPos​; 
2. Create a new function for ​Vector3 RandomForce()​ and call it in ​Start() 
3. Create a new function for ​float RandomTorque()​, and call it in S
​ tart() 
4. Create a new function for ​RandomSpawnPos()​, have it return a new 
Vector3​ and call it in S
​ tart() 

​ loat​ minSpeed = 12; p


private​ f ​ rivate​ ​float​ maxSpeed = 16;
private​ f​ loat​ maxTorque = 10; p ​ rivate​ ​float​ xRange = 4;
private​ f ​ loat​ ySpawnPos = -6;

void​ ​Start​() {
... targetRb.AddForce(​...​ ​RandomForce​(), ForceMode.Impulse);
targetRb.AddTorque(​...​ ​RandomTorque(), RandomTorque(),
​RandomTorque()​, ForceMode.Impulse);
transform.position = ​new​ Vector3(​...​ ​RandomSpawnPos​; }

Vector3 ​RandomForce​() { ​return​ Vector3.up * Random.Range(minSpeed, maxSpeed);


}
float​ ​RandomTorque​() { ​return​ Random.Range(-maxTorque, maxTorque); }
Vector3 ​RandomSpawnPos​() { ​return​ ​new​ Vector3(Random.Range(-xRange, xRange),
ySpawnPos); }

   

© Unity 2019 Lesson 5.1​ - Clicky Mouse 



Step 5: Create object list in Game Manager 
The next thing we should do is create a list for these objects to spawn from. Instead of making 
a Spawn Manager for these spawn functions, we’re going to make a Game Manager that will 
also control game states later on. 
1. Create a new “​Game Manager​” ​Empty object​,  - New Concept:​ Lists  
attach a new ​GameManager.cs​ script, then open it  - New Concept:​ Game Manager 
2. Declare a new ​public List<GameObject> targets;​,  - Demo:​ Feel free to reference old code: 
We used an array instead of a list to 
then in the Game Manager inspector, change the 
spawn the animals in Unit 2 
list ​Size​ to 4 and assign your ​prefabs 

 
 
Step 6: Create a coroutine to spawn objects 
Now that we have a list of object prefabs, we should instantiate them in the game using 
coroutines and a new type of loop. 
1. Declare and initialize a new p ​ rivate float spawnRate  - Tip:​ Feel free to reference old code: 
variable  we used coroutines for the 
2. Create a new ​IEnumerator SpawnTarget ()​ method   powerup cooldown in Unit 4  
- Tip:​ Arrays return an integer with 
3. Inside the new method, ​while(true),​ w ​ ait ​1 second​, 
.Length, while Lists return an 
generate a r​ andom index​, and spawn a random ​target  integer with .Count 
4. In ​Start()​, use the ​StartCoroutine​ method​ t​ o begin  - New Concept:​ While Loops 
spawning objects 

private​ ​float​ spawnRate = 1.0f;

void​ ​Start​() { ​StartCoroutine(SpawnTarget());​ }

IEnumerator ​SpawnTarget​() {
​while​ (​true​) {
​yield​ return new ​WaitForSeconds​(spawnRate);
​int​ index = Random.Range(0, targets.Count);
​Instantiate(targets[index]); } } 

© Unity 2019 Lesson 5.1​ - Clicky Mouse 



Step 7: Destroy target with click and sensor 
Now that our targets are spawning and getting tossed into the air, we need a way for the player 
to destroy them with a click. We also need to destroy any targets that fall below the screen. 
1. In ​Target.cs​, add a new method for ​private void  - New Function:​ OnMouseDown  
OnMouseDown() { } ,​ and inside that method,  - Tip:​ There is also OnMouseUp, and 
destroy the gameObject  OnMouseEnter, but Down is definitely 
the one we want 
2. Add a new method for p ​ rivate void 
- Tip:​ You could use Update and check if 
OnTriggerEnter(Collider other)​ ​and inside that  target y position is lower than a certain 
function, destroy the gameObject  value, but a sensor is better because it 
doesn't run all the time 

private​ ​void​ ​OnMouseDown​() {


​Destroy(gameObject); }

private​ ​void​ ​OnTriggerEnter​(Collider other) {


​Destroy(gameObject); } 

 
Lesson Recap 
New  ● Random objects are tossed into the air on intervals 
Functionality  ● Objects are given random speed, position, and torque 
● If you click on an object, it is destroyed 

New Concepts  ● 2D View 


and Skills  ● AddTorque 
● Game Manager 
● Lists 
● While Loops 
● Mouse Events 

Next Lesson  ● We’ll add some effects and keep track of score! 
 
 

© Unity 2019 Lesson 5.1​ - Clicky Mouse 


 
 
 

5.2​ K​ eeping Score 


 
Steps: 
Step 1: Add Score text position it on screen  Example of project by end of lesson 
Step 2: Edit the Score Text’s properties 

Step 3: Initialize score text and variable 

Step 4: Create a new UpdateScore method 

Step 5: Add score when targets are destroyed 

Step 6: Assign a point value to each target 

Step 7: Add a Particle explosion   


 
 
Length:  60 minutes 

Overview:   Objects fly into the scene and the player can click to destroy them, but 
nothing happens. In this lesson, we will display a score in the user interface 
that tracks and displays the player’s points. We will give each target object a 
different point value, adding or subtracting points on click. Lastly, we will add 
cool explosions when each target is destroyed.  

Project  A “Score: “ section will display in the UI, starting at zero. When the player 
Outcome:  clicks a target, the score will update and particles will explode as the target 
is destroyed. Each “Good” target adds a different point value to the score, 
while the “Bad” target subtracts from the score. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Create UI Elements in the Canvas 
- Lock elements and objects into place with Anchors 
- Use variables and script communication to update elements in the UI 

   

© Unity 2019 Lesson 5.2​ - Keeping Score 



Step 1: Add Score text position it on screen 
In order to display the score on-screen, we need to add our very first UI element. 
1. Create > UI > ​TextMeshPro text​, then if prompted  - New Concept:​ Text Mesh Pro / TMPro  
click the button to ​Import TMP Essentials   - New Concept:​ Canvas 
2. Rename the new object “​Score Text​”, then z ​ oom  - New Concept:​ Anchor Points 
- Tip:​ Look at how it displays in scene 
out​ to see the c​ anvas​ in Scene view 
vs game view. It may be hard to see 
3. Change the ​Anchor Point​ so that it is anchored  white text depending on the 
from the ​top-left​ c
​ orner  background 
4. In the inspector, change its P ​ os X​ and P
​ os Y​ so 
that it is in the top-left corner 

 
 
Step 2: Edit the Score Text’s properties 
Now that the basic text is in the scene and positioned properly, we should edit its properties so 
that it looks nice and has the correct text. 
1. Change its text to “​Score​:”   
2. Choose a ​Font Asset​, S
​ tyle​, S
​ ize​, and V
​ ertex color 
to look good with your background 

© Unity 2019 Lesson 5.2​ - Keeping Score 



Step 3: Initialize score text and variable 
We have a great place to display score in the UI, but nothing is displaying there! We need the UI 
to display a score variable, so the player can keep track of their points. 
1. At the top of ​GameManager.cs​, add “​using TMPro;​”  - New Concept: 
2. Declare a new p ​ ublic​ ​TextMeshProUGUI scoreText​,​ then assign that  Importing Libraries 
variable in the inspector  
3. Create a new p ​ rivate int score​ variable and initialize it in S
​ tart()​ as 
score = 0; 
4. Also in S
​ tart()​, set s
​ coreText.text = "Score: " + score; 

private​ ​int​ score;


public​ TextMeshProUGUI scoreText;

void​ ​Start​() {
StartCoroutine(SpawnTarget());
​score = 0;
​scoreText.text = ​"Score: "​ + score;​ } 
 
Step 4: Create a new UpdateScore method 
The score text displays the score variable perfectly, but it never gets updated. We need to write 
a new function that racks up points to display in the UI. 
1. Create a new p​ rivate void UpdateScore()​ method  - Don’t worry:​ It doesn’t 
2. Cut and paste s ​ coreText.text = "Score: " + score;​ ​into the new  make sense to add to 
method, then call ​UpdateScore()​ ​in S ​ tart()  score when spawned, this 
is just temporary 
3. Add the parameter i​ nt scoreToAdd​ to the ​UpdateScore 
method, then fix the error in S​ tart()​ by passing it a value of 
zero 
4. In U
​ pdateScore()​, increase the score by setting s ​ core += 
scoreToAdd;  
5. Call U
​ pdateScore(5)​ in the s
​ pawnTarget()​ function 

void​ ​Start​() {
... ​score = 0;
​scoreText.text = ​"Score: "​ + score; UpdateScore(0);​ }

IEnumerator ​SpawnTarget​() {
​while​ (​true​) { ... ​UpdateScore(5);​ }

private​ ​void​ ​UpdateScore​(​int​ scoreToAdd) {


​score += scoreToAdd;
​scoreText.text = ​"Score: "​ + score; } 

   
© Unity 2019 Lesson 5.2​ - Keeping Score 

Step 5: Add score when targets are destroyed 
Now that we have a method to update the score, we should call it in the target script whenever 
a target is destroyed. 
1. In Target.cs, create a reference to ​private  - Tip:​ Feel free to reference old code: 
GameManager gameManager;   We used script communication in Unit 
2. Initialize GameManager in S ​ tart() ​ using the F
​ ind()  3 to stop the game on GameOver  
- Warning:​ If you try to call UpdateScore 
method 
while it’s private, it won’t work 
3. In GameManager.cs, make the ​UpdateScore 
method ​public 
4. When a target is d ​ estroyed​, call U
​ pdateScore(5);​, 
then d​ elete​ the method call from SpawnTarget() 

private​ GameManager gameManager;

void​ ​Start​() {
... ​gameManager = GameObject.Find(​"Game
Manager"​).GetComponent<GameManager>();​}

private​ ​void​ ​OnMouseDown​() {


Destroy(gameObject); ​gameManager.UpdateScore(5);​ }

private​ ​public​ ​void​ ​UpdateScore​(​int​ scoreToAdd) { ... } 


 
Step 6: Assign a point value to each target 
The score gets updated when targets are clicked, but we want to give each of the targets a 
different value. The good objects should vary in point value, and the bad object should subtract 
points. 
1. In Target.cs, create a new p​ ublic int pointValue  - Tip:​ Here’s the beauty of variables at 
variable  work. Each target can have their own 
2. In each of the ​Target prefab’s​ inspectors, set the  unique pointValue! 
Point Value​ to whatever they’re worth, including 
the bad target’s ​negative value 
3. Add the new variable to U​ pdateScore(pointValue);  

public​ ​int​ pointValue;

private​ ​void​ ​OnMouseDown​() {


Destroy(gameObject);
gameManager.UpdateScore(​5​ ​pointValue​); } 
 
   

© Unity 2019 Lesson 5.2​ - Keeping Score 



Step 7: Add a Particle explosion 
The score is totally functional, but clicking targets is sort of… unsatisfying. To spice things up, 
let’s add some explosive particles whenever a target gets clicked! 
1. In Target.cs, add a new p ​ ublic ParticleSystem explosionParticle   
variable  
2. For each​ o​ f your target prefabs, assign a p
​ article prefab​ from 
Course Library > Particles​ to the ​Explosion Particle​ variable 
3. In the O
​ nMouseDown()​ function, i​ nstantiate​ a new explosion 
prefab 

public​ ParticleSystem explosionParticle;

private​ ​void​ ​OnMouseDown​() {


Destroy(gameObject);
​Instantiate(explosionParticle, transform.position,
​explosionParticle.transform.rotation);
gameManager.UpdateScore(5 pointValue); }

 
Lesson Recap 
New  ● There is a UI element for score on the screen 
Functionality  ● The player’s score is tracked and displayed by the score text when hit a 
target 
● There are particle explosions when the player gets an object 

New Concepts  ● TextMeshPro  


and Skills  ● Canvas 
● Anchor Points 
● Import Libraries 
● Custom methods with parameters 
● Calling methods from other scripts 

Next Lesson  ● We’ll use some UI elements again - this time to tell the player the game is 
over and reset our game! 
 
 

© Unity 2019 Lesson 5.2​ - Keeping Score 


 
 
 

5.3​ G​ ame Over 


 
Steps: 
Step 1: Create a Game Over text object  Example of project by end of lesson 
Step 2: Make GameOver text appear 

Step 3: Create GameOver function 

Step 4: Stop spawning and score on GameOver 

Step 5: Add a Restart button 

Step 6: Make the restart button work 

Step 7: Show restart button on game over   


 
 
Length:  60 minutes 

Overview:   We added a great score counter to the game, but there are plenty of other 
game-changing UI elements that we could add. In this lesson, we will create 
some “Game Over” text that displays when a “good” target object drops 
below the sensor. During game over, targets will cease to spawn and the 
score will be reset. Lastly, we will add a “Restart Game” button that allows 
the player to restart the game after they have lost. 

Project  When a “good” target drops below the sensor at the bottom of the screen, 
Outcome:  the targets will stop spawning and a “Game Over” message will display 
across the screen. Just underneath the “Game Over” message will be a 
“Reset Game” button that reboots the game and resets the score, so the 
player can enjoy it all over again. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Make UI elements appear and disappear with .SetActive 
- Use Script Communication and Game states to have a working “Game 
Over” screen 
- Restart the game using a UI button and Scene Management 

   

© Unity 2019 Lesson 5.3​ - Game Over 



Step 1: Create a Game Over text object 
If we want some “Game Over” text to appear when the game ends, the first thing we’ll do is 
create and customize a new UI text element that says “Game Over”.  
1. Right-click on the ​Canvas​, create a new ​UI >  - Tip:​ The center of the screen is the 
TextMeshPro - Text​ o ​ bject, and rename it “​Game  best place for this Game Over 
Over Text​”  message - it grabs the player’s 
attention  
2. In the inspector, edit its T ​ ext​, ​Pos X​, ​Pos Y​, F
​ ont 
Asset​, S
​ ize​, S
​ tyle​, ​Color​, and ​Alignment 
3. Set the “Wrapping” setting to “Disabled” 

 
 
 
Step 2: Make GameOver text appear 
We’ve got some beautiful Game Over text on the screen, but it’s just sitting and blocking our 
view right now. We should deactivate it, so it can reappear when the game ends. 
1. In GameManager.cs, create a new ​public  - Don’t worry:​ We’re just doing this 
TextMeshProUGUI gameOverText;​ and assign the  temporarily to make sure it works 
Game Over​ object to it in the inspector 
2. Uncheck​ the Active checkbox to ​deactivate​ the 
Game Over text by default 
3. In ​Start()​, activate the Game Over text 

public​ TextMeshProUGUI gameOverText;

void​ ​Start​() {
...
​gameOverText.gameObject.SetActive(​true​);​ }
 
   

© Unity 2019 Lesson 5.3​ - Game Over 



Step 3: Create GameOver function 
We’ve temporarily made the “Game Over” text appear at the start of the game, but we actually 
want to trigger it when one of the “Good” objects is missed and falls. 
1. Create a new ​public void GameOver()​ function, and ​move​ the code   
that activates the game over text inside it 
2. In Target.cs, call g
​ ameManager.GameOver()​ if a target collides 
with the ​sensor 
3. Add a new “​Bad​” tag to the B​ ad object​, add a condition that will 
only trigger game over if it’s n​ ot​ a bad object 

void​ ​Start​() {
... ​gameOverText.gameObject.SetActive(​true​);​ }

public​ ​void​ ​GameOver​() {


​gameOverText.gameObject.SetActive(​true​);​ }

<------>
private​ ​void​ ​OnTriggerEnter​(Collider other) {
Destroy(gameObject);
​if​ (!gameObject.CompareTag(​"Bad"​)) { gameManager.GameOver(); }​ } 
 
Step 4: Stop spawning and score on GameOver 
The “Game Over” message appears exactly when we want it to, but the game itself continues to 
play. In order to truly halt the game and call this a “Game Over’, we need to stop spawning 
targets and stop generating score for the player. 
1. Create a new ​public bool isGameActive;   
2. As the f​ irst line​ In S
​ tart()​, set ​isGameActive = true;​ and in 
GameOver()​, set ​isGameActive = false; 
3. To prevent spawning, in the ​SpawnTarget()​ coroutine, change 
while (true)​ to w​ hile (isGameActive) 
4. To prevent scoring, in Target.cs, in the ​OnMouseDown() 
function, add the condition ​if (gameManager.isGameActive) { 

public​ ​bool​ isGameActive;

void​ ​Start​() { ... ​isGameActive = ​true​;​ }

public​ ​void​ ​GameOver​() { ... ​isGameActive = ​false​;​ }

IEnumerator ​SpawnTarget​() { ​while​ (​true​ ​isGameActive​) { ... }


<------>
private​ ​void​ ​OnMouseDown​() {
​if​ (gameManager.isGameActive) {​ ... ​[all function code moved inside]​ ​}​} 

© Unity 2019 Lesson 5.3​ - Game Over 



Step 5: Add a Restart button 
Our Game Over mechanics are working like a charm, but there’s no way to replay the game. In 
order to let the player restart the game, we will create our first UI button 
1. Right-click on the ​Canvas​ and ​Create > UI > Button  - New Concept: 
2. Rename the button “​Restart Button​”  Buttons  
3. Temporarily r​ eactivate​ the Game Over text in order to reposition the 
Restart Button nicely with the text, then d​ eactivate​ it again  
4. Select the Text child object, then edit its ​Text​ to say “​Restart​”​, i​ ts 
Font, Style, a
​ nd ​Size 

 
 
Step 6: Make the restart button work 
We’ve added the Restart button to the scene and it LOOKS good, but now we need to make it 
actually work and restart the game. 
1. In GameManager.cs, add ​using  - New Concept:​ Scene Management  
UnityEngine.SceneManagement;  - New Concept:​ On Click Event 
2. Create a new ​void RestartGame()​ function that  - Don’t worry:​ The restart button is just 
sitting there for now, but we will fix it 
reloads the current scene 
later 
3. In the ​Button’s​ inspector, click ​+​ to add a new ​On 
Click event​, drag it in the G
​ ame Manager​ object 
and select the ​GameManager.RestartGame 
function 

using​ UnityEngine.SceneManagement;

void​ ​RestartGame​() {
​SceneManager.LoadScene(SceneManager.GetActiveScene().name); } 
 
   

© Unity 2019 Lesson 5.3​ - Game Over 



Step 7: Show restart button on game over 
The Restart Button looks great, but we don’t want it in our faces throughout the entire game. 
Similar to the “Game Over” message, we will turn off the Restart Button while the game is 
active. 
1. At the top of GameManager.cs add ​using UnityEngine.UI;  - Tip:​ Adding “using 
2. Declare a new ​public Button restartButton;​ and assign the  UnityEngine.UI” allows you to 
Restart Button​ to it in the inspector  access the Button class 
3. Uncheck​ the “Active” checkbox for the R ​ estart Button​ in 
the inspector 
4. In the ​GameOver​ function, activate the R
​ estart Button 

using​ UnityEngine.UI;  

public​ Button restartButton;

public​ ​void​ ​GameOver​() { ...


restartButton.gameObject.SetActive(​true​);​ } 

 
Lesson Recap 
New  ● A functional Game Over screen with a Restart button 
Functionality  ● When the Restart button is clicked, the game resets 

New Concepts  ● Game states  


and Skills  ● Buttons 
● On Click events 
● Scene management Library 
● UI Library 
● Booleans to control game states 

Next Lesson  ● In our next lesson, we’ll use buttons to really add some difficulty to our 
game 
 
 

© Unity 2019 Lesson 5.3​ - Game Over 


 
 
 

5.4​ W
​ hat’s the Difficulty? 
 
Steps: 
Example of project by end of lesson 
Step 1: Create Title text and menu buttons 

Step 2: Add a DifficultyButton script 

Step 3: Call SetDifficulty on button click 

Step 4: Make your buttons start the game 

Step 5: Deactivate Title Screen on StartGame 

Step 6: Use a parameter to change difficulty 


 
 
 
Length:  60 minutes 

Overview:   It’s time for the final lesson! To finish our game, we will add a Menu and Title 
Screen of sorts. You will create your own title, and style the text to make it 
look nice. You will create three new buttons that set the difficulty of the 
game. The higher the difficulty, the faster the targets spawn! 

Project  Starting the game will open to a beautiful menu, with the title displayed 
Outcome:  prominently and three difficulty buttons resting at the bottom of the screen. 
Each difficulty will affect the spawn rate of the targets, increasing the skill 
required to stop “good” targets from falling. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Store UI elements in a parent object to create Menus, UI, or HUD 
- Add listeners to detect when a UI Button has been clicked 
- Set difficulty by passing parameters into game functions like SpawnRate 

   

© Unity 2019 Lesson 5.4​ - What’s the Difficulty? 



Step 1: Create Title text and menu buttons 
The first thing we should do is create all of the UI elements we’re going to need. This includes a 
big title, as well as three difficulty buttons. 
1. Duplicate your ​Game Over text​ to create your ​Title  - Tip:​ You can position the title and 
Text, e
​ diting its name, text and all of its attributes  buttons however you want, but you 
2. Duplicate your ​Restart Button​ and edit its  should try to keep them central and 
visible to the player 
attributes to create an “​Easy Button​” button 
3. Edit and duplicate the new Easy ​button​ to create 
a“​Medium Button​” and a “​Hard Button​” 

 
 
Step 2: Add a DifficultyButton script 
Our difficulty buttons look great, but they don’t actually do anything. If they’re going to have 
custom functionality, we first need to give them a new script. 
1. For all 3 new buttons, in the Button component, in the ​On Click ()   
section, click the ​minus​ (​-)​ ​ ​button to remove the RestartGame 
functionality 
2. Create a new ​DifficultyButton.cs​ script and attach it to ​all 3 
buttons 
3. Add ​using UnityEngine.UI​ t​ o your imports 
4. Create a new ​private Button button;​ variable and initialize it in 
Start()  

using​ UnityEngine.UI;

private​ Button button;

void​ ​Start​() {
​button = GetComponent<Button>();​ }

   

© Unity 2019 Lesson 5.4​ - What’s the Difficulty? 



Step 3: Call SetDifficulty on button click 
Now that we have a script for our buttons, we can create a SetDifficulty method and tie that 
method to the click of those buttons 
1. Create a new ​void SetDifficulty​ function, and  - New Function:​ AddListener 
inside it, ​Debug.Log(gameObject.name + " was  - Don’t worry:​ onClick.AddListener is 
clicked");  similar what we did in the inspector 
with the Restart button 
2. Add the ​button listener​ to call the ​SetDifficulty 
- Don’t worry:​ We’re just using Debug for 
function  testing, to make sure the buttons are 
working 

void​ ​Start​() {
button = GetComponent<Button>();
​button.onClick.AddListener(SetDifficulty);​ }

void​ ​SetDifficulty​() {
​Debug.Log(gameObject.name + ​" was clicked"​); } 
 
Step 4: Make your buttons start the game 
The Title Screen looks great if you ignore the target objects bouncing around, but we have no 
way of actually starting the game. We need a StartGame function that can communicate with 
SetDifficulty. 
1. In GameManager.cs, create a new ​public void StartGame()  - Don’t worry:​ Title objects 
function and move everything from ​Start()​ into it  don’t disappear yet - we’ll 
2. In DifficultyButton.cs, create a new ​private GameManager  do that next 
gameManager;​ and initialize it in S ​ tart()  
3. In the ​SetDifficulty()​ function, call g
​ ameManager.startGame(); 

void​ ​Start​() { ​ ... ​ }

public​ ​void​ ​StartGame​() {


​isGameActive = ​true​;
​score = 0;
​StartCoroutine(SpawnTarget());
​UpdateScore(0);​ }

<------>
private​ GameManager gameManager;

void​ ​Start​ () { ...


gameManager = GameObject.Find(​"Game Manager"​).GetComponent<GameManager>(); }

SetDifficulty() { ... ​gameManager.startGame();​ } 

© Unity 2019 Lesson 5.4​ - What’s the Difficulty? 



Step 5: Deactivate Title Screen on StartGame 
If we want the title screen to disappear when the game starts, we should store them in an 
empty object rather than turning them off individually. Simply deactivating the single empty 
parent object makes for a lot less work. 
1. Right-click on the Canvas and ​Create > Empty Object​, rename it “​Title   
Screen​”, and drag the 3​ buttons​ and t​ itle​ onto it 
2. In GameManager.cs, create a new ​public GameObject titleScreen;​ and 
assign it in the inspector 
3. In ​StartGame()​, deactivate the title screen object 

public​ GameObject titleScreen;

StartGame() {
... ​titleScreen.gameObject.SetActive(​false​);​ } 
 
Step 6: Use a parameter to change difficulty 
The difficulty buttons start the game, but they still don’t change the game’s difficulty. The last 
thing we have to do is actually make the difficulty buttons affect the rate that target objects 
spawn. 
1. In DifficultyButton.cs, create a new ​public int difficulty ​variable, then  - New Concept: 
in the Inspector, assign the E ​ asy​ difficulty as 1, M
​ edium​ as 2, and  /= operator  
Hard​ as 3 
2. Add an ​int difficulty​ parameter to the S ​ tartGame()​ function 
3. In ​StartGame()​, set s
​ pawnRate /= difficulty; 
4. Fix the error in DifficultyButton.cs by passing the difficulty parameter 
to ​StartGame(int difficulty) 

public​ ​int​ difficulty;

void​ ​SetDifficulty​() {
... gameManager.startGame(​difficulty​); }

<------>
public​ ​void​ S
​ tartGame​(​int​ difficulty​) {
​spawnRate /= difficulty;​ } 
 
   

© Unity 2019 Lesson 5.4​ - What’s the Difficulty? 



Lesson Recap 
New  ● Title screen that lets the user start the game 
Functionality  ● Difficulty selection that affects spawn rate 

New Concepts  ● AddListener()  


and Skills  ● Passing parameters between scripts 
● Divide/Assign (/=) operator 
● Grouping child objects 

Next Lesson  ● In our next lesson, we’ll use buttons to really add some difficulty to our 
game 
 
 

© Unity 2019 Lesson 5.4​ - What’s the Difficulty? 


 
 
 
 

Challenge 5  
Whack-a-Food  

 
 
Challenge  Put your User Interface skills to the test with this whack-a-mole-like challenge 
Overview:   in which you have to get all the food that pops up on a grid while avoiding the 
skulls. You will have to debug buttons, mouse clicks, score tracking, restart 
sequences, and difficulty setting to get to the bottom of this one.  

Challenge  - All of the buttons look nice with their text properly aligned 
Outcome:  - When you select a difficulty, the spawn rate changes accordingly 
- When you click a food, it is destroyed and the score is updated in the 
top-left 
- When you lose the game, a restart button appears that lets you play again 

Challenge  In this challenge, you will reinforce the following skills/concepts: 


Objectives:  - Working with text and button objects to get them looking the way you want 
- Using Unity’s various mouse-related methods appropriately 
- Displaying variables on text objects properly using concatenation 
- Activating and deactivating objects based on game states 
- Passing information between scripts using custom methods and 
parameters 

Challenge  - Open​ your P ​ rototype 5 ​project 


Instructions:  - Download​ the "​Challenge​ 5 Starter Files" from the Tutorial Materials section, 
then double-click on it to ​Import 
- In​ the ​Project Window > Assets > Challenge 5 > I​ nstructions​ folder, use the 
"Challenge 5 - Outcome” video as a guide to complete the challenge 
   

© Unity 2019 Challenge 5 ​- Whack-a-Food 



 

Challenge  Task  Hint 


1  The difficulty buttons  Center the text on the buttons  If you expand one of the button 
look messy  horizontally and vertically  objects in the hierarchy, you’ll see a 
“Text” object inside - you have to edit 
the properties of that “Text” object 

2  The food is being  The food should only be  OnMouseEnter() detects when the 
destroyed too soon  destroyed when the player  mouse ​enters​ an object’s collider - 
clicks on it, not when the  OnMouseDown() detects when the 
mouse touches it  mouse ​clicks​ on an object’s collider 

3  The Score is being  It should always say,   When you set the score text, you have 
replaced by the word  “Score: __“ with the value  to add (concatenate) the word 
“score”  displayed after “Score:”  “Score: “ ​and​ the actual score value 

4  When you lose, there’s  Make the Restart button  In the GameOver() method, make 
no way to Restart  appear on the game over  sure the restart button is being 
screen  reactivated 

5  The difficulty buttons  When you click Easy, the  There is no information (or 
don’t do anything  spawnRate should be slower  parameter) being passed from the 
- if you click Hard, the  buttons’ script to the Game 
spawnRate should be faster  Manager’s script - you need to 
implement a difficulty parameter 

     
Bonus Challenge  Task  Hint 
X  The game can go on  Add a “Time: __” display that  Google, “Unity Count down timer C#”. 
forever  counts down from 60 in  It will involve subtracting 
whole numbers (i.e. 59, 58,  “Time.deltaTime” and using the 
57, etc) and triggers the  Mathf.Round() method to display only 
game over sequence when it  whole numbers. 
reaches 0. 
 
 
 
 
 
 
 
 
 
 

© Unity 2019 Challenge 5 ​- Whack-a-Food 


Challenge Solution 
1  Expand each of the “Easy”, “Medium”, and “Hard” buttons to access their “Text” object 
properties, then select the horizontal and vertical alignment buttons in the “Paragraph” 
properties 

2  In TargetX.cs, change OnMouseEnter() to OnMouseDown() 

  ​ own​() {
private​ ​void​ ​OnMouse​Enter D

3  In GameManagerX.cs, in UpdateScore(), concatenate the word “Score: “ with the score 


value: 

  public​ ​void​ ​UpdateScore​(​int​ scoreToAdd) {


score += scoreToAdd;
scoreText.text = ​"score" ​"Score: "​ + score​;
}

4  In GameManagerX.cs, in GameOver(), change SetActive(false) to “true” 

  public​ ​void​ ​GameOver​() {


gameOverText.gameObject.SetActive(​true​);
restartButton.gameObject.SetActive(​false t​ rue​);
...
}

5  In GameManagerX.cs, in StartGame(), add an “int difficulty” parameter and divide the 


spawnRate by it. Then in DifficultyButtonX.cs, in SetDifficulty(), pass in the “difficulty” 
value from the buttons. 

  GameManagerX.cs DifficultyButtonX.cs
public​ ​void​ S
​ tartGame​(​int​ difficulty){ void​ ​SetDifficulty​() {
spawnRate /= ​5 d ​ ifficulty​; ...
... gameManagerX.StartGame(​difficulty​);
} }

© Unity 2019 Challenge 5 ​- Whack-a-Food 


Bonus Challenge Solution 


X1  Duplicate the “Score Text” object in the hierarchy to create a new “Timer text” object, then in 
GameManagerX.cs declare a new ​TextMeshProUGUI timerText​ variable and assign it in the 
inspector 

X2  In GameManagerX.cs, in StartGame(), set your new timerText variable to your starting time 

  public​ ​void​ ​StartGame​(​int​ difficulty) {


...
​timeLeft = 60;
}

X3  In GameManagerX.cs, add an Update() function that, if the game is active, subtracts from the 
timeLeft and sets the timerText to a rounded version of that timeLeft. Then, if timeLeft is less 
than zero, calls the game over method. 

  private​ ​void​ ​Update​() {


​if​ (isGameActive) {
timeLeft -= Time.deltaTime;
timerText.SetText(​"Time: "​ + Mathf.Round(timeLeft));
​if​ (timeLeft < 0) {
GameOver();
}
}
}
 
 

© Unity 2019 Challenge 5 ​- Whack-a-Food 


 
 
 

Unit 5 Lab  
Swap out your Assets 
 
Steps:  Example of progress by end of lab 
Step 1: Import and browse the asset library 

Step 2: Replace player with new asset 

Step 3: Browse the Asset store 

Step 4: Replace all non-player primitives 

Step 5: Replace the background texture 


   
 
Length:  90 minutes 

Overview:   In this lab, you will finally replace those boring primitive objects with 
beautiful dynamic ones. You will either use assets from the provided course 
library or browse the asset store for completely new ones to give your game 
exactly the look and feel that you want. Then, you will go through the process 
of actually swapping in those new assets in the place of your placeholder 
primitives. By the end of this lab, your project will be looking a ​lot​ better. 

Project  All primitive objects are replaced by actual 3D models, retaining the same 
Outcome:  basic gameplay functionality.  

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Browse the asset store to find the perfect assets for your project 
- Use Nested Prefabs to swap out placeholder objects with real assets 
- Adjust material settings to get the resolution and look you want 

   

© Unity 2019 Lab 5​ - Swap out your Assets 



Step 1: Import and browse the asset library 
If we are going to swap out our primitive shapes with cool new assets, we need to import those 
assets first. 
1. Click on the ​link ​to download the C​ ourse Library  - Don’t worry:​ It will take longer than 
asset files, then i​ mport​ them into your project   normal to import these files because it’s 
2. Close​ the ​Asset Store ​window  a lot more files 
3. Browse through the library to find the assets you  - Don’t worry:​ Even if you don’t think 
would like to replace your Player and non-player  you’re going to use one of these assets 
objects with  for your player, just choose something 
for now to get used to the process 

 
Step 2: Replace player with new asset 
Now that we have the assets ready to go, the first thing we’ll do is replace the Player object 
1. Drag​ the Player object into the “Prefabs” folder to make it  - New:​ Nested Prefabs 
a prefab, then ​double-click​ on it to open the prefab editor  - Tip:​ Notice how the asset 
2. Drag​ the asset you want into the​ hierarchy​ to make it a  updates automatically in game 
view 
nested prefab of the Player, then s ​ cale​ and ​position​ it so 
- Tip:​ Isometric view is useful 
that it is around the same size and location  when resizing and 
3. On the parent P ​ layer​ object itself, either ​Edit​ the collider to  repositioning child objects 
be the size of the new asset or r​ eplace​ it with a different 
type of collider (e.g. Box)  
4. Test​ testing to make sure it works, then u ​ ncheck​ the 
Mesh Renderer ​component of the primitive 

© Unity 2019 Lab 5​ - Swap out your Assets 



Step 3: Browse the Asset store  
Even though we have a really great asset library, there may be certain assets you want that 
aren’t in there. In that case, it might be good to try and find assets in the Unity Asset Store. 
1. From the top menu, click ​Window > A ​ sset Store​ to  - Warning:​ This will only be possible if 
open the Asset Store window in Unity, then  you can sign into a Unity account  
right-click on the tab and ​Maximize​ it to make it  - Explain: ​The assets for this course 
easier to browse  were made by Synty Studios, which 
2. In the ​Publisher​ filter, search for “Synty Studios”,  are really good - as you can see, you 
then browse some of their asset packs  normally have to pay for them 
3. In the ​Pricing​ filter, drag the right handle back to  - New:​ Unity Asset Store 
only view “Free” assets, r​ emove ​the Synty Studios  - New:​ “Low Poly” assets 
filter, and search for “​Low Poly​”  - Warning:​ Only download “Low Poly” 
4. If you see something you want to include in your  assets or your project will become 
project, d​ ownload​ and i​ mport​ it into your project  huge​, then not web- or 
5. Drag​ the imported assets into a new folder called  mobile-friendly 
“​Asset Store​”,​ then browse through the imported  - Don’t worry:​ Even if you think you 
assets   have all the assets you need, it’s still 
good to take a look 

 
 
Step 4: Replace all non-player primitives 
Now that we know the basic concept of our project, let’s figure out how we’ll get it done. 
1. Repeat the process you used to replace the player  - Warning:​ Make sure that, if you are 
prefab with your other non-player objects  editing prefabs in the scene, to 
2. Test to make sure everything is working as expected  Override any changes you make  

 
 

© Unity 2019 Lab 5​ - Swap out your Assets 



Step 5: Replace the background texture 
Now that our dynamic objects have a new look, we should update the ground / background too. 
1. From the C​ ourse Library ​> Textures​, (or from a Unity  - Tip:​ You might want to adjust the 
Asset Store package), drag a new material onto the  resolution/tiling of the material, 
Ground / Background object  depending on the scale of the 
2. To adjust the material’s r​ esolution​, in the Material  objects 
properties (with the sphere next to it), change the  - Tip:​ Natural ground materials like 
Main Map ​Tiling​ X and Y values  grass or dirt do not tend to show 
3. To make the material less shiny, in the Material  highlights or reflections 
properties, ​uncheck​ the “Specular highlights” and 
“Reflections” settings  

 
 
 
Lesson Recap 
New Progress  ● Primitive objects replaced with new assets that function the same way 

New Concepts  ● Art workflow 


and Skills  ● High vs. Low Poly 
● Asset Store 
● Nested Prefabs 
● Material properties 
 
 

© Unity 2019 Lab 5​ - Swap out your Assets 


 
 
 

Quiz ​ ​Unit 5  


 
QUESTION    CHOICES 
 
1  Which of the following follows Unity naming conventions    a. Line 1 
(especially as they relate to capitalization)?  b. Line 2 
c. Line 3 
1. public​ ​void​ ​MultiplyScore​(​int​ currentScore) { } d. Line 4 
2. public​ ​void​ ​multiplyScore​(​int​ CurrentScore) { }
3. public​ ​Void​ ​MultiplyScore​(​Int​ currentScore) { }
4. public​ ​Void​ ​MultiplyScore​(​int​ CurrentScore) { }

 
2  If there is a boolean in script A that you want to access    a. 1 only  
in script B, which of the following are true:  b. 1 and 2 only 
c. 2 and 3 only  
  1. You need a reference to script A in script B    d. 3 and 4 only 
2. The boolean needs to be public  e. 1, 2, and 3 only 
3. The boolean must be true  f. All are true 
4. The boolean must be included in the Update method 
 
3  Which code to fill in the blank will result in the object    a. name = “player” &&  
being destroyed?  isDead && health < 5 
b. name != “player”  
string name = “player” && isDead != true && health > 5 
bool isDead; c. name == “player” && !isDead 
float health = 3;
&& health < 5 
d. name == “player” && isDead != 
if (________________) {
Destroy(gameObject);
true && health > 5 
}

© Unity 2019 Quiz​ - Unit 5 



 
4  You run your game and get the following error message    a. In the hierarchy, rename “Game 
in the console, “NullReferenceException: Object  Manager” to “gameManager” 
reference not set to an instance of an object”. Given the  b. In the hierarchy, rename “Game 
image and code below, what would resolve the problem?  Manager” as “GameManager” 
c. On Line 1, rename 
“GameManager” as “Game 
Manager” 
d. On Line 3, remove the 
GetComponent code  

 
1. private​ GameManager gameManager;
2. void​ ​Start​() {
3. gameManager = GameObject.Find(​"GameManager"​).GetComponent<GameManager>();
4. }

 
5  Read the Unity documentation below about the    a. 0 
OnMouseDrag event and the code beneath it. What will  b. 1 
the value of the “counter” variable be if the user clicked  c. 99 
and held down the mouse over an object with a collider  d. 100 
for 10 seconds?  e. A value over 100 

int​ counter = 0;
void​ ​OnMouseDrag​() {
​if​ (counter < 100) {
counter++;
}
}

© Unity 2019 Quiz​ - Unit 5 



 
6  Based on the code below, what will be displayed in the    a. “Welcome, Robert Smith” 
console when the button is clicked?  b. “Welcome, firstName Smith” 
c. “Button is ready” 
d. “Welcome + Robert + Smith” 
  private​ Button button;
private​ ​string​ firstName = ​"Robert"​;

void​ ​Start​() {
button = GetComponent<Button>();
button.onClick.AddListener(DisplayWelcomeMessage);
Debug.Log(​"Button is ready"​);
}

void​ ​DisplayWelcomeMessage​() {
Debug.Log(​"Welcome, "​ + ​"firstName"​ + ​" Smith"​);

 
7  You have declared a new Button variable as “private    a. You can’t name a button “start” 
Button start;”, but there’s an error under the word  because that’s the name of a 
“Button” that says “error CS0246: The type or  Unity Event Function 
namespace name 'Button' could not be found (are you  b. “Button” should be lowercase 
missing a using directive or an assembly reference?)”  “button” 
c. You are missing “using 
UnityEngine.UI;” from the top of 
your class 
d. New Button variables must be 
made public 

 
8  Look at the documentation and code below. Which of    a. Line 5 
the following lines would ​NOT ​produce an error?  b. Line 6 
c. Line 7 
d. Line 8 

© Unity 2019 Quiz​ - Unit 5 


1. public​ Vector3 explosion;


2. Vector3​ startPos;
3. float​ startSpeed;
4. void​ Start {
5. AddForceAtPosition(50, 0, ForceMode.Impulse)
6. AddForceAtPosition(100, startPos, ForceMode.Impulse)
7. AddForceAtPosition(startSpeed, startPos, ForceMode.Impulse)
8. AddForceAtPosition(explosion, ​new​ Vector3(0, 0, 0), ForceMode.Impulse)
9. }

 
9  If you wanted a button to display the message, “Hello!”    a. (SendMessage); 
when a button was clicked, what code would you use to  b. (SendMessage(“Hello”)); 
fill in the blank?  c. (SendMessage(string Hello)); 
d. (SendMessage(Hello)); 
private​ Button button;
void​ Start {
button = GetComponent<Button>();
button.onClick.AddListener________________;
}
void​ ​SendMessage​() {
Debug.Log(​”Hello!”​);
}

 
10  Which of the following is the correct way to declare a    a. Line 1 
new List of game objects named “enemies”?  b. Line 2 
c. Line 3 
1. public​ ​List​[GameObjects] enemies; d. Line 4 
2. public​ ​List​(GameObject) ​"enemies"​;
3. public​ ​List​<GameObjects> ​"enemies"​;
4. public​ ​List​<GameObject> enemies;
 

© Unity 2019 Quiz​ - Unit 5 


Quiz ​ A​ nswer Key 


 
#    ANSWER  EXPLANATION 
   
1    A  public void MultiplyScore(int currentScore) 
The “public”, “void”, and “int” keywords should be lowercase. Method names 
(like “MultiplyScore”) should be Title Case. variable names (like 
“currentScore”) should be camelCase. 

2    B  You always need a variable reference to the script you’re trying to access and 
that variable must be public. 

3    C  To compare a string, two ==’s are needed. By default, booleans are false 
unless declared as true and adding an exclamation mark before !isDead 
checks that it’s false. Since health = 3, checking “health < 5” is true. 

4    B  GameObject.Find("GameManager") is returning a NullReferenceException 


error because there’s no object in the scene named that. If you renamed the 
“Game Manager” in the hierarchy to have no spaces, it would be fixed. 

5    D  Since the function is called “every frame” the mouse is held, it will be called 
hundreds of times in 10 seconds. However, the condition will only be true if 
the counter is less than 99, meaning it will no longer increase after 100. 

6    B  If you wanted it to say “Robert Smith”, you would have needed to use the 
variable name, firstName, ​without​ quotation marks. 

7    C  In order to use some of the UI classes like “Button,” you need to include the 
“UnityEngine.UI” library 

8    D  The first two required parameters are Vector3 variables. Only option D uses 
Vector3 variables for those parameters. 

9    A  SendMessage does not require any parameters - it prints “Hello” no matter 


what when it is called. Also, when adding a listener, you just need to include 
the method’s name - no parentheses are required. 

10    D  public List<GameObject> enemies is correct. <GameObject> should be in 


angle brackets. You don’t need “GameObject” to be plural because it’s the 
type​ of object it is. Variable names are never declared with quotation marks 
around them. 
 

© Unity 2019 Quiz​ - Unit 5 


 
 
 

6.1​ P​ roject Optimization  


 
Techniques: 
1: Variable attributes 
 
2: Unity Event Functions   
3: Object Pooling 
 
 
Length:  30 minutes 

Overview:   In this lesson, you will learn about a variety of different techniques to 
optimize your projects and make them more performant. You may not notice 
a huge difference in these small prototype projects, but when you’re 
exporting a larger project, especially one for mobile or web, every bit of 
performance improvement is critical.  

Project  Several of your prototype projects will have improved optimization, serving 
Outcome:  as examples for you to implement in your personal projects 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Recognize and use new variable attributes to keep values private, but still 
editable in the inspector 
- Use the appropriate Unity Event Functions (e.g. Update vs. FixedUpdate vs. 
LateUpdate) to make your project run as smoothly as possible 
- Understand the concept of Object Pooling, and appreciate when it can be 
used to optimize your project 

   

© Unity 2019  Lesson 6.1​ - Project Optimization  



1: Variable attributes 
In the course, we only ever used “public” or “private” variables, but there are a lot of other variable 
attributes you should be familiar with. 
1. Open your ​Prototype 1​ project and open the  - New Concept:​ using [SerializeField] 
PlayerController.cs​ script  instead of public attribute 
2. Replace the keyword “private” with ​[SerializeField]​,  - Tip: ​“protected” is very similar to 
“private”, but would also allow 
then edit the values in the inspector 
access to derived classes  
3. In ​FollowPlayer.cs​, add the [​ SerializeField] ​attribute to 
the Vector3 o​ ffset​ variable 
4. Try applying the “​readonly​”, “​const​”, or “​static​” 
attributes, noticing that all have the effect of removing 
the variable from the inspector 

​ rivate​ f
[​SerializeField​]​ p ​ loat​ speed = 30.0f;
[​SerializeField​]​ p​ rivate​ f​ loat​ turnSpeed = 50.0f;

[​SerializeField​]​ ​private​ Vector3​ offset = new Vector3(0, 5, -7);


 
 
2: Unity Event Functions 
In the course we only ever used the default Update() and Start() event functions, but there are others 
you might want to use in different circumstances 
1. Duplicate​ your main Camera, rename it “​Secondary  - New Concept:​ “Event Functions” 
Camera​”, then d​ eactivate​ the Main Camera  are Unity’s default methods that 
2. Reposition​ the Secondary camera in a first-person  run in a very particular order over 
the life of a script (e.g. Start and 
view, then edit the ​offset variable t​ o match that 
Update) 
position  - New Concept: U ​ pdate vs 
3. Run your project and notice how choppy it is  FixedUpdate vs LateUpdate 
4. In ​PlayerController​.cs, change “Update” to  - New Concept: A ​ wake vs Start 
“​FixedUpdate​”, and in ​FollowPlayer​.cs, change  - Tip:​ If you’re not using Start or 
“Update” to “​LateUpdate​”, then ​test again  Update, it’s cleaner to delete them 
5. Delete​ the Start() function in both scripts, then 
reactivate your Main Camera 

PlayerController.cs  
void​ ​Fixed​Update​() { ...

FollowPlayer.cs
void​ ​Late​Update​() { ...
 
 
© Unity 2019  Lesson 6.1​ - Project Optimization  

3: Object Pooling 
Throughout the course, we’ve created a lot of prototypes that instantiated and destroyed objects during 
gameplay, but there’s actually a more performant / efficient way to do that called Object Pooling. 
1. Open ​Prototype 2​ and create a backup   - Warning​: You will be overwriting your old work 
2. Download​ the ​Object Pooling u ​ nity  with this new system, so it’s important to make a 
package​ a ​ nd i​ mport​ it into your scene  backup first in case you want to revert back 
- New Concept​: Object Pooling: creating a 
3. Reattach the P ​ layerController​ script to 
reusable “pool” of objects that can be activated 
your player and reattach the  and deactivated rather than instantiated and 
DetectCollisions​ script to your animal  destroyed, which is much more performant 
prefabs (​not​ to your food prefab)  - Tip​: Try reading through the new code in the 
4. Attach the O ​ bjectPooler ​script to your  ObjectPooler and PlayerController scripts 
Spawn Manager, drag your projectile  - Don’t worry​: If your project is small enough that 
into the “​Objects To Pool​” variable, and  you’re not experiencing any performance issues, 
you probably don’t have to implement this 
set the “​Amount To Pool​” to 20  
5. Run​ your project and see how the 
projectiles are activated and deactivated 

 
 
Lesson Recap 
New Concepts  ● Optimization 
and Skills  ● Serialized Fields 
● readonly / const / static / protected  
● Event Functions 
● FixedUpdate() vs. Update() vs. LateUpdate() 
● Awake() vs. Start() 
● Object Pooling 
 
 

© Unity 2019  Lesson 6.1​ - Project Optimization  


 
 
 

6.2​ R​ esearch and Troubleshooting  


 
Example of project by end of lesson 
Steps: 
Step 1: Make the vehicle use forces 

Step 2: Prevent car from flipping over 

Step 3: Add a speedometer display 

Step 4: Add an RPM display 

Step 5: Prevent driving in mid-air 


   
 
 
Length:  75 minutes 

Overview:   In this lesson, you will attempt to add a speedometer and RPM display for 
your vehicle in Prototype 1. In doing so, you will learn the process of doing 
online research when trying to implement new features and troubleshoot 
bugs in your projects. As you will find out, adding a new feature is very rarely 
as simple as it initially seems - you inevitably run into unexpected 
complications and errors that usually require a little online research. In this 
lesson, you will learn how to do that so that you can do it with your own 
projects. 

Project  By the end of this lesson, the vehicle will behave with more realistic physics, 
Outcome:  and there will be a speedometer and Revolution per Minute (RPM) display.,  

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Use Unity Forums, Unity Answers, and the online Unity Scripting 
Documentation to implement new features and troubleshoot issues with 
your projects 

   

© Unity 2019 Lesson 6.2​ - Using Unity’s Online Resources  



Step 1: Make the vehicle use forces 
If we’re going to implement a speedometer, the first thing we have to do is make the vehicle accelerate 
and decelerate more like a real car, which uses forces - as opposed to the Translate method.  
1. Open your ​Prototype 1​ project and make a backup  - New Concept:​ using Unity 
2. Replace the Translate call with an AddForce call on  Documentation 
the vehicle’s Rigidbody, renaming the “speed” variable  - New Concept: u ​ sing Unity Answers 
- New Concept: A ​ ddRelativeForce 
to “​horsePower​” 
- Don’t worry:​ Still a big issue where 
3. Increase the h​ orsePower​ to be able to actually move  the vehicle can drive in air and that 
the vehicle  it flips over super easily! 
4. To make the vehicle move in the appropriate direction, 
change AddForce to AddRelativeForce 

private​ Rigidbody playerRb;

void​ ​Start​() {
​playerRb = GetComponent<Rigidbody>();
}

void​ ​FixedUpdate​() {
​transform.Translate(Vector3.forward * speed * verticalInput);
​playerRb.AddRelativeForce(Vector3.forward * verticalInput * horsePower);
}

 
 
   

© Unity 2019 Lesson 6.2​ - Using Unity’s Online Resources  



Step 2: Prevent car from flipping over 
Now that we’ve implemented real physics on the vehicles, it is very easy to overturn. We need to figure 
out a way to make our vehicle safer to drive.  
1. Add wheel colliders to the wheels of your vehicle and  - New Concept:​ Wheel colliders 
edit their radius and center position, then disable any  - New Concept: C ​ enter of Mass 
other colliders on the wheels  - Don’t Worry​: We can still drive the 
vehicle when it’s sideways or 
2. Create a new ​GameObject centerOfMass​ variable, then 
upside down 
in Start(), assign the playerRb variable to the  - Warning:​ This is still not the ​proper 
centerOfMass position  way to do vehicles - should actually 
3. Create a new ​Empty Child o ​ bject for the vehicle called  be rotating / turning the wheels 
“​Center Of Mass​”, reposition it, and assign it to the 
Center Of Mass v​ ariable in the inspector 
4. Test​ different center of mass positions, speed, and 
turn speed values to get the car to steer as you like 

[​SerializeField​] GameObject centerOfMass;

void ​Start​() {
​playerRb.centerOfMass = centerOfMass.transform.position;
}
 
Step 3: Add a speedometer display 
Now that we have our vehicle in a semi-drivable state, let’s display the speed on the User Interface. 
1. Add a new ​TextMeshPro - Text​ object for your “Speedometer Text”  - Warning​: Will be going 
2. Import the​ T
​ MPro​ l​ ibrary​, then create and assign new create a  fast through adding 
new ​TextMeshProUGUI v​ ariable for your ​speedometerText   the text, since we did 
this in prototype 5 
3. Create a new float variables for your​ speed  
- New Concept: 
4. In Update(), ​calculate​ the speed in mph or kph then d ​ isplay​ those  RoundToInt 
values on the UI 

using​ TMPro;

[​SerializeField​] TextMeshProUGUI speedometerText;


[​SerializeField​] ​float​ speed;

private​ ​void​ ​Update​() {


​speed = Mathf.Round(playerRb.velocity.magnitude * 2.237f); ​// 3.6 for kph
​speedometerText.SetText(​"Speed: "​ + speed + ​"mph"​);
}
 

© Unity 2019 Lesson 6.2​ - Using Unity’s Online Resources  



Step 4: Add an RPM display 
One other cool feature that a lot of car simulators have is a display of the RPM (Revolutions per Minute) 
- the tricky part is figuring out how to calculate it.  
1. Create a new “​RPM Tex​t” object, then c ​ reate​ and  - New Concept:​ Modulus / Remainder 
assign​ a new r​ pmText variable​ for it  (%) operator 
2. In Update(), calculate the the RPMs using the 
Modulus/Remainder operator (%), then display that 
value on the UI 

[​SerializeField​] TextMeshProUGUI rpmText;


[​SerializeField​] ​float​ rpm;

private​ ​void​ ​Update​() {


​rpm = Mathf.Round((speed % 30)*40);
​rpmText.SetText(​"RPM: "​ + rpm);

 
   

© Unity 2019 Lesson 6.2​ - Using Unity’s Online Resources  



Step 5: Prevent driving in mid-air 
Now that we have a mostly functional vehicle, there’s one other big bug we should try to fix: the car can 
still accelerate/decelerate, turn, and increase in speed/rpm in mid-air! 
1. Declare a new ​List​ of W​ heelColliders​ named a​ llWheels​ (or  - New Concept:​ looping 
frontWheels/backWheels), then assign each of your wheels  through lists  
to that list in the inspector  - New Concept​: custom 
methods with bool returns 
2. Declare a new ​int​ w​ heelsOnGround 
- Tip​: if you use frontWheels or 
3. Write a ​bool IsOnGround()​ method that returns true if all  backWheels, make sure you 
wheels are on the ground and false if not  only drag in two wheels and 
4. Wrap the ​acceleration​, ​turning​, and ​speed/rpm​ functionality  only test that 
in if-statements that check if the car is on the ground  wheelsOnGround == 2 

[​SerializeField​] List<WheelCollider> allWheels;


[​SerializeField​] ​int​ wheelsOnGround;

if​ (IsOnGround()) {​[ACCELERATION], [ROTATION], [SPEED/RPM]​}

bool​ ​IsOnGround​ () {
wheelsOnGround = 0;
​foreach​ (WheelCollider wheel ​in​ allWheels) {
​if​ (wheel.isGrounded) {
wheelsOnGround++;
}
}
​if​ (wheelsOnGround == 2) {
​return​ ​true​;
} ​else​ {
​return​ ​false​;
}
}
 
Lesson Recap 
New Concepts  ● Searching on Unity Answers, Forum, Scripting API 
and Skills  ● Troubleshooting to resolve bugs 
● AddRelativeForce, Center of Mass, RoundToInt 
● Modulus/Remainder (%) operator 
● Looping through lists 
● Custom methods with bool return 
 

© Unity 2019 Lesson 6.2​ - Using Unity’s Online Resources  


 
 
 

6.3​ S​ haring your Projects 


 
Example of project by end of lesson 

Steps: 
Step 1: Install export Modules 

Step 2: Build your game for Mac or Windows 

Step 3: Build your game for WebGL 


 

 
 
 
Length:  30 minutes 

Overview:   In this lesson, you will learn how to build your projects so that they’re 
playable outside of the Unity interface. First, you will install the necessary 
export modules to be able to publish your projects. After that, you will build 
your project as a standalone app to be played on Mac or PC computers. 
Finally, you will export your project for WebGL and even upload it to a game 
sharing site so that you can send it to your friends and family. 

Project  Your project will be exported and playable as a standalone app on Mac/PC or 
Outcome:  for embedding online. 

Learning  By the end of this lesson, you will be able to: 


Objectives:  - Add and manage export modules for your Unity installs so you can choose 
which platforms to build for 
- Build your projects for Mac or PC so they can be played as standalone 
apps 
- Build your projects for WebGL so they can be uploaded and embedded 
online and shared with a single URL 

   

© Unity 2019 Lesson 6.3​ - Sharing your Projects 



Step 1: Install export Modules 
Before we can export our projects, we need to add the “Export Modules” that will allow us to export for 
particular platforms. 
1. Open ​Unity Hub​ and click to ​Add Modules​ to the  - Tip​ - Mac and Windows will create 
version of Unity you have used in the course  apps for your computer and WebGL 
2. Select W
​ ebGL Build Support​, and either M​ ac​ or  will allow you to publish online 
- Tip​ - you should see little icons 
Windows ​build support, then click ​Done​ and wait for 
appear when it is complete 
the installation to complete  - Tip​ - WebGL is nice because you 
can more easily share it online and 
it is platform-independent 

 
   

© Unity 2019 Lesson 6.3​ - Sharing your Projects 



Step 2: Build your game for Mac or Windows 
Now that we have the export modules installed, we can put them to use and export one of our projects 
1. Open​ the project you would like to build (could be a  - Don’t worry​ - a prototype that’s not 
prototype or your personal project)  fully playable will be problematic 
2. In Unity, click ​File > Build Settings, t​ hen click A
​ dd  when you share it because the user 
will have to close and reopen it to 
Open Scenes​ to add your scene 
play it again, but that’s OK for now 
3. Click P​ layer Settings​ and adjust any settings you  - Tip​ - since it’s just a mini-game, it 
want, including making it “Windowed”, “Resizable”,  might be better to use “Windowed” 
and whether or not you want to enable the “Display  - this also allows the player to more 
Resolution Dialog”  easily exit since we don’t have a 
4. Click B ​ uild​, name your project, and save it inside a  full UI to do that 
new folder inside your Create with Code folder called  - Don’t worry​ - on Windows, you have 
an .exe file and a Data folder - on 
“​Builds​”  Mac, you just have a .app file 
5. Play​ your game to test it out, then if you want, ​rebuild  - Warning​ - it’s kind of hard to 
it with different settings  distribute these as is because 
most email clients are cautious of 
executables like this 

© Unity 2019 Lesson 6.3​ - Sharing your Projects 



Step 3: Build your game for WebGL 
Since it is pretty hard to distribute your games on Mac or Windows, it’s a good idea to make your 
projects available online by building for WebGL. 
1. Reopen the B ​ uild Settings​ menu, select W
​ ebGL​,  - Warning​ - it’s easy to forget to click 
then click ​Switch Platform  “Switch platform” and can be confusing 
2. Click B
​ uild​, then save in your “Builds” folder with “  - Don’t worry​ - building for WebGL can 
take a long time 
- WebGL”​ in the name  
- Warning​ - some browsers do not 
3. Try clicking on ​index.html​ to run your project (you  support opening WebGL programs from 
may have to try opening with different browsers)   your computer 
4. Right-click on your WebGL build folder and  - Tip​ - If uploading your game to a site 
Compress/Zip​ it into a .zip file  like itch.io, make sure to choose 
5. If you want, ​upload​ it to a game sharing site like  “HTML” format and to “Play in browser” 
itch.io 

 
 
Lesson Recap 
New Concepts  ● Installing export modules  
and Skills  ● Building for Mac/PC 
● Building for WebGL/HTML 
 

© Unity 2019 Lesson 6.3​ - Sharing your Projects 

You might also like