Maze in Unity – calculating shortest path and changing material

The problem seems to be that for some reason the ApplyMaterial only goes to the target cell and does not even try to change the materials of the other cells accordingly. I want the solver to find a path from each point to the target point, and update the material of the walls to “rightArrow” and “leftArrow” and at the target point to put a special material at the top wall, but it never changes. Each wall in my case consists of walls – the inner and the outer, and the maze is generating correctly but the materials dont change. Here is my mazeSolver:

using System.Collections.Generic;
using UnityEngine;

public class MazeSolver : MonoBehaviour
{
    public int mazeWidth = 5, mazeHeight = 5;
    public MazeCell[,] maze;
    public Vector2Int targetPoint;
    public Material leftArrowMaterial;
    public Material rightArrowMaterial;
    public Material specialTopWallMaterial;

    private MazeGenerator mazeGenerator;
    private bool mazeGenerated = false;

    void Start()
    {
        mazeGenerator = GetComponent<MazeGenerator>();
        if (mazeGenerator != null)
        {
            // Subscribe to the MazeGenerationComplete event
            mazeGenerator.MazeGenerationComplete += OnMazeGenerationComplete;
            mazeGenerator.GenerateMaze(); // Start maze generation
        }
        else
        {
            Debug.LogError("MazeGenerator component not found!");
        }
    }

    void OnMazeGenerationComplete()
    {
        maze = mazeGenerator.maze;
        mazeGenerated = true;

        Debug.Log("Maze generation complete. Starting pathfinding...");
        CalculateShortestPath();
    }

    void CalculateShortestPath()
    {
        if (!mazeGenerated)
        {
            Debug.LogError("Maze is not generated yet!");
            return;
        }

        Debug.Log("Calculating shortest path...");

        Queue<Vector2Int> queue = new Queue<Vector2Int>();
        Dictionary<Vector2Int, Vector2Int> previous = new Dictionary<Vector2Int, Vector2Int>();
        bool[,] visited = new bool[mazeWidth, mazeHeight];

        Vector2Int[] directions = { Vector2Int.left, Vector2Int.right, Vector2Int.up, Vector2Int.down };

        queue.Enqueue(targetPoint);
        visited[targetPoint.x, targetPoint.y] = true;

        int iteration = 1;
        while (queue.Count > 0)
        {
            Vector2Int current = queue.Dequeue();

            foreach (Vector2Int direction in directions)
            {
                Vector2Int neighbor = current + direction;

                if (IsValidCell(neighbor) && !visited[neighbor.x, neighbor.y] && !IsWallBetween(current, neighbor))
                {
                    queue.Enqueue(neighbor);
                    visited[neighbor.x, neighbor.y] = true;
                    previous[neighbor] = current;
                }
            }

            Debug.Log("Iteration " + iteration);
            iteration++;
        }

        Debug.Log("Pathfinding complete. Updating maze with arrows...");
        UpdateMazeWithArrows(previous);
    }

    bool IsValidCell(Vector2Int cell)
    {
        return cell.x >= 0 && cell.x < mazeWidth && cell.y >= 0 && cell.y < mazeHeight;
    }

    bool IsWallBetween(Vector2Int cell1, Vector2Int cell2)
    {
        if (cell1.x < cell2.x) return maze[cell1.x, cell1.y].rightWall;
        if (cell1.x > cell2.x) return maze[cell2.x, cell2.y].rightWall;
        if (cell1.y < cell2.y) return maze[cell1.x, cell1.y].topWall;
        if (cell1.y > cell2.y) return maze[cell2.x, cell2.y].topWall;
        return false;
    }

