Unity All Lesson Plans
Unity All Lesson Plans
Steps:
Step 1: Download and install Unity Hub
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.
Lesson Recap
New Progress ● Unity Hub, Unity Editor 2018+, and Visual Studio installed
● Signed into Unity Hub
Next Lesson ● We will actually create a new project and open the Unity Editor to start
creating
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.
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
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”
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
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
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
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.
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
}
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);
}
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
Lesson Recap
New ● Vehicle moves down the road at a constant speed
Functionality ● When the vehicle collides with obstacles, they fly into the air
Next Lesson ● We’ll add some code to our camera, so that it follows the player as they
drive along the road.
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.
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
void Update()
{
transform.position = player.transform.position;
}
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
void Update()
{
transform.position = player.transform.position + new Vector3(0, 5, -7)
offset;
}
Lesson Recap
New ● Camera follows the vehicle down the road at a set offset distance
Functionality
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.
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.
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
void Update()
{
horizontalInput = Input.GetAxis("Horizontal");
loat horizontalInput;
public f
public f loat forwardInput;
void Update()
{
horizontalInput = Input.GetAxis("Horizontal");
forwardInput = Input.GetAxis("Vertical");
void Update()
{
horizontalInput = Input.GetAxis("Horizontal");
forwardInput = Input.GetAxis("Vertical");
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
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!
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.
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.
Challenge Solution
1 In PlayerControllerX.cs, in Update, change V
ector3.back to Vector3.forward
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:
© Unity 2019 Challenge 1 - Plane Programming
4
X2 In RotatePropellerX.cs, add a new propellorSpeed variable and Rotate the propeller on the Z
axis
void Update() {
transform.Rotate(Vector3.forward, propellorSpeed * Time.deltaTime);
}
Unit 1 Lab
Project Design Document
Steps: Example of progress by end of lab
Step 1: Understand what a Personal Project is
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.
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
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
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
Lesson Recap
New Progress ● Completed your project concept and production timeline
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]
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
3
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?
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.
5 A “public float speed” would be visible because it has the “public” modifier
applied to it
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.
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.
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
3
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
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);
}
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);
}
}
Next Lesson ● We’ll learn how to create and throw endless amounts of food to feed our
animals!
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.
© Unity 2019 Lesson 2.2 - Food Flight
2
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
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
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);
}
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
void U pdate() {
if (transform.position.z > topBound) {
Destroy(gameObject); }}
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
Next Lesson ● Instead of dropping all these animal prefabs onto the scene, we’ll create a
herd of animals roaming the plain!
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.
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
void U pdate() {
if (Input.GetKeyDown(KeyCode.S)) {
Instantiate(animalPrefabs[animalIndex], new Vector3(0, 0, 20),
animalPrefabs[animalIndex].transform.rotation);
}
}
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
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); }}
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
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.
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
3
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 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
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
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
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.
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
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);
}
}
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)
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);
}
Unit 2 Lab
New Project with Primitives
Steps:
Example of progress by end of lab
Step 1: Create a new Unity Project
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.
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
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
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”)
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
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);
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”);
2 C Since the “health” variable is an int, anything less than 1 would be “0”. The
sign for “less than” is “<”.
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).
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.
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.
Step 2: Choose and set up a player character Example of project by end of lesson
Step 3: Make player jump at start
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.
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
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 * 100,
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
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; }
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
void Start() {
Instantiate(obstaclePrefab, spawnPos, obstaclePrefab.transform.rotation); }
© Unity 2019 Lesson 3.1 - Jump Force
6
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
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!
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
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.
© Unity 2019 Lesson 3.2 - Make the World Whiz By
2
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
void Start() {
startPos = transform.position; }
void U pdate() {
if (transform.position.x < startPos.x - 50) {
transform.position = startPos; } }
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
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
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
5
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
void U pdate() {
if (playerControllerScript.gameOver == false) {
transform.Translate(Vector3.left * Time.deltaTime * speed); }
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
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
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.
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
void U pdate() {
if (Input.GetKeyDown(KeyCode.Space) && isOnGround && !gameOver) {
playerRb.AddForce(Vector3.up * 10 jumpForce, ForceMode.Impulse);
isOnGround = false;
animator.SetTrigger("Jump_trig"); } }
Next Lesson ● We’ll really polish this game up to make it look nice using particles and
sound effects!
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.
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
void U pdate() {
if (Input.GetKeyDown(KeyCode.Space) && isOnGround && !gameOver) {
... dirtParticle.Stop(); } }
void Start() {
... playerAudio = GetComponent<AudioSource>(); }
void U pdate() {
if (Input.GetKeyDown(KeyCode.Space) && isOnGround && !gameOver) {
... playerAudio.PlayOneShot(jumpSound, 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
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.
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!
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);
}
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)
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:
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
Unit 3 Lab
Player Control
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.
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
3
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.
By the end of this step, the player’s movement should be constrained in such a way that makes your
game playable.
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
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”)
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
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);
}
}
}
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;
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.
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.
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.
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.
4.1 W
atch Where You’re Going
Steps:
Example of project by end of lesson
Step 1: Create project and open scene
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.
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
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
void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
transform.Rotate(Vector3.up, horizontalInput * rotationSpeed * Time.deltaTime);
}
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
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
5
Lesson Recap
New ● Camera rotates around the island based on horizontal input
Functionality ● Player rolls in direction of camera based on vertical input
Next Lesson ● In the next lesson, we’ll add more challenge to the player, by creating
enemies that chase them in the game.
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.
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); }
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
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); }
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); }
Next Lesson ● In our next lesson, we’ll create ways to fight back against these enemies
using Powerups!
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.
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
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
© Unity 2019 Lesson 4.3 - PowerUp and CountDown
4
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
IEnumerator PowerupCountdownRoutine() {
yield return new WaitForSeconds(7); hasPowerup = false; }
void Update() {
... powerupIndicator.transform.position = transform.position
+ new Vector3(0, -0.5f, 0); }
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
Next Lesson ● We’ll start generating waves of enemies for our player to fend off!
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.
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 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
void Start() {
SpawnEnemyWave(3 waveCount); }
void Update() {
enemyCount = FindObjectsOfType<Enemy>().Length;
if (enemyCount == 0) { waveCount++; SpawnEnemyWave(1 waveCount); } }
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
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
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
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().
Challenge Solution
1 In PlayerControllerX.cs, in OnCollisionEnter(), the awayFromPlayer Vector3 is in the opposite
direction it should be.
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");
;}
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 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
Unit 4 Lab
Basic Gameplay
Steps: Example of progress by end of lab
Step 1: Give objects basic movement
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.
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.
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.
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
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");
}
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
}
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. }
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.
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.
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.
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.
© Unity 2019 Lesson 5.1 - Clicky Mouse
2
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
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
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); }
void Start() {
... targetRb.AddForce(... RandomForce(), ForceMode.Impulse);
targetRb.AddTorque(... RandomTorque(), RandomTorque(),
RandomTorque(), ForceMode.Impulse);
transform.position = new Vector3(... RandomSpawnPos; }
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
IEnumerator SpawnTarget() {
while (true) {
yield return new WaitForSeconds(spawnRate);
int index = Random.Range(0, targets.Count);
Instantiate(targets[index]); } }
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
Next Lesson ● We’ll add some effects and keep track of score!
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.
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
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); }
© Unity 2019 Lesson 5.2 - Keeping Score
4
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()
void Start() {
... gameManager = GameObject.Find("Game
Manager").GetComponent<GameManager>();}
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
Next Lesson ● We’ll use some UI elements again - this time to tell the player the game is
over and reset our game!
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.
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
void Start() {
...
gameOverText.gameObject.SetActive(true); }
void Start() {
... 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) {
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); }
using UnityEngine.UI;
Lesson Recap
New ● A functional Game Over screen with a Restart button
Functionality ● When the Restart button is clicked, the game resets
Next Lesson ● In our next lesson, we’ll use buttons to really add some difficulty to our
game
5.4 W
hat’s the Difficulty?
Steps:
Example of project by end of lesson
Step 1: Create Title text and menu buttons
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.
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;
void Start() {
button = GetComponent<Button>(); }
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();
<------>
private GameManager gameManager;
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)
void SetDifficulty() {
... gameManager.startGame(difficulty); }
<------>
public void S
tartGame(int difficulty) {
spawnRate /= difficulty; }
Next Lesson ● In our next lesson, we’ll use buttons to really add some difficulty to our
game
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
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.
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
own() {
private void OnMouseEnter D
GameManagerX.cs DifficultyButtonX.cs
public void S
tartGame(int difficulty){ void SetDifficulty() {
spawnRate /= 5 d ifficulty; ...
... gameManagerX.StartGame(difficulty);
} }
X2 In GameManagerX.cs, in StartGame(), set your new timerText variable to your starting time
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.
Unit 5 Lab
Swap out your Assets
Steps: Example of progress by end of lab
Step 1: Import and browse the asset library
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.
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
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
Lesson Recap
New Progress ● Primitive objects replaced with new assets that function the same way
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
}
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++;
}
}
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
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;
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.
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.
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
rivate f
[SerializeField] p loat speed = 30.0f;
[SerializeField] p rivate f loat turnSpeed = 50.0f;
PlayerController.cs
void FixedUpdate() { ...
FollowPlayer.cs
void LateUpdate() { ...
© Unity 2019 Lesson 6.1 - Project Optimization
3
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
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.,
void Start() {
playerRb = GetComponent<Rigidbody>();
}
void FixedUpdate() {
transform.Translate(Vector3.forward * speed * verticalInput);
playerRb.AddRelativeForce(Vector3.forward * verticalInput * horsePower);
}
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;
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
Steps:
Step 1: Install export Modules
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.
Lesson Recap
New Concepts ● Installing export modules
and Skills ● Building for Mac/PC
● Building for WebGL/HTML