Sliding Puzzle game in Unity Tutorial

Master the art of creating a sliding puzzle game in Unity with this comprehensive tutorial. Perfect for beginners and aspiring game developers, this guide walks you through setting up a 2D puzzle board, creating interactive tiles with C# scripts, implementing tile movement and shuffling mechanics, and adding a win condition. By the end of this tutorial, you’ll have a fully functional sliding puzzle game and a solid understanding of Unity’s UI, prefabs, and scripting. Follow along and bring your first 2D puzzle game to life!

🧩 Step 1: Project Setup/

  1. Open Unity Hub → Create a 2D Project.
  2. Set up a simple scene:
    • Add a Canvas (UI → Canvas).
    • Add a Panel inside to hold the tiles.
    • This will be your puzzle board.

🧩 Step 2: Preparing the Puzzle Tiles

  1. Create a Tile prefab:
    • Right-click in Hierarchy → UI → Button (TextMeshPro if available).
    • Resize it into a square (e.g., 100×100).
    • Change its background color.
    • Inside the button, set a Text object for the tile number.
    • Make the text bold and centered.
    • Convert this Button into a Prefab.
  2. You’ll need multiple instances of this prefab arranged in a grid (e.g., 4×4 for a 15-puzzle).

🧩 Step 3: Creating the Board

Write a BoardManager script to generate the tiles:

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

public class BoardManager : MonoBehaviour
{
    public int rows = 4;
    public int cols = 4;
    public GameObject tilePrefab;
    public RectTransform board;

    private List<GameObject> tiles = new List<GameObject>();
    private Vector2 emptySpace;

    void Start()
    {
        CreateBoard();
        Shuffle();
    }

    void CreateBoard()
    {
        float size = 100f; // tile size
        emptySpace = new Vector2(cols - 1, rows - 1);

        int number = 1;
        for (int y = 0; y < rows; y++)
        {
            for (int x = 0; x < cols; x++)
            {
                if (x == cols - 1 && y == rows - 1) continue; // leave empty

                GameObject tile = Instantiate(tilePrefab, board);
                tile.GetComponentInChildren<Text>().text = number.ToString();

                RectTransform rt = tile.GetComponent<RectTransform>();
                rt.anchoredPosition = new Vector2(x * size, -y * size);

                tile.GetComponent<Tile>().Init(new Vector2(x, y), this);

                tiles.Add(tile);
                number++;
            }
        }
    }

    public bool IsNextToEmpty(Vector2 pos)
    {
        return (Mathf.Abs(pos.x - emptySpace.x) == 1 && pos.y == emptySpace.y) ||
               (Mathf.Abs(pos.y - emptySpace.y) == 1 && pos.x == emptySpace.x);
    }

    public void MoveTile(Tile tile)
    {
        if (IsNextToEmpty(tile.pos))
        {
            Vector2 oldPos = tile.pos;
            tile.Move(emptySpace);
            emptySpace = oldPos;
        }
    }

    void Shuffle()
    {
        // Simple shuffle: randomize tile moves
        for (int i = 0; i < 100; i++)
        {
            foreach (var tile in tiles)
            {
                if (IsNextToEmpty(tile.GetComponent<Tile>().pos))
                    MoveTile(tile.GetComponent<Tile>());
            }
        }
    }
}

🧩 Step 4: Tile Script

Each tile needs to know its position and how to move:

using UnityEngine;
using UnityEngine.UI;

public class Tile : MonoBehaviour
{
    public Vector2 pos;
    private BoardManager board;

    public void Init(Vector2 startPos, BoardManager manager)
    {
        pos = startPos;
        board = manager;
    }

    public void Move(Vector2 newPos)
    {
        pos = newPos;
        RectTransform rt = GetComponent<RectTransform>();
        rt.anchoredPosition = new Vector2(newPos.x * 100f, -newPos.y * 100f);
    }

    public void OnClick()
    {
        board.MoveTile(this);
    }
}

Attach this script to your Tile prefab and assign the Button’s OnClick() to call Tile.OnClick.

🧩 Step 5: Add Win Check

In BoardManager, after each move, check if the tiles are in order:

public void CheckWin()
{
    int number = 1;
    foreach (var tile in tiles)
    {
        int expectedX = (number - 1) % cols;
        int expectedY = (number - 1) / cols;
        if (tile.GetComponent<Tile>().pos != new Vector2(expectedX, expectedY))
            return;
        number++;
    }
    Debug.Log("You Win!");
}

Call CheckWin() at the end of MoveTile.

🧩 Step 6: Playtest

Run the game.

You should be able to click tiles next to the empty space and slide them.

Tiles shuffle at the start, and the win condition is detected.

👉 You now have a basic sliding puzzle game in Unity!