    void UpdateMazeWithArrows(Dictionary<Vector2Int, Vector2Int> previous)
    {
        if (!mazeGenerated)
        {
            Debug.LogError("Maze is not generated yet!");
            return;
        }

        Debug.LogWarning("Updating maze with arrows...");

        if (mazeWidth == 1 && mazeHeight == 1 && targetPoint == Vector2Int.zero)
        {
            Debug.Log("Maze is 1x1 with target at (0, 0). Applying special material to the single cell.");

            // Apply special material to the single cell
            ApplySpecialMaterialToTopWall(Vector2Int.zero);
            return;
        }

        foreach (KeyValuePair<Vector2Int, Vector2Int> entry in previous)
        {
            Vector2Int from = entry.Key;
            Vector2Int to = entry.Value;

            // Ensure 'from' and 'to' are valid maze coordinates
            if (IsValidCell(from) && IsValidCell(to))
            {
                // Apply arrows based on direction
                if (to.x > from.x)
                {
                    ApplyMaterialToWall(from, Direction.Right, rightArrowMaterial);
                }
                else if (to.x < from.x)
                {
                    ApplyMaterialToWall(from, Direction.Left, leftArrowMaterial);
                }
                else if (to.y > from.y)
                {
                    ApplyMaterialToWall(from, Direction.Up, rightArrowMaterial); // Assuming up arrow material same as right
                }
                else if (to.y < from.y)
                {
                    ApplyMaterialToWall(from, Direction.Down, leftArrowMaterial); // Assuming down arrow material same as left
                }

                // Check if this is the target point
                if (to == targetPoint)
                {
                    Debug.Log("target point");
                    ApplySpecialMaterialToTopWall(targetPoint);
                }
            }
            else
            {
                Debug.LogWarning("Invalid maze coordinates in previous dictionary: from=" + from + ", to=" + to);
            }
        }
    }

    void ApplySpecialMaterialToTopWall(Vector2Int cell)
    {
        MazeCell mazeCell = maze[cell.x, cell.y];
        if (mazeCell.topWallObject != null)
        {
            Debug.Log("Applying special material to top wall of target cell");
            mazeCell.topWallObject.GetComponent<Renderer>().material = specialTopWallMaterial;
        }
        else
        {
            Debug.LogWarning("topWallObject is null for the target cell");
        }
    }

    void ApplyMaterialToWall(Vector2Int cell, Direction direction, Material material)
    {
        Debug.Log("Applying material to wall:" + material);
        MazeCell mazeCell = maze[cell.x, cell.y];
        Debug.Log("Cell.x,cell.y and direction is= " + cell.x + cell.y + direction);
        switch (direction)
        {
            case Direction.Up:
                if (mazeCell.topWallObject != null)
                {
                    SetMaterialForWallObjects(mazeCell.topWallObject, material);
                }
                break;
            case Direction.Down:
                if (mazeCell.bottomWallObject != null)
                {
                    SetMaterialForWallObjects(mazeCell.bottomWallObject, material);
                }
                break;
            case Direction.Left:
                if (mazeCell.leftWallObject != null)
                {
                    SetMaterialForWallObjects(mazeCell.leftWallObject, material);
                }
                break;
            case Direction.Right:
                if (mazeCell.rightWallObject != null)
                {
                    SetMaterialForWallObjects(mazeCell.rightWallObject, material);
                }
                break;
        }
    }

    void SetMaterialForWallObjects(GameObject wallParent, Material material)
    {
        // Assuming the outer and inner walls are children of wallParent
        foreach (Transform child in wallParent.transform)
        {
            Debug.Log("Applying material to wall in set for wall objects" + material);
            Renderer renderer = child.GetComponent<Renderer>();
            if (renderer != null)
            {
                renderer.material = material;
            }
        }
    }

    Dictionary<Vector2Int, Vector2Int> previous;
}

my mazeRenderer:

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

public class MazeRenderer : MonoBehaviour
{
    public MazeCell[,] maze;

    [SerializeField] MazeGenerator mazeGenerator;
    [SerializeField] GameObject MazeCellPrefab;

    public float CellSize = 1f;

    private void Start()
    {
        // Get MazeGenerator component and subscribe to maze generation complete event
        mazeGenerator = GetComponent<MazeGenerator>();
        if (mazeGenerator != null)
        {
            mazeGenerator.MazeGenerationComplete += RenderMaze;
        }
        else
        {
            Debug.LogError("MazeGenerator component not found on the same GameObject.");
        }
    }

    void RenderMaze()
    {
        // Ensure mazeGenerator and maze are not null
        if (mazeGenerator == null || mazeGenerator.maze == null)
        {
            Debug.LogError("MazeGenerator or maze is null. Maze cannot be rendered.");
            return;
        }

        maze = mazeGenerator.maze;

        for (int x = 0; x < mazeGenerator.mazeWidth; x++)
        {
            for (int y = 0; y < mazeGenerator.mazeHeight; y++)
            {
                GameObject newCell = Instantiate(MazeCellPrefab, new Vector3((float)x * CellSize, 0f, (float)y * CellSize), Quaternion.identity, transform);

                MazeCellObject mazeCell = newCell.GetComponent<MazeCellObject>();

                bool top = maze[x, y].topWall;
                bool left = maze[x, y].leftWall;

                bool right = false;
                bool bottom = false;
                if (x == mazeGenerator.mazeWidth - 1) right = true;
                if (y == 0) bottom = true;

                mazeCell.Init(top, bottom, right, left);
            }
        }
    }
}

