Tetris for Android in the Unity Engine – Part 2 (Player Input)

Hello all – this is the second part of the series of posts in which I have been developing the video game ‘Tetris’ for the Android platform using the ‘Unity’ engine. In this post, we will enable the player to move the falling blocks from left to right using buttons on the HUD (head-up display). Additionally, we will also implement a feature which enables the player to increase the rate of time and cause the falling blocks to fall faster – this feature is present in many other versions of the game.

The final product of this post of this post can be downloaded here.

In order to allow the player to give input, we need to add three buttons to the user interface – Unity has a UI development toolkit which allows us to do this relatively easily. In Unity, UI objects can be treated as actual GameObjects which are children of a ‘Canvas’ object – these UI objects contain certain components which allow them to function as various different interface elements (such as buttons, sliders and toggles). We need to add a ‘move block left’ button, a ‘move block right’ button and a ‘speed up time’ button – this can be done within the editor. Since the buttons are treated as GameObjects, they can be moved and shaped using the engine’s level editing tools.



Now, we can write the functions which will be called by the engine when the user presses the buttons. The ‘move left’ and ‘move right’ buttons only need to provide a response to tap actions – on the other hand, the ‘speed up time’ button must react to both being pressed and being released. First, we will write the functions called when the left/right movement buttons are pressed. The code which moves the tetrominoes downwards can be copied and edited slightly in order to provide functionality for moving them sideways – instead of looping through each block in the current tetromino and moving it down one row, we can loop through each block and move it either one column to the left or one column to the right. However, before moving any blocks, we need to loop through the entire tetromino and ensure that it is not already positioned on the very edge of the screen (we can do this by checking if any of its blocks are on the very left column or the very right column). If this check is passed, each block in the current tetromino can then be translated by one unit – the grid array which we created in the previous post must be updated in order to reflect this chance. The functions are have been made public in order for them to be called through UI input events.


In order to hook these public functions to their buttons, we set the ‘On Click ()’ option on the ‘Button’ components of the UI button objects which we added to the scene earlier.


Now, if the user presses the ‘move left’ button, the tetromino which is currently falling gets translated one column to the left, and if the user presses the ‘move right’ button, the tetromino which is currently falling gets translated one column to the right.

To speed up the falling block, the player must hold down the ‘speed up time’ button. Therefore, we need to implement two separate functions – one which reacts to the button being initially pressed down (this is where the button starts getting held down) and another which reacts to the button being released (where the button is no longer being held down). By default, the ‘Tick ()’ function which controls the falling tetrominoes is called once per second – in order to speed up the falling blocks, we cancel this pattern using the function ‘CancelInvoke ()’ and then use ‘InvokeRepeating ()’ in order to create a new calling pattern for the ‘Tick ()’ function with less time in between each call. The second argument to the new ‘InvokeRepeating ()’ call is set to 0.0f – this ensures that the ‘Tick ()’ function is instantly called when the ‘speed up time’ button is pressed (if this argument was not 0.0f, it would theoretically be possible for the player to completely freeze the block in mid-air by repeatedly pressing and releasing the ‘speed up time’ button). The same technique for speeding up the falling blocks is used to slow them down when the button is released – in the second function, we use ‘CancelInvoke ()’ to cancel the faster calling pattern before using ‘InvokeRepeating ()’ to replaced the cancelled pattern with the default calling pattern (which has 1-second intervals in between each tick).


We can then add ‘Event Trigger’ components to the ‘speed up time’ button, in order to hook these two public functions to their corresponding button events.


Now, the player has significantly control over the falling blocks in our version of Tetris – the blocks can be moved to the left, moved to the right, or pushed downwards at a higher speed. In the next post, we will start using the Unity editor to construct actual Tetrominoes (coloured groups of blocks) similar to those found in the original game.

Developing Tetris for Android in the Unity Game Engine – Part 1 (Falling Blocks)

Hello all – due to having a fairly busy schedule as of late (owing to the run-up to my exams in May and June), I have been unable to make regular blog posts recently. However, enough progress has been made on my previously-mentioned computing-related side project for me to decide that it should not be kept under wraps for any longer. As the title suggests, the following series of posts will be about developing the video game ‘Tetris’ for the Android platform using the Unity game engine (an explanation of the game’s rules can be found here). This first post will be about developing the ‘backbone’ of the game (that is, the system which enables blocks to be generated at the top of the screen and fall).

