Infinite Roller Tutorial Eleven – Blocks Part One

Welcome to Edge of Code’s series of Infinite Roller tutorials. If you’d prefer a video tutorial, you can find one here.

In the previous tutorial, we learned about audio in Unity and added both background music and sound effects to our game. Today we’ll look at how to use blocks rather than the square pieces of ground we have been using.

Let’s look at how the blocks will work. We’ll draw perhaps five different blocks, which we can also flip across the vertical axis to add more variation. We’ll position a block under the character so that it always has something to land on, then as the character rolls along, the first block will be removed and a random one will be added in front. Each block will be positioned within some random range, for both height and x position.

First, we’ll draw the blocks. Open Inkscape and select the circle tool on the left panel. Click in the centre of the screen and drag to form an ellipse. Once it’s drawn, go to Path → Object to Path, then Object → Fill and Stroke… and click on the Fill tab of the panel that appears to the right. Pick a colour for the centre of the block. I’ve gone for purple. Next click on the Stroke paint tab and pick a colour for the block’s outline (I’ve picked a bright green), then on the Stroke style tab and change the width to about 50.

Click on the Edit paths by nodes button (the second one down on the left panel), then click and drag the mouse over your oval to select all of the nodes. Click on the plus button on the top toolbar to increase the number of nodes. Next, move the nodes to give the appearance of blocks of ground (see the image below). You might need to add more nodes for this.

Inkscape blocks

Once you’re happy with the first block, create a few more of different shapes and sizes. One should be wider than the rest – this will be the starting block for the game.

Save the Inkscape file, then export each of the images to PNG files. To do this, click on the first button (Select and transform objects) on the left panel, then click on one of the blocks to select it. Go to File → Export PNG Image… In the window that opens, make sure Selection is selected, change the width or height so that they are at the quality you want. I’m setting the width of each of the blocks to about 900. Click on Export As… and select a location and filename for the image. Click Save, then click on Export. Do this for each block, remembering to change the filename.

Open your Infinite Roller project and the scene. Open the folder you saved the block images in, and drag them into the Sprites folder in Unity’s Project window.

Create a gameobject for the first block by dragging it onto the hierarchy. Add a collider so that the character will be able to land on it: Click on Add Component, then Physics 2D → Polygon Collider 2D. The polygon collider creates a collider in the shape of the object. It can be quite costly in terms of performance compared to the other, simpler, colliders, but we don’t have many different blocks, so it will be fine. Repeat this for each block, then create prefabs of each by dragging them into the Prefabs folder in the Project window.

Unity tutorial block prefab

Next, delete the blocks in the hierarchy – we’ll write a script to place them in the scene.

Open the TerrainGenerator script and rename it ChunkTerrainGenerator by highlighting the class name, then right click, select Refactor → Rename, type the new name in and click OK.

Unity tutorial refactor class name

Now save the script. If you have any other scripts open, make sure those are saved too. Go back to Unity and select the TerrainGen gameobject in the hierarchy. Rename it ChunkTerrainGenerator. The script component will say Missing because we renamed the script. Drag the ChunkTerrainGenerator script onto the slot. Also drag the previous, current and next chunk gameobjects onto the ChunkTerrainGenerator to make them child objects.

Unity tutorial move gameobject