and my mazeGenerator:

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

public class MazeGenerator : MonoBehaviour
{
    public int mazeWidth = 10, mazeHeight = 10; // The dimensions of the maze
    public int startX, startY;                // The start position of the maze
    public GameObject lightPrefab;
    public GameObject vrCharacter;            // Reference to the VR character

    private MazeCell[,] _maze;                // An array of maze cells

    public MazeCell[,] maze
    {
        get { return _maze; }
        private set { _maze = value; } // Private setter
    }
    Vector2Int currentCell;                   // Current cell position
    // Event to notify when maze generation is complete
    public event Action MazeGenerationComplete;

    // Start is called before the first frame update
    void Start()
    {
        // Disable directional light
        GameObject directionalLight = GameObject.Find("Directional Light");
        if (directionalLight != null)
        {
            directionalLight.SetActive(false);
        }

        // Set ambient light to dark
        RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
        RenderSettings.ambientLight = Color.black;

        // Enable and configure fog
        RenderSettings.fog = true;
        RenderSettings.fogMode = FogMode.ExponentialSquared;
        RenderSettings.fogColor = Color.black;
        RenderSettings.fogDensity = 0.05f;

        GenerateMaze();
    }

    public void GenerateMaze()
    {
        maze = new MazeCell[mazeWidth, mazeHeight];

        for (int x = 0; x < mazeWidth; x++)
        {
            for (int y = 0; y < mazeHeight; y++)
            {
                maze[x, y] = new MazeCell(x, y);

                if (x % 4 == 0 && y % 4 == 0)
                {
                    Vector3 cellPosition = new Vector3(x, 0, y); // Adjust the y value as needed
                    Instantiate(lightPrefab, cellPosition, Quaternion.identity);
                }
            }
        }

        CarvePath(startX, startY);

        // Select an edge cell as the target point and add the special cell
        Vector2Int targetPoint = SelectEdgeCell();

        PositionCharacterAtStart();

        // Notify listeners (like MazeSolver) that maze generation is complete
        if (MazeGenerationComplete != null)
        {
            MazeGenerationComplete.Invoke();
        }
    }

    Vector2Int SelectEdgeCell()
    {
        List<Vector2Int> edgeCells = new List<Vector2Int>();

        // Top row
        for (int x = 0; x < mazeWidth; x++)
        {
            edgeCells.Add(new Vector2Int(x, mazeHeight - 1));
        }
        // Right column
        for (int y = 1; y < mazeHeight - 1; y++)
        {
            edgeCells.Add(new Vector2Int(mazeWidth - 1, y));
        }

        // Select a random edge cell
        int rndIndex = UnityEngine.Random.Range(0, edgeCells.Count);
        
        return edgeCells[rndIndex];
    }

    /*void AddSpecialCell(int x, int y)
    {
        if (x < 0 || y < 0 || x > mazeWidth - 1 || y > mazeHeight - 1)
        {
            Debug.LogWarning("Special cell position is out of bounds");
            return;
        }

        // Instantiate the special cell
        GameObject specialCell = Instantiate(specialCellPrefab);

        // Find the attach point in the special cell
        Transform attachPoint = specialCell.transform.Find("AttachPoint");
        if (attachPoint == null)
        {
            Debug.LogError("AttachPoint not found in special cell prefab");
            return;
        }

        // Calculate the position of the special cell based on the attach point
        Vector3 cellPosition = new Vector3(x, 0, y);
        Vector3 offset = attachPoint.position - specialCell.transform.position;
        specialCell.transform.position = cellPosition - offset;

        // Remove the appropriate wall of the target cell to create an entrance
        if (x == mazeWidth - 1) // Right edge
        {
            maze[x, y].leftWall = false; // The right wall is part of the next cell's left wall
        }
        else if (y == mazeHeight - 1) // Top edge
        {
            maze[x, y].topWall = false;
        }
    }*/

    void PositionCharacterAtStart()
    {
        if (vrCharacter != null)
        {
            Vector3 startPosition = new Vector3(0, 1, 0); // Adjust the y value to place the character correctly on the ground
            vrCharacter.transform.position = startPosition;
            vrCharacter.transform.rotation = Quaternion.identity; // Reset rotation if needed
        }
    }

