Part 3: Block Movement

Christiane Snyder

After setting up your base project from the resources in part 2, we’re going to get started on the scripts that compose tetris’ game mechanics. The simplest mechanic to implement first is the blocks moving down until they hit they hit something.

Create a Block.cs script and attach it to the block prefabs already available in the starter project.

Inside of the Block script, create a Downward boolean and Vector3 value named Movement. Movement will represent how much is subtracted from the position of the current block during each update (causing the block to move down the gameboard without gravity or a physics system). Set these two variables to the values below:

private bool Downward;

private Vector3 Movement;

void Start () {

   Movement = new Vector3 (0f, 0.1f, 0f);

   Downward = true;


Add the following lines of code to Block’s Update() function. This section will prevent the block from moving through the bottom of the board and other blocks by having each child block send out a raycast hit and checking how far the object below is. If it’s too close, don’t subtract anything from the current block’s position and round its current x and y values so that its stationary position on the board fits into the grid.

void Update () {

if (Downward) {

foreach (Transform child in transform) {

RaycastHit hit;

               if (Physics.Raycast (child.position, new Vector3 (0f, -1.0f, 0f), out hit)) {

                   if (hit.distance < 0.5f && !hit.collider.transform.parent.Equals (child.parent)) {

                       Downward = false;





           if (Downward) {

               transform.position -= Movement;

           } else {

               transform.position = new Vector3 (Mathf.Round(transform.position.x), Mathf.Round(transform.position.y), 6.0f);




We’ll just set the Blocks speed to constant velocity upon creation. Now if you drag a prefab into the scene, it should move downwards. You can change this number to whatever you like, but I found -4.4 to be the most enjoyable while using the Cardboard viewer.

Create a blank C# script named PuzzleSystem.cs and attach it to the “Backdrop” game object. This script will spawn and keep track of the blocks throughout the game.


For now, add seven public GameObject variables that will represent the seven block prefabs we use, as well as a list of GameObjects to contain references to all active blocks and a GameObject variable that will represent the block that is currently moving.

We’ll also add in StartSpawning() and SpawnPiece() functions that will continuously wait and spawn new puzzle pieces at the top of the board.

using System.Collections.Generic;


public class PuzzleSystem : MonoBehaviour{


   List<GameObject> Blocks;

   public GameObject LBlock, LBlock2, SquareBlock, LineBlock, SBlock1, SBlock2, TBlock;

   private GameObject CurrentBlock;


   void Start () {

       Blocks = new List<GameObject>();

       CurrentBlock = null;

       //Start coroutine to continuously spawn new blocks

       StartCoroutine ("StartSpawning");



   void Update () {



   IEnumerator StartSpawning(){

       while (true) {

           SpawnPiece ();

           yield return new WaitForSeconds(5);



   public void SpawnPiece(){

       //Choose a random rotation for the spawned block

       Quaternion rot = Quaternion.identity;

       int randRot = Random.Range (0, 3);

       if (randRot == 0) {

           rot = Quaternion.Euler (0f, 0f, 0f);

       } else if (randRot == 1) {

           rot = Quaternion.Euler (0f, 0f, 90f);

       } else if (randRot == 2) {

           rot = Quaternion.Euler (0f, 0f, 180f);

       } else if (randRot == 3) {

           rot = Quaternion.Euler (0f, 0f, 270f);


       //Instantiate to some block, this value will be overwritten anyways

       GameObject block = LBlock;

 //Choose a random block type to spawn

       int randBlock = Random.Range (0, 7);

       if (randBlock == 0) {

           block = LBlock;

       } else if (randBlock == 1) {

           block = LBlock2;

       } else if (randBlock == 2) {

           block = SquareBlock;

       } else if (randBlock == 3) {

           block = LineBlock;

       } else if (randBlock == 4) {

           block = SBlock1;

       } else if (randBlock == 5) {

           block = SBlock2;

       } else if (randBlock == 6) {

           block = TBlock;


       //Choose a random x value in range of the playing field

       int x = Random.Range (0, 10);


       /*Instantiate new block clone. Always use same spawning height and block always stays in the same Z plane*/

       CurrentBlock = (GameObject)Instantiate (block, new Vector3 ((float)x, 26f, 6f), rot);

       Blocks.Add (CurrentBlock);


After adding in the above code, make sure to assign the GameObject variables in the inspector by dragging the block prefabs into their matching fields.