Interactive Maze with Unity

Learn how to create an interactive maze with Unity!

Prerequisites

This project assumes you are familiar with the basic functionality of Unity.

Setup

Note: You must use the Spatial Phidget (MOT1102) for this project. Other Spatial Phidgets (e.g. MOT1101) do not have the built-in functionality required.

Spatial Phidget

Phidget cable

USB cable

Attach your Spatial Phidget to your VINT Hub as shown:

Configure Unity

In order to use Phidgets with Unity, you have to configure your project. Follow the instructions below.

Step 1

Download a copy of the Phidget libraries and unzip it as shown.

Step 2

Next, open Unity and create a new 3D project. Name it PhidgetsMaze and place it in the location of your choice.

Step 3

Navigate to the file you previously unzipped and import Phidget22.NET.dll and phidget22.dll as shown.

Note: If you are developing on macOS, you do not need to import phidget22.dll

Create Environment

Now that your project is configured, you can create your environment.

Step 1

Place a cube on your scene. Under the Transform controls, configure the folloiwng:

  • Y-Position: -1
  • X-Scale: 21
  • Z-Scale: 21

Step 2

Place another cube on your scene. Under the Transform controls, configure the following:

  • X-Position: 10
  • Y-Rotation: 90
  • X-Scale: 21

Step 3

Place another cube on your scene. Under the Transform controls, configure the following:

  • X-Position: -10
  • Y-Rotation: 90
  • X-Scale: 21

Step 4

Place another cube on your scene. Under the Transform controls, configure the following:

  • Z-Position: -10
  • X-Scale: 21

Step 5

Place another cube on your scene. Under the Transform controls, configure the following:

  • Z-Position: 10
  • X-Scale: 21

Step 6

You can rename your objects to something that makes more sense like “Floor” and “Wall”. Nest all of the elements under an object named Table.

Step 7

Next, right-click on your Assets and create a new Prefab.

Step 8

Name the Prefab Maze Wall and place a cube in the scene.

Step 9

Select the Table object and add a new script called TableTilt

Step 10

Finally, right-click on your Assets folder and create a new C# Script wit the name MazeGenerator.

