There isn’t much new math in here. Just some semi-practical things we can do with it.
Sometimes we only want a simple 360-degree spin, usually around y.
The simplest way to do that is hand-moving our own y variable, then setting rotation from it:
This method also works if the player can use arrow keys to add and subtract
from y. We could fix it when y goes outside of 0-360, but we don’t have
If we want to spin to a certain number, there’s a problem – we have to account for wrap-around.
Say we’re at 50 degrees now. To spin up to 120 degrees, we add. But because of
wrapping, we should subtract to go to 330 degrees. We could add, but we’d be going
the wrong way, spinning for more than 1/2 a circle.
The solution involves a few if’s, but Unity has a common built-in that takes care of it:
MoveTowardsAngle(d1, d2, 4) adds or subtracts 4 from d1 to move it closer to d2, accounting for wrap-around. Like MoveTowards, it also won’t overshoot.
This code lets us set targYspin and spin the shortest way to it:
Like MoveTowards and friends, 30*Time.deltaTime means it spins 30 degrees/second.
Just so you know, it’s made to never snap d1. If ySpin is 350 and targYspin is 10, this will gradually increase ySpin to 370. But it’s safe to adjust your numbers into 0-360 whenever you want.
When controlling spin through your variables, you always know your degrees.
But sometimes we’re free-spinning (LookAt, rotating over funny axis, or just
rolling on the ground), and want to find our y-spin.
It so happens transform.eulerAngles.y is always the correct 0-360 y-facing. It even fixes over-the-top x-spins:
Suppose y is 20 but x is tilted way back to 170. You’re really aimed the opposite,
at y=200. The system also thinks that – it flips y to 200 and changes x to
For fun, this is basically the math to fix things:
Another way to get 0-360 y-spin is to take the forward z-arrow of the rotation, flatten it, and find the angle between it and +z. Since the Angle function can’t tell left from right, it’s only correct if the angle is on the right side. If the arrow points left (x is negative) we flip it:
Here’s a more trig-like version that uses atan2. The main use is to convince you that using real trig is very error-prone:
Reading the x degrees doesn’t work very well at all. The system keeps it between -90 and 90. But it stores negatives as 270 to 360. If you set x to -150, the system adds 180 to y and changes x into -30, then 330. Ick.
But reading y works fine.
When a game character walks over uneven ground they generally stay straight up.
But sometimes we like it when things tilt with the ground: maybe it rides on
The secret to applying ground tilt is getting the normal. For flat ground, the normal is up. Tilted ground’s normals are mostly up, but tilted a little. The plan is the find the rotation between those two arrows. Then we can place our object for flat ground, and hit it with the ground tilt.
Getting the normal is in a previous chapter (it depends on how the ground is
made). Computing the difference between arrows is the rare FromToRotation.
This code plants a tree tilted with the ground. The tree is first randomly spun on y, to make it more interesting:
The deluxe version of this trick is when the tree is using some fancy math to spin in place. Keep the tree’s “flat” rotation stored, change it however, then re-apply the ground tilt every time.
The tilt of the ground feels like it’s the base rotation. But this logic says we can
think of it as an add-on.
Sometimes we want to partly tilt with the ground. If you remember,
groundTilt*0.3f isn’t legal, but Quaternion.Lerp can do it. This tilts us only 30% with the ground:
With all of these, moving objects cause a snapping problem. Ground like ∕\ or V will snap the tilt back and forth. A MoveRotatation can smooth it out: compute the rotation, but instead of using it, smooth yourself into it:
A simple orbit camera spins around us in a half-sphere (the top half), always looking at us. Looking at us is the easy part – the LookAt shortcut will do that.
For the half-sphere part, it’s like aiming a cannon with x and y. Imagine the
barrel is clear, with a backwards camera glued to the end.
When we use rotations to spin an arrow, we need to pick a good base arrow. In this case, it should be pointing behind us. That’s the normal place a camera starts, so we can see where we’re going. Because of that, we’ll say that 0 degrees counts as behind us.
A neat thing about using a backwards arrow is how +x finally tilts up instead of
down like it normally does.
We probably also want this to spin with the player. As the player turns, a behind camera should stay a behind camera. We can do that by adding the player’s rotation. A little trial and error says it goes as a global, so is in front.
This would go before we use the qCam arrow, to spin it with the player:
For real, we’d tweak this: adjust the center of the spin arrow and the LookAt
point. Otherwise we might be spinning around the player’s feel, aimed at the feet.
But that’s just simple arrow math.
Sometimes the camera might be temporarily controlled by something else. We’d like it to smoothly zoom back into the orbit spot, instead of an ugly snap.
We’ll compute the camera position as normal, then use MoveTowards to go there:
These two lines would replace the one theCam.position= line:
mvSpd should be large enough that normal spins are instant, but a camera put out in Cleveland would have a fast zoom to where it should be in the orbit.
We can change arrow lengths pretty well with normalizing and scaling. But some
things always confuse me, and they also have a shortcut.
Suppose we have a length 7 arrow and want it to be length 5. We’re pretty good at cutting them in half, or making them 10% longer. But this is different.
The long solution, which we know, is to normalize it, then take it times 5. Turning 7 into 5 is hard, but turning it into 1 then 5 is easy.
A cool shortcut is doing both at once. This makes it so arrows can’t be longer than 5:
Dividing by len normalizes it, then multiplying by 5 makes it that long.
arrow*(wantLen/currentLen); resizes any arrow to the length you want.
A similar problem is adding or subtracting from the length of a line – making it
0.5 longer. We can do it like:
arrow*=(len+0.5f)/len;. That’s the same trick.
The main thing is we’re used to plus/minus being easier than multiplication. But for arrows, it’s the other way around.
To get a line between two points, take a length one object, put it exactly between the points, aim it at the second one, and stretch it to be that distance.
The object you use should be set-up so its z forward axis is the stretchable part. For example a Unity cylinder has height 2 and runs along +y. We’d use the parent trick to aim it along +z and cut the length in half.
The code to make a line between me and a ball:
Placing midway works if the origin is in the center – stretching goes equally in
both directions. If the origin was at the back then a z-stretch goes only forward. We’d
need to place it at the start.
That plan makes the line go center-to-center (really, origin to origin). If
it’s going between 3D models, like a duck and a frog, that won’t look so
nice. For fun, we can try two different ways where the line really starts and
We often want the line to come from a specific part of us, maybe our eyes. Doing that is simple arrow math:
It’s more common to mark the eyes using an empty child, named "eyePos" positioned right between the eyes. We’d use it like this:
Since it’s a child, the system keeps it at our eyes as we spin and move, and sets
it’s position as the actual location. We only need to look it up.
For another way to draw a nicer line, pretend it ends at a see-through ball. We want it to stop right at the edge without going inside:
After getting the center-to-center line, we can subtract the radius of the sphere. Since we use the line starting from us, that shrinks the far end and it stops short:
Sometimes a line looks better if it goes just a little bit inside of what it
One final trick involves playing with the free z-spin from a LookAt. Often the line is merely a stretched 2D square. To avoid seeing an edge, we’d like the z-spin to face the flat part (the top) towards the camera as much as possible:
A square that spins to perfectly face the camera is a Billboard. This version, where it only spins on its z, is called an Axis-Aligned Billboard. It looks good from any side, but looking down the line gives a ugly edge-on view.
Suppose we have blocks with plug-ins on the sides. We usually mark them with empties: +z is straight out and +y shows the spin. Another block needs it’s +z facing ours, spun to have the +y’s lined up.
For example, this shows two copies of a block, with A from the first lined up with B from the second:
The problem is figuring out how to place and rotate block 2 so it plugs into block
1 using the slots we wanted.
First we need to find the two plugs: A from block 1 and B from block 2. They’re children:
Now the problem is a little simpler. We’re only trying to get block 2 to line up
Since B goes in the same spot as A, the only thing left is to follow the arrow, backwards, from B to the center of its block. But which direction? We need to account for A’s rotation, flipped 180 degrees, then account for B’s rotation on it’s block. Yikes!
It took me a few tries to get right:
This took a ton of testing. The first testing step was to try to get block2’s
rotation correct, without trying to move it yet.
An alternate way of doing all of that is tricking Unity into setting things for us.
We can temporarily make B the parent of block2. Then we can place B on A and let Unity do the work figuring out where block2 is. We still have to use A’s rotation, flipped 180:
This version might be easier to visualize. It’s not any faster – Unity has to do all of the math from the first version to set all the children.