Create two new scripts (right click in the Scripts folder in the Project window, Create → C# Script) called BlockTerrainGenerator and Block. The two scripts will work together similarly to the way the existing Chunk and ChunkTerrainGenerator scripts do.

Open both scripts and delete the existing code inside each class. Go to BlockTerrainGenerator and start by creating a variable to store the block prefabs

//the blocks
public GameObject[] blockPrefabs;

The [] indicates this is an array of GameObjects, which means we’ll be able to add multiple blocks in the inspector. Save the script and go back to Unity. Select the BlockTerrainGenerator gameobject in the hierarchy and where it says Block Prefabs, change the Size to the number of blocks you’ve got. Since I made five, I type in 5. Five elements will appear. Drag the block prefabs into each of the slots. Go back to the script and create another variable to store the blocks we’ve instantiated:

private List<Block> blocks;

This is a list of Block objects. To access the List object, also add a using statement to the top of the script:

using System.Collections.Generic;

Add an Awake method and initialise the list:

void Awake()
{
	blocks = new List<Block>();
}

Next, create a new method to instantiate the prefabs:

/* instantiate two of each block, one flipped on z axis */
private void InstantiateBlocks()
{}

And call it in Awake, after the list is initialised.

void Awake()
{
	blocks = new List<Block>();

	//instantiate the prefab blocks
	InstantiateBlocks();
}

Inside the InstantiateBlocks method, create a foreach loop:

foreach (GameObject prefab in blockPrefabs)
{}

This is a different type of for loop to the one we’ve seen previously in this tutorial, but works similarly. It goes through the blockPrefabs array, giving the name prefab to each block. The next time through the loop, prefab is the next one in the array.

Create another new method to instantiate a single block

/* Instantiate a block */
private void InstantiateBlock(GameObject prefab, bool flip)
{}

The prefab and a boolean value for whether we want to flip it or not are passed in. First, add code to actually instantiate the block:

//instantiate it once
GameObject blockGameObject = Instantiate(prefab) as GameObject;

Next, set its parent to be the BlockTerrainGenerator gameobject.

	
//set parent
blockGameObject.transform.parent = transform;

And get the Block script component from the prefab.

//get its Block script
Block block = blockGameObject.GetComponent<Block>();

We haven’t added the Block script to the prefabs yet – go back to Unity and select each of the block prefabs in the Prefab folder in the Project window. Add the Block script as a component to each one. Go back to the script, and add an if statement to see if we want to flip it along the vertical axis:

//flip it 
if (flip)
{
	block.FlipX();
}

We’ll create the FlipX method in Block in a moment. Next, add the block to the list we created

//add to blocks list
blocks.Add(block);

And deactivate it so that it is not initially visible

//not active to start with
block.SetBlockActive(false);

We’ll write this method next, along with FlipX(). Save the script and go to the Block script. Add a method that flips the block

/* Flip the block */
public void FlipX()
{
	//use localscale to flip
	Vector3 blockScale = transform.localScale;
	blockScale.x *= -1;
	transform.localScale = blockScale;
}

First we get the scale of the gameobject using transform.localScale, then multiply its x component by minus 1 to flip it, where blockScale.x *= -1; is shorthand for

blockScale.x = -1*blockScale.x;

Then assign the new blockScale to the gameobject with transform.localScale = blockScale;

Next, add

/* Activate or deactivate the block*/
public void SetBlockActive(bool active)
{
	gameObject.SetActive(active);
}

to activate or deactivate the gameobject.

Unity tutorial blocks script

Save the script and go back to the BlockTerrainGenerator script. Inside the foreach loop in InstantiateBlocks(), add

//instantiate a block
InstantiateBlock(prefab, false);
		
//instantiate the same block but flip it for variation
InstantiateBlock(prefab, true);

Next we’ll add an initial block to make sure the character will fall on one at the beginning. Create a new variable

//block to start on
public GameObject initialBlockPrefab;

Unity tutorial blocks

Save the script, go to Unity and drag the largest block prefab onto the new slot. Go back to the script and create two new variables

private Block frontBlock;
private Block initialBlock;

frontBlock keeps track of the block at the front, and initialBlock stores the initial block. Add a new method

/* Create the initial block for the character to fall onto*/
private void CreateInitialBlock()
{
	//initial bigger block positioned under character
	Vector3 position = new Vector3(0, -10, 0);
	GameObject blockGameObject = Instantiate(initialBlockPrefab, position, Quaternion.identity) as GameObject;
		
	//set parent
	blockGameObject.transform.parent = transform;
	
	//set this as the initial block and the previous block
	initialBlock = blockGameObject.GetComponent<Block>();
	frontBlock = initialBlock;
}

and call it from Awake(). First we create a position that is below the character, then instantiate the block at that position, using Quaternion.identity to give no rotation. Next, the parent is set to be the BlockTerrainGenerator gameobject. Finally, we set initialBlock and frontBlock to be the Block script from the gameobject we’ve just instantiated.

Make sure everything is working so far – save the scripts, go back to Unity and press play. Over the ground pieces, you should see the initial block under the character. If you click on the arrow next to the BlockTerrainGenerator script in the hierarchy, you should see the initial block child gameobject, plus another ten (in my case since I have five different blocks) inactive block gameobjects.

Unity tutorial blocks

Save the scene and the project. We’ll continue this in part two of the tutorial.

Remember you can download the files for this tutorial on the Downloads page. See you next time!

PreviousTutorialButtonNextTutorialButton

Comments are closed.