Write Code (C#)

Copy the code below into your TableTilt file.

  
using System.Collections.Generic;
using UnityEngine;
using Phidget22;
using Phidget22.Events;
using MazeGenerator;


public class TableTilt : MonoBehaviour
{
    //Define
    Spatial spatial;
    private Rigidbody rb;
    public GameObject block;
    List<GameObject> blockers = new List<GameObject>();

    //Phidget Events
    double[] q;
    private void Spatial_AlgorithmData(object sender, SpatialAlgorithmDataEventArgs e)
    {
        q = e.Quaternion;
    }

    void Start()
    {
        //Connect Rigidbody
        rb = GetComponent<Rigidbody>();

        //Create
        spatial = new Spatial();

        //Subscribe to Events
        spatial.AlgorithmData += Spatial_AlgorithmData;

        //Open
        spatial.Open(1000);

        //Set data interval to minimum
        spatial.DataInterval = spatial.MinDataInterval;

        CreateMaze();
    }

    int size = 19;
    void CreateMaze()
    {
        MazeMaker builder = new MazeMaker();
        int row, col;
        int xOffset = -9;
        int yOffset = -9;
        bool[,] map = builder.Build();
        for (row = 0; row < size; row++)
        {
            for (col = 0; col < size; col++)
            {

                if (map[row, col] == false)
                {
                    Vector3 position = new Vector3(row + xOffset, 0, col + yOffset);
                    blockers.Add(Instantiate(block, position, Quaternion.identity) as GameObject);
                    blockers[blockers.Count - 1].transform.parent = gameObject.transform;

                }
            }
        }
    }

    void ClearMap()
    {
        int i;
        for (i = 0; i < blockers.Count; i++)
        {
            Destroy(blockers[i]);
        }
    }

    void Update()
    {
        if (q != null)
        {
            rb.MoveRotation(new Quaternion((float)q[0], (float)(-1.0 * q[2]), (float)q[1], (float)q[3]));
        }
    }

    //Required for Unity and Phidgets
    private void OnApplicationQuit()
    {
        spatial.Close();
        spatial.Dispose();
    }
}
  

Write Code (C#)

Copy the code below into your MazeGenerator file.

  
using System;
using System.Collections.Generic;
using System.Collections;

namespace MazeGenerator
{
    class MazeMaker
    {
        const int SIZE = 19;
        private static Random random = new Random();
        public static bool[,] grid = new bool[SIZE, SIZE];

        public bool[,] Build()
        {
            ClearGrid(ref grid);
            Stack stack = new Stack();
            int[] coordinates = { 0, 0 };
            stack.Push(coordinates);
            grid[coordinates[0], coordinates[1]] = true;

            BuildMaze(ref grid, ref stack, ref coordinates);

            bool[,] rGrid = grid;
            //WriteMap(rGrid);
            return rGrid;
        }

        private void ClearGrid(ref bool[,] grid)
        {
            int row, col;
            for (row = 0; row < SIZE; row++)
            {
                for (col = 0; col < SIZE; col++)
                {
                    grid[row, col] = false;
                }
            }
        }
        private static void BuildMaze(ref bool[,] grid, ref Stack stack, ref int[] coordinates)
        {
            List<int[]> connections = new List<int[]>();
            int[] newCoordinates = new int[2];
            int randomC;

            while (stack.Count != 0)
            {
                connections.Clear();
                getConnections(grid, coordinates, ref connections);

                if (connections.Count > 0)
                {
                    randomC = random.Next(connections.Count); //that sorta thing
                    newCoordinates = connections[randomC];

                    int wallRow = coordinates[0] + (newCoordinates[0] - coordinates[0]) / 2;
                    int wallCol = coordinates[1] + (newCoordinates[1] - coordinates[1]) / 2;
                    grid[wallRow, wallCol] = true;
                    coordinates = newCoordinates;
                    grid[coordinates[0], coordinates[1]] = true;
                    stack.Push(coordinates);
                }
                else
                {
                    coordinates = (int[])stack.Pop();
                }
            }
        }

        private static void getConnections(bool[,] grid, int[] coordinates, ref List<int[]> connections)
        {
            //Creating new variables to circumvent issue with list created by reference and containing all the same elements
            int row = coordinates[0];
            int col = coordinates[1];


            if (row + 2 < SIZE && !grid[row + 2, col])
            {
                int[] down = { row + 2, col };
                connections.Add(down);
            }

            if (row - 2 >= 0 && !grid[row - 2, col])
            {
                int[] up = { row - 2, col };
                connections.Add(up);

            }

            if (col + 2 < SIZE && !grid[row, col + 2])
            {
                int[] right = { row, col + 2 };
                connections.Add(right);

            }

            if (col - 2 >= 0 && !grid[row, col - 2])
            {
                int[] left = { row, col - 2 };
                connections.Add(left);
            }

        }
        private static void WriteMap(bool[,] grid)
        {
            int row, col;
            for (row = 0; row < SIZE; row++)
            {
                for (col = 0; col < SIZE; col++)
                {
                    Console.Write(Convert.ToInt32(grid[row, col]));
                }
                Console.Write("\n");
            }
        }
    }
}
  

Add Maze Wall

Before running your code, click on the Table object and set the Block property to MazeWall as shown.

Run Your Program

A maze will be generated within the bounds of your table. When you move your Phidget, the table will move as well.

Code Review

When using the Spatial Phidget, it's important to set the data interval to the minimum as shown in the code above. This will ensure your sensor is as responsive as possible.

The Spatial Phidget returns a quaternion that you can use directly with Unity. Learn more about quaternions here.

Practice

  1. Try adding a ball and target on opposite sides of the maze. Players can tilt the maze with their Spatial Phidget and navigate the ball to the target.

What are Phidgets?

Phidgets are programmable USB sensors. Simply plug in your sensor, write code in your favorite language and go!

Phidgets have been used by STEM professionals for over 20 years and are now available to students.

Learn more

Set your preferences

Windows

Mac OS

Raspberry Pi

Java

Python

C#

Swift

NetBeans

Processing

Eclipse

Thonny

PyCharm

PyScripter

Visual Studio

Xcode

Setting your preferred operating system, programming language and environment lets us display relevant code samples for the Getting Started Tutorial, Device Tutorials and Projects

Done