Code: Select all
using UnityEngine;
using Unity.AI.Navigation;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
[ExecuteAlways]
public class MazeGenerator : MonoBehaviour
{
///
/// Defines the generation state of the maze.
///
public enum MazeState
{
NotStarted,
InProgress,
Done
}
[Header("Maze Size")]
public int width = 30;
public int height = 30;
// Read-only properties for external use
public int Width => width;
public int Height => height;
[Header("Prefabs")]
public GameObject wallPrefab;
public GameObject floorPrefab;
public GameObject entranceMarkerPrefab;
public GameObject exitMarkerPrefab;
public GameObject deadEndMarkerPrefab;
[Header("Options")]
public bool generateEntranceAndExit = true;
// Expose this list to other scripts.
public List DeadEndMarkers { get; private set; } = new List();
// Public property to check the current state of the maze generation
public MazeState CurrentState { get; private set; } = MazeState.NotStarted;
#if UNITY_EDITOR
[Tooltip("If true, the maze generated in Play Mode will persist in the editor after stopping Play Mode.")]
public bool persistRuntimeMazeOnStop = false;
#endif
// maze[x,y] == true => wall
// maze[x,y] == false => walkable path
// Add [SerializeField] to ensure this data is saved with the scene!
[SerializeField]
private bool[,] grid;
public bool[,] Grid => grid;
Code: Select all
public void GenerateAndBuildMaze()
{
CurrentState = MazeState.InProgress;
ClearMaze();
ValidateMazeDimensions();
GenerateMaze();
BuildMaze();
CurrentState = MazeState.Done;
}
Code: Select all
public void GenerateMaze()
{
grid = new bool[width, height];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
grid[x, y] = true;
int startX = 1, startY = 1;
grid[startX, startY] = false;
CarvePath(startX, startY);
if (generateEntranceAndExit)
AddRandomEntranceAndExit();
}
das Editor-Skript:
Code: Select all
using UnityEditor;
using UnityEditor.SceneManagement; // Added this using directive for MarkSceneDirty
using UnityEngine;
[CustomEditor(typeof(MazeGenerator))]
public class MazeGeneratorEditor : Editor
{
public override void OnInspectorGUI()
{
// Draw default inspector fields
DrawDefaultInspector();
MazeGenerator mazeGen = (MazeGenerator)target;
serializedObject.Update();
GUILayout.Space(10);
if (GUILayout.Button("Generate New Maze"))
{
Undo.RecordObject(mazeGen, "Generate New Maze");
mazeGen.GenerateAndBuildMaze();
//
// FIX: Pass the transform of the MazeGenerator object (this is the parent transform)
if (mazeGen.generateEntranceAndExit && mazeGen.Grid != null)
{
// We need to use the transform of the MazeGenerator itself here,
// as that's the parent transform for the visualization in the Editor.
// NOTE: When running the game, MazeGenerator.GenerateNewMaze() passes _currentMaze.transform.
// For Editor visualization, using mazeGen.transform is correct.
MazePathfinder.FindPath(
mazeGen.Grid,
mazeGen.EntranceGridPos,
mazeGen.ExitGridPos,
mazeGen.transform
);
}
//
// The NPC Spawner logic might be redundant if the new MazeGenerator.GenerateNewMaze()
// already handles the NPC, but keeping it here as a placeholder for external spawning:
MarkSceneDirty(mazeGen);
}
if (GUILayout.Button("Clear Maze"))
{
Undo.RecordObject(mazeGen, "Clear Maze");
mazeGen.ClearMaze();
MazePathfinder.LastGeneratedPath.Clear();
MarkSceneDirty(mazeGen);
}
serializedObject.ApplyModifiedProperties();
SceneView.RepaintAll();
}
private void MarkSceneDirty(MazeGenerator mazeGen)
{
if (!Application.isPlaying)
{
EditorUtility.SetDirty(mazeGen);
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(mazeGen.gameObject.scene);
}
}
}
Code: Select all
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NPCMovement : MonoBehaviour
{
[Header("Movement Settings")]
public float MoveSpeed = 5f;
public float RotationSpeed = 720f;
[Header("Automatic Start")]
[Tooltip("If true, the NPC will automatically try to find the maze path and start moving upon scene load.")]
public bool StartMovementOnStart = true;
[Header("Path Visualization")]
[Tooltip("If true, draws a cyan line trail behind the NPC in the Scene View (runtime only).")]
public bool DrawTrailGizmo = true;
private List _path;
private int _pathIndex = 0;
private List _trailHistory = new List();
private bool _isMoving = false;
private Vector3 _targetPosition;
// --- Core Logic: Check for and initiate movement on start ---
private void Start()
{
// 1. Check the control flag set in the Inspector
if (!StartMovementOnStart) return;
// 2. Find the MazeGenerator in the scene
MazeGenerator mazeGen = Object.FindFirstObjectByType();
if (mazeGen == null)
{
Debug.LogError("NPCMovement: Cannot find MazeGenerator in the scene. Movement aborted.");
return;
}
// 3. Ensure the maze grid data is available
if (mazeGen.Grid == null)
{
Debug.LogWarning("NPCMovement: MazeGenerator grid is null. Cannot calculate path at runtime. Please ensure the maze has been generated and persisted in the scene.");
return;
}
Ich dachte, wenn ich [SerializeField] verwende und dann einmal die Schaltfläche zum Generieren eines neuen Labyrinths verwende, wird das Gitter gespeichert und ich kann es dann im letzten Skript verwenden, und es wird nicht null sein.
Da ich das Skript einmal im Editormodus und das im Editor vorhandene Labyrinth erstellt habe, bevor ich das Spiel starte, möchte ich das vorhandene Labyrinth und Gitter verwenden das Bewegungsskript, wenn das Spiel ausgeführt wird, ohne ein neues Labyrinth zu erstellen.

Mobile version