Unity迷宫生成脚本修改:支持外部配置长宽及参数合法性校验
Unity 迷宫生成脚本修改实现
核心实现逻辑
- 所有尺寸参数全部暴露为Inspector可配置公共参数,新增参数合法性校验,不符合要求直接打印错误日志终止执行
- 自动读取墙体预制体的实际网格尺寸,基于输入的迷宫长宽自动计算整体尺寸,缩放地面对象适配迷宫大小
- 外墙、内墙的生成起始位置完全基于地面中心和迷宫总尺寸计算,无硬编码坐标
- 内墙生成的循环边界完全由输入的迷宫长宽推导,无固定写死的迭代次数
- 出入口固定为西墙中间位置为入口、北墙中间位置为出口,可直接切顶视角验证生成结果
修改完成的C#脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Labyrinth : MonoBehaviour { [Header("资源引用")] public Transform wallPrefab; public Transform ground; [Header("迷宫参数(必须为≥2的偶数)")] public int mazeWidth; public int mazeDepth; private float _wallUnitSize; private float _totalMazeSizeX; private float _totalMazeSizeZ; private Vector3 _mazeCenterPos; void Start () { // 基础空引用校验 if (wallPrefab == null) { Debug.LogError("未赋值墙体预制体,脚本终止执行"); return; } if (ground == null) { Debug.LogError("未赋值地面对象,脚本终止执行"); return; } // 迷宫参数合法性校验 if (mazeWidth < 2 || mazeWidth % 2 != 0) { Debug.LogError($"迷宫宽度必须为≥2的偶数,当前输入值为{mazeWidth},脚本终止执行"); return; } if (mazeDepth < 2 || mazeDepth % 2 != 0) { Debug.LogError($"迷宫深度必须为≥2的偶数,当前输入值为{mazeDepth},脚本终止执行"); return; } // 计算单块墙体的实际尺寸 Transform wallChild = wallPrefab.transform.GetChild(0); if (wallChild == null) { Debug.LogError("墙体预制体缺少子物体网格,脚本终止执行"); return; } MeshFilter meshFilter = wallChild.GetComponent<MeshFilter>(); if (meshFilter == null) { Debug.LogError("墙体子物体缺少MeshFilter组件,脚本终止执行"); return; } Mesh wallMesh = meshFilter.mesh; Vector3 meshSize = wallMesh.bounds.size; Vector3 wallScale = wallChild.transform.localScale; _wallUnitSize = meshSize.x * wallScale.x; // 计算迷宫总尺寸与中心位置 _totalMazeSizeX = mazeWidth * _wallUnitSize; _totalMazeSizeZ = mazeDepth * _wallUnitSize; _mazeCenterPos = transform.position; // 缩放地面对象适配迷宫尺寸,适配Unity默认平面10x10米基准,自定义地面可按需调整缩放系数 Vector3 groundOriginalScale = ground.localScale; ground.localScale = new Vector3( _totalMazeSizeX / 10f, groundOriginalScale.y, _totalMazeSizeZ / 10f ); ground.position = _mazeCenterPos; // 生成外墙 GenerateOuterWalls(); // 生成内墙 GenerateInnerWalls(); } /// <summary> /// 生成迷宫四周外墙,预留固定出入口 /// </summary> void GenerateOuterWalls() { float halfX = _totalMazeSizeX / 2f; float halfZ = _totalMazeSizeZ / 2f; float spawnY = wallPrefab.position.y; // 南墙(Z轴负方向边,无缺口) for (int x = 0; x <= mazeWidth; x++) { float spawnX = _mazeCenterPos.x - halfX + x * _wallUnitSize; float spawnZ = _mazeCenterPos.z - halfZ; Instantiate(wallPrefab, new Vector3(spawnX, spawnY, spawnZ), Quaternion.identity, transform); } // 北墙(Z轴正方向边,中间留出口缺口) int exitGapIndex = mazeWidth / 2; for (int x = 0; x <= mazeWidth; x++) { if (x == exitGapIndex) continue; float spawnX = _mazeCenterPos.x - halfX + x * _wallUnitSize; float spawnZ = _mazeCenterPos.z + halfZ; Instantiate(wallPrefab, new Vector3(spawnX, spawnY, spawnZ), Quaternion.identity, transform); } // 西墙(X轴负方向边,中间留入口缺口) int entranceGapIndex = mazeDepth / 2; for (int z = 1; z < mazeDepth; z++) { if (z == entranceGapIndex) continue; float spawnX = _mazeCenterPos.x - halfX; float spawnZ = _mazeCenterPos.z - halfZ + z * _wallUnitSize; Instantiate(wallPrefab, new Vector3(spawnX, spawnY, spawnZ), Quaternion.identity, transform); } // 东墙(X轴正方向边,无缺口) for (int z = 1; z < mazeDepth; z++) { float spawnX = _mazeCenterPos.x + halfX; float spawnZ = _mazeCenterPos.z - halfZ + z * _wallUnitSize; Instantiate(wallPrefab, new Vector3(spawnX, spawnY, spawnZ), Quaternion.identity, transform); } } /// <summary> /// 生成迷宫内部墙体,循环次数完全由迷宫参数推导 /// </summary> void GenerateInnerWalls() { float halfX = _totalMazeSizeX / 2f; float halfZ = _totalMazeSizeZ / 2f; float spawnY = wallPrefab.position.y; // 生成纵向内墙(平行于Z轴) for (int x = 1; x < mazeWidth; x += 2) { float spawnX = _mazeCenterPos.x - halfX + x * _wallUnitSize; for (int z = 0; z < mazeDepth; z += 2) { float spawnZ = _mazeCenterPos.z - halfZ + z * _wallUnitSize; // 30%概率留通路,保证迷宫可通行 if (Random.value > 0.3f) { Instantiate(wallPrefab, new Vector3(spawnX, spawnY, spawnZ), Quaternion.identity, transform); } } } // 生成横向内墙(平行于X轴) for (int z = 1; z < mazeDepth; z += 2) { float spawnZ = _mazeCenterPos.z - halfZ + z * _wallUnitSize; for (int x = 0; x < mazeWidth; x += 2) { float spawnX = _mazeCenterPos.x - halfX + x * _wallUnitSize; if (Random.value > 0.3f) { Instantiate(wallPrefab, new Vector3(spawnX, spawnY, spawnZ), Quaternion.Euler(0,90,0), transform); } } } } void Update () { } }
使用说明
- 将脚本挂载到迷宫根空物体上,在Inspector面板分别赋值墙体预制体、场景中的地面对象
- 输入符合要求的偶数长宽值,运行场景即可自动生成适配尺寸的迷宫
- 切换到场景视图顶视角,可直接观察迷宫结构、墙体对齐情况、出入口位置是否符合预期
内容的提问来源于stack exchange,提问作者Mischa Plumps
相关产品推荐
相关产品推荐

