This section starts with Unity3D tricks: a simple way to get input, another way to get output, and how to make the program keep running and doing things. But that won’t take long, and we’ll be able to use them to write some more interesting programs.
Most of this chapter will be about how we can use variables and the n=n+1; trick to make the computer do things.
Then, near the end, we’ll move a Cube around on the screen, by adding just one extra command.
Unity uses an old trick where it can show you the “box” for a variable. Typing into it
is a shortcut to give that variable a starting value. Then, while the program
runs, we can watch our variables change, or even cheat by hand-changing
them.
This seems like cheating, but the secret is all real input is about putting a value in a variable. For example, suppose we had a drop-down with five options. There would be rules to set it up, but the end result is an int changing from 1 to 5. Output is the same way. If we have an auto-centered text-box with a pretty font, we’d still create a string and assign it to the text-box.
So changing and looking at variables directly is a completely fair way to do
input/output. It’s ugly and confusing if you’re not a programmer. Luckily we
are.
To do it we have to declare the variable outside of Start() with the word public in front. Here’s a silly sample program that lets us see x, w1 and w2. I named it testB, but you could just as easily reuse testA.
Note how the declarations are outside of Start, but are still inside the big {}s for testB. The indentation (even with Start) is also to help us see that:
Once you have this script set up (dragged onto the Directional Light) you’ll see the cool part. Select the Light and look at the Inspector. If it isn’t already, click the arrow to “pop open” the tab with the script. You should see new lines with x 0, w1 and w2. You can click and type in new values (the boxes for strings are sometimes further right than you think, so keep clicking along the row.)
When you press Play (don’t press Stop yet) you should see w2 and x change. Pressing Stop makes them snap back (it just does.) Try entering "ham" for w1. Pressing Play again should show w2 is "ham1ous".
Not super exciting, but it’s a quick, easy way to test this program for lots of
different inputs and see the results. Try 3+4 for w1. You should see 3+41ous for w2,
proving it’s using string-add.
Here are some notes, to explain this more:
Here’s a slightly different “Mad Lib” example. animal, food and place are the input variables:
We can enter values, Play, and check w to see how it looks. The neat thing is, a real program would compute w just like this does. The only difference is it would then copy it into a fancy text-box somewhere on the screen.
A traditional program runs once, outputs, and is done. Start in Unity works this way.
There are a few tricks to making a program that runs over time. Unity uses a common one. You write a regular run-once program, but you tell the system to run it over and over. That’s what Update is for.
The original starter program looked something like this (showing the important parts):
Anything you put inside the Start curly-braces will run once. Anything in the Update curly-braces runs over-and-over. You’re allowed to use either one by itself, or both.
Here’s an example showing how they work together. I’m putting them each on one line, to save space:
If you press Play, wait a little, then Stop, you”ll see one “begin now” followed by x’s blasted down the page (you may have to scroll up.) If you only see a single x, you probably have collapse checked on the Console, which won’t show duplicate lines. Just uncheck it, at the top.
Notice how the inside of Update doesn’t have anything about repeating. It’s
completely normal. The system just knows it should run Update over and
over.
Here’s a program taking advantage of Update(). It adds one to x over-and-over and lets us watch:
This is fundamentally no different than when we had several x=x+1;’s in a
row inside Start(). We’re just using a trick to make it run lots, spread over
time.
If you know games, you may notice it’s going too fast. Update should be running 60 times each second. A quirk of Unity is when you run things this way it goes as fast as possible, usually a few hundred times per second. That’s fine for our purposes.
If you don’t know games, each time Update runs is usually called a frame or a
tick.
We can use the Update trick to improve the Mad Lib program. Moving it there makes it so changes while running immediately update the answer (this version is a little different than before, but the same idea):
I had eatAmt keep increasing just so we can see this really is running
over-and-over. It’s not super exciting, but we can now change animal or food, while
running, and have w change.
Here’s a little more interesting program. It computes hours and seconds based on minutes:
If we type (while this is running) 120 into the minutes box, we should see hours
snap to 2, and seconds snap to 7200.
The Update trick works with any other “change me” assignments. This next program makes y go down very slowly, and computes 5% interest on x:
At first x won’t change, since anything times 0 is 0. But if you change it to 1, it will go up slowly, then faster and faster, like compound interest. That’s not really useful yet – just showing how the “change me” assign tricks from the last chapter work here.
We can use the declare-and-equals trick with public “Inspector” variables, but there are some tricks. This will start x at 100, for real and in the Inspector:
But what happens if you change Inspector x to -999? The rule is: the Inspector wins, and x starts at -999, even though the code still says it starts at 100. That’s because Unity jumps in and changes it to -999 before running Start.
This is horribly, horribly, horribly confusing if you try to read the program and forget. For real, variables never just magically change their values. But it makes testing programs much easier – what you see in the Inspector is always what you get.
One way not to be confused by this rule is not to use the assign trick. But I do it anyway, to give the Inspector that starting value. If you use Unity for real, this trick is handy.
Here’s a program that goes up by 1 each tick:
The old version used x=x+1;. The new version uses x=x+xSpeed;, but xSpeed is
always 1, so it’s the same.
It seems overly complicated, but there’s one advantage: we can change xSpeed while we’re running.
Press Play, let x go up by 1 for a while, then type 0.1 for xSpeed – x will go up
1/10th as fast. Try -1 and x starts going down. 0 for xSpeed makes it stop (it’s still
adding, just adding 0.)
Here’s an even more interesting version. It starts out increasing by 1, but then increases by a little less each time (it has one new line):
x will go up, slow down, almost pause, then go back down. That’s kind of neat,
for a 2-line program.
This is one of the Big Ideas in programming: they’re your variables, and they mean what you say they mean. xSpeed is how fast x changes, because we made it that way – because of the first line. xSpeed of 1.0 means x is going up quickly, 0 means it isn’t changing, negative means x is going down. Those numbers would mean different things for some other variable, but they mean this for xSpeed.
In the second line xSpeed=xSpeed-0.005f; means “make x slow down.” It’s also just a regular line that subtracts a little from a variable. But it means “slow down” in this program.
numOfCats = numOfCats + 1; adds 1 to how many cats we have, but it seems like a waste having to write numOfCats twice.
There’s a family of shortcuts for modifying a variable, so you only have to write it
once.
numOfCats += 4; is a shortcut for numOfCats = numOfCats + 4;. The += counts as one symbol, so it can’t have spaces or be =+. You can think of it as saying “numOfCats gets increased by 4.”
It also works for floats and strings:
The same shortcut works with other math symbols: -=, *= and /=:
These tricks are very common. You almost never see someone write this out the
long way. But they’re only shortcuts – they don’t even run any faster than if you
use the long way. Use them when you get sick of writing the same variable
twice.
There’s one tricky part – the entire right side is always computed first. Ex:
You usually don’t use the shortcut for anything complicated like this. I just write
these out the long way.
There’s a super shortcut for just adding or subtracting 1. That seems excessive, but we do it a lot. x++; adds 1 to x. x--; subtracts 1 from x. There isn’t even an =. Just x++; all by itself adds one:
The official name of ++ is increment (coming from the root word, increase.) And -- is called a decrement.
With just a little extra work, we can take a program that moves x around, and have
it also move a Cube on the screen around, using x. All we need is a rule to apply x to
the position of some Cube.
Here are the steps, then an explanation later. Make sure it isn’t in Play mode for any of this:
If it’s on the Directional Light, Remove it from that one.
Here’s the explanation of the parts:
The things in the Scene are officially called GameObjects. The GameObject->3Dobject menu has simple testing shapes, like a Cube or a Sphere. Any of them are good enough.
When you make it, the system puts it “in front” of you, which could be
anywhere. Since our program will position the object, it doesn’t matter where it
starts.
Way back, I mentioned how scripts are intended to be on their Cube, which they move around. We’re using that rule now. The last line of that script says “move me,” the Cube it’s on counts as the “me”.
This really is the entire movement command:
If you look in the Cube’s Inspector, in the Transform block, in the Position slot, you’ll see it changing.
For now, it’s “just because.” All we need to know about it is that x, y and z can
be any float or float variable.
There’s no natural size of the screen. It depends on the position of the camera and how it’s aimed and even the particular size of your Scene/Game area. With the camera in the starting position, the left side is about x=-7, which is why the code starts us there. The right side is about x=+7.
Since the screen is only 14 across, a speed of 0.1 feels about right.
To get a feel how that last line works, we can change things around:
I think of this as two parts. The new part is the set position command – the name transform.position=, what the three slots mean and where the edges of the screen are. The other part is what we’ve been doing – making x go up and down
Most cool-looking programs break down that way. Once you understand the rules for using some neat thing, the rest is regular programming to make the numbers change how they should.
Before we knew how to move Cubes, we could make more than one variable change at once but we didn’t have a reason. Now, with Cubes, we do.
If we change x and y at the same time, the Cube can move at an angle:
That should make the cube fly from the lower-left to the upper-right.
We can change the angle by changing either speed. Or have it go lower-right to
upper-left (by making x go from 7 backwards.) And so on.
We already know how to make x go up, slow, then back down. We can reuse that for a Cube that goes right, slows, then goes back left:
It’s the same idea, except in the old version we didn’t care about the exact value
where x turned around and started getting smaller. Now we have to play with the
math and trial&error so it changes direction somewhere around 7. But otherwise it’s
the same idea.
We can use the “variables are better than constants” rule again, by turning that -0.0002 slowdown into a variable. I’m going to name the variable xAccel:
Now we can just adjust the slowdown in the Inspector, instead of having to go back to the code each time.
A fun trick is to start xSpeed at 0, and xAccel at a very small positive number. The cube will speed up from a standstill. Or, set xSpeed negative and xAccel positive – it will go left, slow, then right.
If we want to change the Cube’s color, we have to know the command, and what the values mean. This makes the Cube turn red:
The first part is very strange-looking, but it works and changing color is fun enough to be worth it. The pop-up will even help us. Note the R in Renderer is capital, and those really are a less-than and greater-than (they’re being used as angle-brackets.)
Like before, we need to know what the 3 values in parens mean. They stand
for red, green and blue, in that order, and go from 0 to 1. For example,
Color(0,0.3f,0); makes dark green.
Now we can use the same tricks to move the color. This slowly colors the Cube from black to red (if the Cube is off the screen, you may have to manually enter 0,0,0 for the position in Transform in the Inspector.):
We can try the usual tricks:
Start r at 1 and have rSpeed be negative (so it starts red and goes to black.) Use
the second slot – Color(0,r,0) – to make green change, or Color(0,0,r) to change
blue. Or use something besides 0’s – Color(1,r,1) goes from purple to
white.
Another interesting one is putting the variable in two places – Color(r,r,0). The
same variable controls red and green (which happens to make yellow.)
We can change red, green and blue at once by making a variable for each. These particular numbers change them at different speeds, making kind of an interesting pattern. You’re probably sick of seeing the long way, so I’ll start using the += shortcut:
To make us twice as big, use transform.localScale = new Vector3(2,2,2);. As usual, we need to know what the numbers mean.
You may have guessed from the Vector3, that they stand for x, y and z. 3D programs don’t use just one number for size. They let you stretch it wider, taller and deeper (along the x-axis, y-axis and z-axis) in different amounts. If you want to just make the whole thing bigger or smaller, you have to use the same number for all 3.
Here are a few uses of it:
The numbers aren’t officially the size – they’re a multiplier. But Cubes’ base size
is 1x1x1, so for Cubes, the scale is also the size.
This next program makes the Cube get wider and taller, in sort of a fun pattern. It starts not as wide, but it gets wider faster than it gets taller. I used xSizeSpeed for how fast the x-size changes since it was the best variable name I could think of:
This would start taller, grow with time, but eventually get wider than it is
tall.
As usual, we could enter a small negative number for one of the speeds, to see it
get smaller. Or 0 for one speed to have that size stay the same. Negative sizes are
allowed, but aren’t good – it looks inside-out.
This, and the color change, and the movement are really the same thing - just some variables that get bigger or smaller, then one special Unity command saying what they control.
But that’s the point. A lot of things that look different are mostly the same old lines playing with numbers.
When using the assign shortcuts it’s easy to forget the = in +=, or to add an extra =, or an extra x. Examples:
Some mistakes aren’t errors, they just do wrong stuff or look funny:
I try to remember that += and ++ are shortcuts. Using them should make a line
shorter, not longer.
A script changing color needs to be on a real colorable shape, like a Cube. On a
Light it gives the run-time error “Missing Component Exception: there is no
Renderer .... It’s looking for the color slot and can’t find it.
The scripts that move or change size won’t give errors on a non-Cube, but you
won’t see anything happen.
Leaving out the public in front of a variable isn’t an error. You won’t see a slot for it in the Inspector, but it will work as normal. This prints 10, 11, 12 …:
And, to repeat, remember the Inspector wins. If you write public int x; an inspector slot with a 0 appears. If you later change it to public int x=7;, x will still start at 0 until you change it inside the Inspector.