    List<Direction> directions = new List<Direction>
    {
        Direction.Up, Direction.Down, Direction.Left, Direction.Right
    };

    List<Direction> GetRandomDirections()
    {
        // A copy of our directions list
        List<Direction> dir = new List<Direction>(directions);

        // A directions list to put our randomised directions into
        List<Direction> rndDir = new List<Direction>();

        while (dir.Count > 0)
        {
            int rnd = UnityEngine.Random.Range(0, dir.Count);
            rndDir.Add(dir[rnd]);
            dir.RemoveAt(rnd);
        }

        return rndDir;
    }

    bool IsCellValid(int x, int y)
    {
        // If the cell is outside the map or if it was already visited it will be considered invalid
        if (x < 0 || y < 0 || x > mazeWidth - 1 || y > mazeHeight - 1 || maze[x, y].visited) return false;
        else return true;
    }

    Vector2Int CheckNeighbours()
    {
        List<Direction> rndDir = GetRandomDirections();
        for (int i = 0; i < rndDir.Count; i++)
        {
            Vector2Int neighbour = currentCell;

            switch (rndDir[i])
            {
                case Direction.Up:
                    neighbour.y++;
                    break;
                case Direction.Down:
                    neighbour.y--;
                    break;
                case Direction.Right:
                    neighbour.x++;
                    break;
                case Direction.Left:
                    neighbour.x--;
                    break;
            }

            if (IsCellValid(neighbour.x, neighbour.y)) return neighbour;
        }

        return currentCell;
    }

    void BreakWalls(Vector2Int primaryCell, Vector2Int secondaryCell)
    {
        if (primaryCell.x > secondaryCell.x) // Primary cell's left wall
        {
            maze[primaryCell.x, primaryCell.y].leftWall = false;
        }
        else if (primaryCell.x < secondaryCell.x) // Secondary cell's left wall
        {
            maze[secondaryCell.x, secondaryCell.y].leftWall = false;
        }
        else if (primaryCell.y < secondaryCell.y) // Primary cell's top wall
        {
            maze[primaryCell.x, primaryCell.y].topWall = false;
        }
        else if (primaryCell.y > secondaryCell.y) // Secondary cell's top wall
        {
            maze[secondaryCell.x, secondaryCell.y].topWall = false;
        }
    }

    void CarvePath(int x, int y)
    {
        if (x < 0 || y < 0 || x > mazeWidth - 1 || y > mazeHeight - 1)
        {
            x = y = 0;
            Debug.LogWarning("Starting position is out of bounds, defaulting to 0,0");
        }

        currentCell = new Vector2Int(x, y);
        List<Vector2Int> path = new List<Vector2Int>();

        bool deadEnd = false;
        while (!deadEnd)
        {
            Vector2Int nextCell = CheckNeighbours();

            if (nextCell == currentCell)
            {
                for (int i = path.Count - 1; i >= 0; i--)
                {
                    currentCell = path[i];
                    path.RemoveAt(i);
                    nextCell = CheckNeighbours();

                    if (nextCell != currentCell)
                    {
                        break;
                    }
                }

                if (nextCell == currentCell)
                {
                    deadEnd = true;
                }
            }
            else
            {
                BreakWalls(currentCell, nextCell);
                maze[currentCell.x, currentCell.y].visited = true;
                currentCell = nextCell;
                path.Add(currentCell);
            }
        }
    }
}

public enum Direction
{
    Up,
    Down,
    Left,
    Right
}

public class MazeCell
{
    public bool visited;
    public int x, y;

    public bool topWall;
    public bool leftWall;
    public bool rightWall;
    public bool bottomWall;

    public bool rightArrow;
    public bool leftArrow;

    // Reference to the wall GameObjects
    public GameObject topWallObject;
    public GameObject leftWallObject;
    public GameObject rightWallObject;
    public GameObject bottomWallObject;

    public GameObject arrowObject;

    // Return x,y as Vector2Int
    public Vector2Int position
    {
        get
        {
            return new Vector2Int(x, y);
        }
    }

    public MazeCell(int x, int y)
    {
        // The coordinates of this cell in the maze grid
        this.x = x;
        this.y = y;

        visited = false;
        topWall = leftWall = rightWall = bottomWall = true;

        rightArrow = leftArrow = false;
    }
}

Already checked that everything is applied correctly and I just dont get why doent it work.
Please help!

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật