那你用团结引擎开发游戏时,你要进行一个AI自动生成的地图迷宫(臨時生成迷宫,玩家走到哪就生成到哪)但是你又要N PC而且要聪明的,NPC又要知道地图该怎么办

那你用团结引擎开发游戏时,你要进行一个AI自动生成的地图迷宫(臨時生成迷宫,玩家走到哪就生成到哪)但是你又要N PC而且要聪明的,NPC又要知道地图该怎么办

中午好🌞🌞🌞
本答案参考通义千问
在使用团结引擎(Unity)开发游戏时,要实现一个动态生成地图迷宫,同时让NPC能够聪明地追踪玩家,这确实是一个挑战。它涉及到多个技术领域,包括程序化生成(Procedural Generation)、路径规划(Pathfinding)、AI行为逻辑和实时地图更新。
下面我将详细说明如何解决这个难题,并给出具体的解决方案和代码示例。
Grid 或 Tilemap 来表示每个区块。Tilemap 或自定义网格系统。using UnityEngine;
public class MapGenerator : MonoBehaviour
{
public GameObject tilePrefab;
public int chunkSize = 10;
private Dictionary<Vector2Int, GameObject> generatedChunks = new Dictionary<Vector2Int, GameObject>();
void Update()
{
Vector2Int playerPosition = GetPlayerChunkPosition();
if (!generatedChunks.ContainsKey(playerPosition))
{
GenerateChunk(playerPosition);
}
}
private Vector2Int GetPlayerChunkPosition()
{
return new Vector2Int((int)Player.Instance.transform.position.x / chunkSize,
(int)Player.Instance.transform.position.z / chunkSize);
}
private void GenerateChunk(Vector2Int position)
{
// 生成一个包含随机障碍物的迷宫块
GameObject chunk = new GameObject("Chunk_" + position);
chunk.transform.position = new Vector3(position.x * chunkSize, 0, position.y * chunkSize);
for (int x = 0; x < chunkSize; x++)
{
for (int z = 0; z < chunkSize; z++)
{
if (Random.Range(0, 10) > 5)
{
Instantiate(tilePrefab, new Vector3(x, 0, z), Quaternion.identity, chunk.transform);
}
}
}
generatedChunks[position] = chunk;
}
}
重点:此代码实现了按需生成地图块的功能,避免一次性加载全部地图。
public class GridSystem : MonoBehaviour
{
public int cellSize = 1;
public Transform gridParent;
public List<GameObject> gridCells = new List<GameObject>();
void Start()
{
GenerateGrid();
}
void GenerateGrid()
{
foreach (Transform child in gridParent)
{
Destroy(child.gameObject);
}
gridCells.Clear();
for (int x = 0; x < 100; x++)
{
for (int z = 0; z < 100; z++)
{
GameObject cell = new GameObject("Cell_" + x + "," + z);
cell.transform.position = new Vector3(x * cellSize, 0, z * cellSize);
cell.transform.SetParent(gridParent);
gridCells.Add(cell);
}
}
}
public bool IsWalkable(int x, int z)
{
// 根据实际地图判断是否可走
return true; // 示例中默认可走
}
}
重点:网格系统为 AI 提供了统一的路径搜索基础。
public class AStarPathfinder
{
private GridSystem grid;
private List<Node> openSet = new List<Node>();
private HashSet<Node> closedSet = new HashSet<Node>();
private Node[,] nodes;
public AStarPathfinder(GridSystem grid)
{
this.grid = grid;
nodes = new Node[grid.gridCells.Count, grid.gridCells.Count];
InitializeNodes();
}
private void InitializeNodes()
{
for (int i = 0; i < nodes.GetLength(0); i++)
{
for (int j = 0; j < nodes.GetLength(1); j++)
{
nodes[i, j] = new Node(i, j);
}
}
}
public List<Node> FindPath(int startX, int startZ, int endX, int endZ)
{
Node startNode = nodes[startX, startZ];
Node endNode = nodes[endX, endZ];
openSet.Add(startNode);
while (openSet.Count > 0)
{
Node currentNode = GetLowestFCostNode(openSet);
if (currentNode == endNode)
{
return CalculatePath(endNode);
}
openSet.Remove(currentNode);
closedSet.Add(currentNode);
foreach (Node neighbor in GetNeighbors(currentNode))
{
if (closedSet.Contains(neighbor)) continue;
if (!grid.IsWalkable(neighbor.x, neighbor.z)) continue;
int newCostToReach = currentNode.gCost + GetDistance(currentNode, neighbor);
if (newCostToReach < neighbor.gCost || !openSet.Contains(neighbor))
{
neighbor.gCost = newCostToReach;
neighbor.hCost = GetDistance(neighbor, endNode);
neighbor.parent = currentNode;
if (!openSet.Contains(neighbor))
{
openSet.Add(neighbor);
}
}
}
}
return null;
}
private Node GetLowestFCostNode(List<Node> list)
{
Node lowestNode = list[0];
for (int i = 1; i < list.Count; i++)
{
if (list[i].fCost < lowestNode.fCost)
{
lowestNode = list[i];
}
}
return lowestNode;
}
private List<Node> GetNeighbors(Node node)
{
List<Node> neighbors = new List<Node>();
for (int x = -1; x <= 1; x++)
{
for (int z = -1; z <= 1; z++)
{
if (x == 0 && z == 0) continue;
int checkX = node.x + x;
int checkZ = node.z + z;
if (checkX >= 0 && checkX < nodes.GetLength(0) && checkZ >= 0 && checkZ < nodes.GetLength(1))
{
neighbors.Add(nodes[checkX, checkZ]);
}
}
}
return neighbors;
}
private int GetDistance(Node a, Node b)
{
return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.z - b.z);
}
private List<Node> CalculatePath(Node endNode)
{
List<Node> path = new List<Node>();
Node currentNode = endNode;
while (currentNode != null)
{
path.Add(currentNode);
currentNode = currentNode.parent;
}
path.Reverse();
return path;
}
private class Node
{
public int x, z;
public int gCost, hCost;
public Node parent;
public Node(int x, int z)
{
this.x = x;
this.z = z;
}
public int fCost => gCost + hCost;
}
}
重点:A* 算法为 NPC 提供了高效路径搜索能力,保证其能聪明地追踪玩家。
public class NPCAI : MonoBehaviour
{
public Transform player;
public float moveSpeed = 2f;
private AStarPathfinder pathfinder;
private List<AStarPathfinder.Node> path;
private int currentWaypoint = 0;
void Start()
{
pathfinder = new AStarPathfinder(GameObject.Find("GridSystem").GetComponent<GridSystem>());
}
void Update()
{
if (path == null || currentWaypoint >= path.Count)
{
// 寻找新路径
path = pathfinder.FindPath(
(int)transform.position.x,
(int)transform.position.z,
(int)player.position.x,
(int)player.position.z
);
currentWaypoint = 0;
}
if (path != null && currentWaypoint < path.Count)
{
Vector3 targetPosition = new Vector3(path[currentWaypoint].x, 0, path[currentWaypoint].z);
transform.LookAt(targetPosition);
transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
if (Vector3.Distance(transform.position, targetPosition) < 0.1f)
{
currentWaypoint++;
}
}
}
}
重点:NPC 会根据当前地图状态,实时寻找最优路径,实现聪明追踪。
如果你希望我进一步扩展某个部分(例如行为树、多 NPC 同步、网络同步等),请告诉我!