This series of posts will assume a rudimentary knowledge of the Unity game engine (very basic ideas such as ‘GameObjects’ and ‘Components’ will not be explained in great detail).

The final product of this post can be downloaded here.

Our first task is to create a new Unity project directory – we do not need to import any of the pre-made asset packages (as none of them are necessary for our project). Normally, Tetris has 2D graphics, so we can opt to create a 2D project as opposed to a 3D one.

Screen Shot 2017-03-13 at 8.08.21 AM

After this is done, the main scene can be built (this should be done after setting the aspect ratio of the ‘game’ window to a ratio appropriate for the Android platform, such as 9:16). On my project, I positioned the main camera at (6,6,-10) and set its orthographic size to 11.6 – these settings allow for a grid with 18 rows, each 13 blocks wide.

Screen Shot 2017-03-13 at 8.09.18 AM

Next, we create a ‘prefab’ of an individual block. This can be done by dragging an object from the ‘hierarchy’ interface into the ‘assets’ interface. In the Unity game engine, prefabs are game objects saved as files within the game directory – these files can then be referenced in scripts, and copies of them can be created in the game world from these references. All of the scaling work has been done in the camera settings earlier, so the block prefab can just be a single cube with the dimensions (1,1,1). Later on, we will be able to design ‘tetrominoes’ (the slightly more complex shapes seen in the original game) using these block prefabs – for now, we will just use single blocks.

Screen Shot 2017-03-13 at 8.10.55 AMScreen Shot 2017-03-13 at 8.11.22 AM

Now, we can design the main script which handles the falling block system (I named it ‘MainControl.cs’). This script must be able to both keep track of all of the blocks in the grid and directly reference the blocks which are currently falling. We can achieve this by using a multidimensional array of ‘GameObject’ variables – the camera settings created earlier allow for us to use the x position of a block  as its column in the grid, and the y position of any block as its row in the grid (since the blocks are positioned at integer points along both axes). The script must also have a reference to the block prefab created earlier (so that new blocks can be generated). Furthermore, the script should also contain a variable holding the player’s score.

Screen Shot 2017-03-13 at 8.12.12 AM

In the original game, the blocks fall at a constant rate (unless they are sped up by the player – we will implement this feature in a later post). Moreover, they are translated directly from row to row, as opposed to being moved downwards in a continuous, smooth motion. Therefore, in order to process falling blocks, a function which is repeatedly called once every second can be used. In my code, I named this function ‘Tick’ – first, it checks if there are any blocks at all falling. If there are no blocks falling, it creates a new block using the ‘Instantiate’ function and adds it to the list of falling blocks. The ‘Instantiate’ function takes the block prefab as its first argument, and then the intended position and the rotation of the newly created block as its second and third arguments, respectively. Using the function ‘Random.Range’ while setting the value of the second argument of the ‘Instantiate’ functions enables blocks to be generated anywhere along the top row.

Screen Shot 2017-03-13 at 8.14.42 AM

If there are blocks falling, each of these blocks are processed in a loop. The loop initially iterates through each block and checks if the block has fallen onto a surface – this surface could either be the bottom of the grid, or the top of another block. Therefore, this check can be performed by first checking that the row (that is, the y position) of the block is not 0, and then checking that the value of the grid element exactly one row below the grid element of the current block is null (that is, no game objects are in that position in the grid). If this check returns true for any block in the list, then the list is cleared and all of the blocks in the list are frozen into their positions – since one of the blocks in the current ‘tetromino’ has fallen onto something. However, if this check never returns true, the ‘Translate’ function is used to move all of the blocks downwards by one row each (and the appropriate values in the grid array are updated).

Screen Shot 2017-03-13 at 8.17.42 AM.PNG

In order to ensure that the ‘Tick’ function is called once every second, the ‘InvokeRepeating’ function is used in ‘Start’ (which is called immediately after gameplay begins). Additionally, the grid is also initialised here.

Screen Shot 2017-03-13 at 8.32.21 AM.PNG

Now, we can drag this script onto any object in the scene – in my project, I attached it to the main camera. Our final result is a system which generates single blocks at the top of the grid in random positions along the x axis – these blocks then fall downwards until they either fall on top of other blocks or reach the bottom of the grid. When this happens, new blocks are created. In the next post, we will give the user the ability to control the movement of the blocks through input.