You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 00:21:13