How to Make a Match 3 Game in Unity

Learn how to make a Match 3 game in this Unity tutorial! By Jeff Fisher.

Leave a rating/review
Save for later
Share

In a Match 3 game, the goal is simple: swap pieces around till there’s 3 or more in a row. When a match is made, those tiles are removed and the empty spaces are filled. This lets players rack up potential combos and tons of points!

In this tutorial you’ll learn how to do the following:

  • Create a board filled with game tiles
  • Select and deselect tiles with mouse clicks
  • Identify adjacent tiles with raycasts
  • Swap tiles
  • Detect a match of 3 or more using raycasts
  • Fill empty tiles after a match has been made
  • Keep score and count moves
Note: This tutorial assumes you know your way around the Unity editor, that you know how to edit code in a code editor and that you have a basic knowledge of C#. Check out some of our other Unity tutorials first if you need to sharpen your skills on Unity.

Getting Started

Download the Match 3 how-to starter project and extract it to a location of your choosing.

Open up the Starter Project in Unity. The assets are sorted inside several folders:

Match3StarterAssests

  • Animations: Holds the game over panel animation for when the game ends. If you need to brush up on animation, check out our Introduction to Unity Animation tutorial.
  • Audio: Contains the music and sound effects used in the game.
  • Fonts: Holds the fonts used in the game.
  • Prefabs: Contains various managers, UI, and tile prefabs.
  • Scenes: Holds the menu and game scene.
  • Scripts: Contains the scripts used in the game. BoardManager.cs and Tile.cs are the ones you’ll be editing.
  • Sprites: Contains the UI assets and various character sprites that will be used as tile pieces on the board.

Creating the Board

If it’s not opened yet, open up the Game scene and click play. It’s simply a plain blue background with a score and move counter. Time to fix that!

First, create an empty game object and name it BoardManager.

The BoardManager will be responsible for generating the board and keeping it filled with tiles.

Next, locate BoardManager.cs under Scripts\Board and Grid in the Project window. Drag and drop it onto the BoardManager empty game object in the Hierarchy window.

You should now have this:

BoardManagerEmptyPic

It’s time to dive into some code. Open up BoardManager.cs and take a look at what’s already in there:

public static BoardManager instance;     // 1
    public List<Sprite> characters = new List<Sprite>();     // 2
    public GameObject tile;      // 3
    public int xSize, ySize;     // 4

    private GameObject[,] tiles;      // 5

    public bool IsShifting { get; set; }     // 6

    void Start () {
        instance = GetComponent<BoardManager>();     // 7

        Vector2 offset = tile.GetComponent<SpriteRenderer>().bounds.size;
        CreateBoard(offset.x, offset.y);     // 8
    }

    private void CreateBoard (float xOffset, float yOffset) {
        tiles = new GameObject[xSize, ySize];     // 9

        float startX = transform.position.x;     // 10
        float startY = transform.position.y;

        for (int x = 0; x < xSize; x++) {      // 11
            for (int y = 0; y < ySize; y++) {
                GameObject newTile = Instantiate(tile, new Vector3(startX + (xOffset * x), startY +                                                                 (yOffset * y), 0), tile.transform.rotation);
                tiles[x, y] = newTile;
            }
        }
    }
  1. Other scripts will need access to BoardManager.cs, so the script uses a Singleton pattern with a static variable named instance, this allows it to be called from any script.
  2. characters is a list of sprites that you’ll use as your tile pieces.
  3. The game object prefab tile will be the prefab instantiated when you create the board.
  4. xSize and ySize are the X and Y dimensions of the board.
  5. There's also a 2D array named tiles which will be used to store the tiles in the board.
  6. An encapsulated bool IsShifting is also provided; this will tell the game when a match is found and the board is re-filling.
  7. The Start() method sets the singleton with reference of the BoardManager.
  8. Call CreateBoard(), passing in the bounds of the tile sprite size.
  9. In CreateBoard(), the 2D array tiles gets initialized.
  10. Find the starting positions for the board generation.
  11. Loop through xSize and ySize, instantiating a newTile every iteration to achieve a grid of rows and columns.

Next, locate your character sprites under Sprites\Characters in the Project window. Select the BoardManager in the Hierarchy window.

In the Inspector window, change the Character Size value for the BoardManager script component to 7. This will add 7 elements to the Characters array and display the slots for them in the Inspector window.

Now drag each character into the empty slots. Finally, locate the Tile prefab under the Prefabs folder and drag it into the Tile slot.

When finished, your scene should look like this:

BoardManagerFilledPic

Now select BoardManager again. In the BoardManager component in the Inspector window, set X Size to 8 and Y Size to 12. This is the board size you'll be working with in this tutorial.

Click play. A board is generated, but it's strangely going offscreen:

boardOffScreen

This is because your board generates the tiles up and to the right, with the first tile starting at the BoardManager's position.

To fix this, adjust the BoardManager's position so it's at the bottom left of your camera's field of view. Set the BoardManager's X position to -2.66 and the Y position to -3.83.

Final BoardManager settings

Hit play. That looks better, but it won’t be much of a game if all the tiles are the same. Luckily, there's an easy way to randomize the board.

BoardAllTheSame

Randomizing the Board

Open the BoardManager script and add add these lines of code to the CreateBoard method, right underneath tiles[x, y] = newTile;:

newTile.transform.parent = transform; // 1
Sprite newSprite = characters[Random.Range(0, characters.Count)]; // 2
newTile.GetComponent<SpriteRenderer>().sprite = newSprite; // 3

These lines do three key things:

  1. Parent all the tiles to your BoardManager to keep your Hierarchy clean in the editor.
  2. Randomly choose a sprite from the ones you previously dragged in earlier.
  3. Set the newly created tile's sprite to the randomly chosen sprite.

Run the game, and you should see a randomized board:

randomized

As you may have noticed, your board can generate a matching 3 combo at the start, and that kind of takes the fun out of it!