Math in 3D Space and Other Travails

A capsule with silly eyes

What happens when you ignore rotation because your game object is perfectly symmetrical and then you add eyes to it?


From 2D to 3D

I’ve had a few challenges converting my village sim from 2D to 3D. The main difference has been switching from translation-based movement to physics-based movement.

To give an object physical properties, you attach a Rigidbody. This has settings for drag and gravity forces. Other forces can be applied to affect the base movement from these forces.

At first, I stuck with the translational-based movement (add to the game object’s transform.position to change its location in space), simply converting the Vector2 elements to Vector3s, by moving the Vector2.y to the Vector3.z and setting Vector3.y to a constant. This generally worked, but it wasn’t smooth.

The main problem with translational-based movement is that objects tend to end up occupying the same space. This is not the desired state, and the game engine repels them from each other.

Which is a lot of fun with 1000 objects!

It also caused problems with capsule and spherical colliders, where the collision was completely ignored, and villager capsules would pass right through.


So I used RigidBody.AddForce, and it made things much more hilarious.

The villagers started zipping around at random speeds. When they ran into an object, they’d just keep pushing into it until the next direction update. I had this on a 2-5 second timer (random each change). Then when I assigned a target, they’d barrel right for it, ignoring anything in their path, even if they got stuck. They got stuck a lot.

Turning off the y-axis positional freeze would cause them to fly into the air. This was a huge problem at first, since they’d fly over the edges and fall endlessly. I solved this problem by adding a box made of flattened and stretched Cube gameobjects around the play area with a transparent material so the camera can still see the game board. Bumping the villager count made the game look like a popcorn popper sim. Disabling rotation locks enhanced this effect.

Collision Problems

With y-axis and rotations safely re-frozen, I still had a collision problem. Obviously at this point what I should have done was ask the interwebs how to handle collisions in 3D, to which the interwebs would have replied “Use raycasting, dummy.” But of course, I rolled my own solution, and the effect is pretty great.

What I did was on collision detect, if the object is not the villager’s target, apply a force in the direction opposite that which the villager is traveling. I calculated this force from the current force, multiplying the x and z values by a random value between 10 and 100, then multiplying the resulting Vector3 by -1000000 and applying it to the villager for 1 second. The random value allowed the villager to change direction so that it wasn’t just ramming the blocker from the same position every time. I also added a layer filter so this only occurred against specific objects, omitting other villagers, walls, and storage chests.

Sounds reasonable, right? No? Too bad. This actually worked out pretty well for small quantities of villagers, and ended up looking incredibly silly.

But when you bump the villager quantity, something interesting happens. The game transforms into a strangely accurate depiction (you might have to squint) of modern business offices. Large clumps of villagers are forcibly idle because everyone else gets in their way, while those that have actual tasks are frantically ramming into things that don’t matter!

Fine. Raycasting it is.

Later while I was in the shower, it occurred to me that I was being dense, and that I should just raycast and adjust if anything gets in the way. I could have done that from the start, but then I would have saved myself a lot of hilarious entertainment.

Also, before I add raycasting: LookRotations to make the villagers face the direction they’re moving. (The Anson Seabra - Robin Hood in the background was accidental. You’re welcome. Don’t report me.)