Код: Выделить всё
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();
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 queue = new Queue();
Dictionary previous = new Dictionary();
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 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 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().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();
if (renderer != null)
{
renderer.material = material;
}
}
}
Dictionary previous;
}
Код: Выделить всё
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();
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();
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);
}
}
}
}
Код: Выделить всё
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 edgeCells = new List();
// 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 directions = new List
{
Direction.Up, Direction.Down, Direction.Left, Direction.Right
};
List GetRandomDirections()
{
// A copy of our directions list
List dir = new List(directions);
// A directions list to put our randomised directions into
List rndDir = new List();
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 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 path = new List();
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;
}
}
Пожалуйста, помогите!
Подробнее здесь: https://stackoverflow.com/questions/787 ... g-material