March 8th, 2018

I set out to make a Tetris game. I know there’s lots and lots of tutorials for making Tetris in Unity, but I’m not really a tutorial guy. I’m more of a start-doing-stuff-and-google-like-crazy kind of guy.

This was my first game in a long time — I made a Snake game in Phaser a while back, but haven’t done anything since. Phaser is a wonderful game engine, but I’m more interested in making mobile games than browser games. Unity is the most popular game engine in the world — why not learn it now?

One of the fun things about not going the tutorial route is that unexpected things start to happen.

Setting Up

In a podcast I was listening to this morning, Designer Notes #36, Soren Johnson said that he’d been developing games in Unity for two years, but he still didn’t know how to get started from scratch on a new game. His strategy is to take an existing game, strip it down, and build up a new game. So I think it’d be helpful to cover the first steps I took here to get the game scene set up.

First thing was to set up a platform for the blocks to land on. This was simple enough: Create -> 3D Object -> Cube. I downloaded a basic Brick Texture asset pack and added alternating materials to the bricks in the platform.

Putting the cubes together was easy enough, just a lot of copy-paste-renaming. I made an empty Game Object on the screen to hold the platform cubes. And I did a similar thing for the back wall — I guess there’s really no need for a back wall, but I made one anyway by adding 10 stripes of 20 cubes each.

The next step was to build the seven types of tetrominoes. This I did by making an empty game object for each one, and filling it with four cubes at different positions. Then I made a unique color material for each, and dragged the material onto each of the four cubes. I put these into a prefab for easy access later.

But the 3D got to me after a while, and I decided to make it a regular 2D game. The way to do that is to set up an orthographic camera (as opposed to a regular “perspective camera”). Normally when you select “2D” in the New Project options, Unity makes an orthographic camera for you, but since I started out with a 3D project, I had to do it manually. Easy enough:

Making the Cubes Fall

Turns out there’s an entire Tetris wiki out there. Their goal is “to compile every Tetris detail known to mankind.” And I thought I was a nerd… This was actually pretty helpful to me though, for figuring out the nitty gritty details of the game (like how exactly to rotate, how big the game area is, etc). So I can’t criticize.

To control the blocks, I made an empty game object for the tetromino generator. The script I added to this generator handled instantiating the prefabs and dropping them to the ground.

The code for moving the tetrominoes looks like this:

if (state == State.Dropping) { counter++; if (counter >= frameLength) { counter = 0; Vector3 pos = activeTetromino.transform.position; pos.y -= 1; activeTetromino.transform.position = pos; } }

So I’m directly updating the position vector, rather than dealing with velocity or acceleration or those other pieces of the Unity physics engine. But I forgot to add collision detection on the platform that stops the tetromino for pushing further downward. Here’s what the game looked like at that point:

It was so hilarious I couldn’t be frustrated. Makes me think of xkcd’s Tetris Hell.

Basic Collisions

The advantage of using Unity’s physics engine (rather than turning it off and doing it all myself) is that collisions were much more elegant. My first inclination was to brute force it, to hardcode the positions of the cubes in each style of tetromino and manually check if there’s a rigid body underneath each one. It was, as you would expect, messy. My brother JanPaul came up with a much more elegant way:

bool IsActiveTetrominoColliding(Vector3 direction){ foreach (Transform cube in activeTetromino.transform) { RaycastHit hit; if (Physics.Raycast (cube.position, direction, out hit)) { if (hit.distance <= 1.0f && !hit.transform.IsChildOf(activeTetromino.transform)) return true; } } return false; }

A simple raycasting check did the trick. Rotating was just as simple, using Transform.Rotate().

Oh, and I should mention I used the amazing Fingers – Touch Gestures for Unity pack from the asset store. It was extremely straightforward. Fingers provided a bunch of demos, so I just copied some code straight from the DemoSwipe scene and it worked beautifully.

But now it looked like this:

I just can’t make this thing stop blowing up!

Part of me is actually tempted to just leave something like this in the game as an easter egg.

The solution for this one was less mystifying: I just set all the Rigid Bodies in each of the cubes in each of the prefabs to “kinematic”. That made the game a little more boring but a lot more manageable.

Next Step

In the next post (coming some time next week), I’ll demonstrate row-deleting, high scores, a basic menu, and simple ads. The source code will be on Github soon. Stay tuned!