How I implemented A* pathfinding in Unity C# (with DFS maze generation) Unity game developer Abdul Fahad Shahbaz implemented A* pathfinding and DFS maze generation in C# for an AI-driven 3D maze game. The procedural maze is generated using iterative Depth-First Search, and a custom A* pathfinder navigates the grid-based maze in real time, avoiding Unity's built-in NavMesh which cannot handle runtime-generated geometry. Posted by Abdul Fahad Shahbaz — Unity game developer based in Lahore, Pakistan. Portfolio: fahadshahbaz.fun In my latest Unity project — an AI-driven 3D maze game — I needed two things to work together: a maze generator that creates a unique, fully-connected layout every run, and an enemy AI that could navigate those mazes intelligently in real time. The challenge? The maze is procedural. That means I can't bake a navmesh ahead of time or rely on Unity's built-in navigation system. Every time the player starts a run, a brand new maze is generated — and the enemy has to find its way through it from scratch. I solved this with two algorithms working in tandem: Depth-First Search DFS to generate the maze A pathfinding to navigate it In this post I'll explain both implementations with working C code taken directly from the project. By the end you'll have a self-contained AStarPathfinder class you can drop into any Unity maze project. My portfolio see the full project : https://fahadshahbaz.fun/works/AI-Maze-Game https://fahadshahbaz.fun/works/AI-Maze-Game The problem with Unity's built-in NavMesh Unity's NavMesh is excellent for static environments. But procedural mazes create geometry at runtime — walls are instantiated, corridors are carved, the whole layout is different every time. By the time the maze is ready, it's too late to bake a navmesh without adding significant frame time. I needed a pathfinder that: Works on a grid, not a mesh Knows which cells have walls between them not just which cells exist Converts grid coordinates back to world-space Vector3 positions the enemy can walk to A custom A implementation turned out to be the cleanest fit. Part 1: Generating the maze with DFS Before we can pathfind through a maze, we need a maze. I used iterative Depth-First Search also called "recursive backtracker" because it produces long, winding corridors that feel natural for a 3D game — not a grid of perfect squares. The algorithm works like this: Start at a random cell, mark it visited Pick a random unvisited neighbour Remove the wall between the current cell and that neighbour Move to the neighbour and repeat If no unvisited neighbours exist, backtrack to the previous cell Repeat until all cells are visited Every cell in the grid is a MazeCell — a simple data structure that tracks which of its four walls left, right, front, back are still standing. csharp public class MazeCell { private bool rightWall = true; private bool leftWall = true; private bool frontWall = true; private bool backWall = true; public bool HasRightWall = rightWall; public bool HasLeftWall = leftWall; public bool HasFrontWall = frontWall; public bool HasBackWall = backWall; public void RemoveRightWall = rightWall = false; public void RemoveLeftWall = leftWall = false; public void RemoveFrontWall = frontWall = false; public void RemoveBackWall = backWall = false; } The generator keeps a Stack to track the path for backtracking. When it carves a passage between cell A and cell B, it removes A's wall facing B and B's wall facing A — so both cells agree on the opening. csharp// Example: carving a passage to the RIGHT currentCell.RemoveRightWall ; grid next.x, next.y .RemoveLeftWall ; The result is a MazeCell , grid where every cell knows exactly which of its walls are still standing. This is the data structure the A pathfinder reads directly. Why DFS over Prim's or Kruskal's? DFS produces mazes with a single long main path and fewer dead ends — which feels more fun to race through. Prim's produces mazes with many short dead ends, which is better for puzzle games. For a time-pressure race game, DFS was the right call. Part 2: A pathfinding through a wall-aware grid Here is the full AStarPathfinder class from the project. csharp using System.Collections.Generic; using UnityEngine; public class AStarPathfinder { private MazeCell , grid; private int width; private int depth; private float cellSizeX; private float cellSizeZ; private Vector3 originOffset; public AStarPathfinder MazeCell , grid, int width, int depth, float cellSizeX, float cellSizeZ, Vector3 originOffset = default { this.grid = grid; this.width = width; this.depth = depth; this.cellSizeX = cellSizeX; this.cellSizeZ = cellSizeZ; this.originOffset = originOffset; } I pass in cellSizeX, cellSizeZ, and originOffset so the pathfinder can convert grid coordinates back to Unity world space at the end. The maze cells live in a logical grid integer indices , but the enemy AI needs real Vector3 positions to move to. The Node class csharp class Node { public int x, z; public float g, h; public float f = g + h; public Node parent; public Node int x, int z { this.x = x; this.z = z; } } Each node holds: x, z — grid coordinates I use Z for depth, matching Unity's coordinate system g — cost from the start node to this node h — heuristic estimate to the goal Manhattan distance f — total estimated cost g + h ; this is what A uses to prioritise nodes parent — the node we came from, used to retrace the path at the end The main search loop csharp public List