Why are we here
Simple movement
Homework and builds
Components and references
State
Demo writeup homework (W3)
Here is one idea of what skills you'd need to express a range of ideas (co-written with Richard and Peter):
Strongly recommend this book once you have a little Unity knowledge.
2e also available via the USC Library
along with thousands of other technical books
all you need to know
(almost)
A vector is a mathematical object that is the basis of how games represent space. In math, a vector is an arrow.
A math vector has two basic parts:
magnitude
Magnitude is just a number.
Direction is represented with several numbers:
So you can use a Unity Vector to represent a math vector: an arrow pointing off into space.
But Unity also uses Vectors for other things, like position and scale, for math reasons. It's better to think of a Unity Vector as just a package of three numbers.
Some visuals will make this clearer.
This dot represents a position.
It can be described with two numbers, x and y.
A different point.
An arrow from (0,0) to a point is a vector.
If you want to represent moving from one position to another, it might look like this.
What is the result?
These are two vectors.
What does it mean to add them?
Visually, put the beginning of one at the end of the other. Mathematically, just add the numbers.
It works in the other order too.
What does it mean to subtract two vectors?
To subtract something is to add its opposite.
The opposite of a vector points the opposite direction.
The math works the way you'd expect: subtract x from x and y from y.
What about multiplying by one number?
What about multiplying by a negative number?
The opposite of a vector points the opposite direction.
These are useful shortcuts in code.
Each one is one unit long so you can multiply it by whatever you want.
How about multiplying a vector by another vector?
What would this mean, visually?
This doesn't seem to mean anything.
There are two ways to multiply vectors. But you don't need to know either one in order to get started making games.
A build is a program, a standalone version of your game.
So your player doesn't need to open your project in Unity — they can just double-click on your program to run the game.
You may also encounter the terms application or executable. It all means the same thing.
You can't run a Windows application on OS X, or a PlayStation game on an iPhone. Each requires its own special format.
The operating system your player is using is referred to as a platform or (in Unity) a build target. Some examples are:
For the homework you will only make Windows builds.
On Windows a build consists of a file called YourGameName.exe and several folders.
They are all necessary to run your game, so you need to zip the folder that contains the exe and folders, and turn that in.
If you ever realize you want to make games for a new platform (for example iOS), you don't have to reinstall Unity.
Instead, you can add a new build target using Unity Hub.
GetComponent is an important and powerful bit of code, because it lets you talk to any of the components you can see in the Inspector (including other scripts).
So it is worth all the punctuation!
myLight = gameObject.GetComponent<Light> ();
GetComponent is how you can talk to other components from a script. For example, here's how you can get a reference to a Light component:
myLight = gameObject.GetComponent<Light> ();
How do you know what to put in the <>s? It's almost always the same as the name of the component that you see in the Inspector.
Remember that gameObject refers to the GO that your script is attached to. Later we will see how to talk to other GOs.
So you've got a Light. What can you do with it?
You can talk to its properties, such as color. You can also get to the checkbox that turns it on and off.
As you saw in the homework, one kind of component you can talk to is the Text component built into Unity's UI system.
You can make one from the GameObject menu: choose
UI -> Text
Changing the text of a Text component from code looks like this:
This can get a little confusing with all these uses of the word "text". All you can do is name your variables as clearly as possible.
levelNameText = gameObject.GetComponent<Text>();
levelNameText.text =
"LEVEL "+currentLevel.ToString();
Perhaps this is clearer, even if it's a little longer to type. Think about what makes sense to you.
levelNameTextComponent = gameObject.GetComponent<Text>();
levelNameTextComponent.text =
"LEVEL "+currentLevel.ToString();
The first line asks the gameObject (GO) that is running this script to look at its other components and find one that is a Text.
levelNameText =
gameObject.GetComponent<Text>();
The first line asks the gameObject (GO) that is running this script to look at its other components and find one that is a Text.
levelNameText =
gameObject.GetComponent<Text>();
gameObject
the gameObject that is running this script
In this example, the script called UI Manager is attached to the gameObject called Level UI.
gameObject .GetComponent<Text>();
the function that asks the GO to look through its components and return a reference to the one with the type you want.
gameObject .GetComponent<Text>();
In this example, the gameObject called Level UI has a Text component.
So this piece of code will return a reference (way to talk to) the Text component.
The second line talks to the Text component and sets its "text" property to a new value.
levelNameText.text =
"LEVEL "+currentLevel.ToString();
Just like the Light component, the Text component has lots of different properties; its text is just one of them.
You can also change the text size, font, color, etc. by setting those properties.
In the Unity editor you can make all the GameObjects, components, materials, scripts, etc. that you want.
You can see them. The engine can "see" them. But your scripts can't.
Each script is an island unto itself. To talk to or change anything else, you need a reference.
A reference is (conceptually) an arrow that points to the GameObject, component, or file you want.
In a MonoBehaviour script, Unity gives you a few built-in references. The most important one is
gameObject
which means the GO that this script is attached to.
When you use
GetComponent<ComponentName>()
what is really happening is
gameObject.GetComponent<ComponentName>()
So Unity looks on the same GameObject as your script.
This is the pattern to get a reference to a component. Declare a variable with the type of component we want, and then go find it in the Start function.
Rigidbody rb; Collider myCollider; void Start() { rb = gameObject.GetComponent<Rigidbody>(); myCollider = gameObject.GetComponent<Collider>(); }
We'll see this pattern over and over in the scripts we write in class.
But notice you don't have to GetComponent to talk to a transform.
Transform is special, because every GameObject has a transform, even empty ones. Every other component will be on some GOs and not others.
someGameObject.transform
If you want access to another GameObject, you have to set that up yourself. We'll see many different ways to do that this semester.
The simplest one is this:
[SerializeField] GameObject theOtherGameObject;
This makes a slot on the script in the editor where you can just drag in another GO.
Once you have a reference to that other GO you can do all the GameObject-y things with it:
theOtherGameObject.name theOtherGameObject.transform theOtherGameObject.GetComponent<Light>()
and so on.
Choose someone near you to do this mini-lab with.
Find the demo project on our shared drive. Open it and take a look at the scripts (there are only two).
Then press Play and see if you can spot the bug.
A pattern for thinking about code
Because Unity calls the code in Update every frame, your code needs to be ready to handle any possible situation.
This is hard. But you can break it down.
The computer science name for "situation" is state.
State includes any information you care about while the game is running.
Unity keeps track of some of it for you. For example, Time.time updates constantly and you can just ask Unity when you need it.
But Unity doesn't know anything about your game, so you need to track a lot of things yourself, including things that are so obvious they're invisible.
This is often going to be a boolean (true/false) value, like whether the game is over.
So you often want your game to behave differently when it is in different states: tutorial, game running, level over animation, game over.
But often you want to respond, just once, to the moment when the state changes, which we will call an event.
(Programmers would use the word transition. Use the word that makes sense to you.)
The demo project offers an example of one pattern for responding to an event (transition) once and only once.
Briefly, you need a way to remember whether you already responded. "A way to remember" is the same thing as a variable. Here it is either true or false, so you need a bool.