关于 scenario-unity-world-building
面向 Unity 关卡与环境美术师的世界构建技能,涵盖地形、灰盒、导航、引导、场景流式加载和性能分析。它强调可再生成的程序化内容,并通过角色尺寸、路径、画面捕获和 Player 测试验证关卡。
主要功能
- 01构建并审核程序化地形
- 02以角色和相机指标搭建灰盒
- 03检查导航网格与关卡连通性
- 04布置地标、路径与海岸内容
- 05测试场景流式加载
- 06分析视点性能预算
适用场景
- 01生成带道路和植被的地形
- 02验证角色能否通行并到达各区域
- 03检查地标引导和世界边缘内容
- 04在 Player 中测量场景加载与帧预算
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-unity-world-building安装后在 Claude Code 中输入/scenario-unity-world-building确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/critique.mdexpert-notes.mdgui-paths.mdprocedures.mdsources.mdscripts/ut_world.pyscripts/AgentKit/World/WorldBlockout.csWorldCommon.csWorldGuidance.csWorldGym.csWorldKit.csWorldNav.csWorldScenes.csWorldStreaming.csWorldTerrain.csscripts/Runtime/World/AgentKit.World.Runtime.asmdefProfileTour.csStreamProbe.csWfc.csWorldGuide.csWorldNoise.csWorldStreamer.cs详细介绍
Unity 世界构建(关卡与环境美术师)
专业的世界构建以结构为先,然后生成可重新生成的内容,最后进行验证:角色适配每个空间,摄像机适配每个门口,玩家能到达每个空间并原路返回,世界边缘有内容,最差视角也能在 Player 中满足帧预算。没有鼠标的 Agent 通过 TerrainData、ProBuilder API、PrefabUtility 和场景 API 完成所有工作,然后使用射线检测、NavMesh 路径、截图、性能分析巡查和 Player 探针进行检查。目标:Unity 6000.3.21f1、URP 17.3、ProBuilder 6.1.2、Splines 2.9.0、AI Navigation 2.0.14。如果这里提到的同级技能不在可用技能中,请让用户安装它(npx skills add scenario-labs/skills --skill <name>);无人值守时,根据工具架构继续操作并标明缺失项。
必备背景: scenario-unity-expert(通道、审查循环、6.3 陷阱)。导入其工具包;本技能新增 scripts/ut_world.py、scripts/AgentKit/World/ 中的 C# 任务,以及 scripts/Runtime/World/ 中的运行时程序集。
状态(2026-09-24,盲评重构后): 除 references/procedures.md 中标记为 [not run] 的计划外,所有流程均已在这台 Mac 上的 Unity 6000.3.21f1 中运行:
tests/code/unity-world-building/test_live_world.py(13 个实时测试)、test_live_world_v2.py(12 个实时测试)和 test_offline.py(7 个)。
立场(专家的关键差异)
- 先锁定结构,再处理内容。 雕刻前确定地形尺寸和每张纹理的分辨率(之后更改会导致缩放或重采样,见 6.3 Terrain 手册);灰盒搭建前先根据角色和摄像机确定度量标准,并在控制器每次变更时重建健身房来验证(关卡设计电子书,健身房/动物园);放置前先确定套件网格(Christina Creates Games,0o-QnNs-stc [00:07:35])。在代码中,写入 splat 前先持久化
TerrainData资源,否则 alphamap 会丢失(观察所得)。 - 以非破坏性方式创作,并以确定性方式重新生成。 Alba 将可移动特征、整平工具和道路渲染到高度图中,并在开始游戏前和 CI 中按顺序逐步重新生成世界;这些步骤可以跳过。生成的场景会提交到版本库,并使用
git update-index --skip-worktree标记(Manesh Mistry,YOtDVv5-0A4 [00:06:10]、[00:09:52]、[00:10:05])。从占地轮廓重建的 PolyShape 会丢弃所有后续编辑(ProBuilder 手册;观察所得:面数从 12 减至 7):保留配方,而不是编辑后的网格。 - 原始程序化输出需要第二层加工。 噪声需要侵蚀处理(Lague,eaXk97ujbPQ);WFC 需要手工制作的瓦片(DV Gen,20KHNA9jTsE [00:04:22]);道路需要路径规划:考虑坡度的 A* 路径切出了 2.6 m 深的沟壑,而直线节点切出了 9.1 m 深的峡谷(Alba [00:07:45];观察所得)。
- 先用一个通用部件搭建灰盒,再批量替换;为每个部件和每个组合体创建预制件。 先在所有位置使用同一面墙,再通过替换加入门窗(Christina [00:15:14]);修正度量标准只需编辑一次预制件(YsBniZ5ya7k [00:06:25])。在脚本中,替换前记录实例覆盖项:没有
RecordPrefabInstancePropertyModifications时,ReplacePrefabAssetOfPrefabInstance会保留 0 个位置(共 30 个);使用后则保留 30 个(共 30 个)(观察所得;网格审核没有发现问题,但插槽和周界审核发现了问题)。 - 灰盒阶段的退出门槛必须明确且可执行。 根据 Agent 半径和摄像机摇臂确定门的尺寸;NavMesh 覆盖每一整层楼,烘焙时排除门扇,并确保杂物不会把房间隔开;屋顶标记为 Not Walkable,连接上层楼面,每个区域使用一个 NavMesh Surface(Christina [00:17:12]、[00:19:27];YsBniZ5ya7k [00:15:24]);快速烘焙以检查暗区;先放置地标和路径,最后再放标识(Adam Robinson-Yu,ZW8gWgpptI8 [00:18:37])。
- 玩家会先探索边缘;用逐步引导的方式指路。 在岛上,玩家会游到岛外并绕岛一圈:每段海岸都要有内容和返回路径,而不是墙([00:16:54]、[00:17:58])。先放地标、面包屑式引导和能通向回程的路径,设置朝向目标的坡道,最后再放标识;虚假的山峰必须有存在理由。这里有 36 个海岸方向,其中 32 个在 150 m 范围内没有任何内容(观察所得)。
- 只流式加载放不下的内容,并围绕持久化核心进行;在 Player 中评估效果。 Alba 通过 LOD 和相关性系统让岛屿始终驻留([00:12:43])。核心负责 RenderSettings、光照贴图和雾;按路径加载;游戏运行时绝不要让
allowSceneActivation = false保持不变(这曾导致排队中的卸载冻结一秒,观察所得);卸载后清理资源;可见区块被卸载时显示合并代理。backgroundLoadingPriority和 Integrate 标记只有在构建后的 Player 中才有意义(6.3 Scripting API;此处 Editor 计数器显示为 0)。 - 从最差视角开始分析性能、对比统计数据,并根据设备的实际情况修复。 传送到锚点,旋转 360 度,保留表现最差的朝向(Alba [00:29:46]);每侧对比约 200 帧(Profile Analyzer,[00:17:00])。在基于瓦片的移动 GPU 上,不透明 LOD 植被优于 Alpha 测试的伪像(7.12 / 32.5 ms,[00:20:14]);Firewatch 的远距离 Alpha 截断是针对 PC 和主机的选择(Jane Ng,ZYnS3kKTcGg [00:20:29])。LOD Group 树会忽略
Terrain.treeDistance(60 m 和 700 m 得到的帧数相同,观察所得):LOD Group 才是调节手段。
首先确定
平台和预算(默认桌面端 60 fps = 16.67 ms;移动端 30 fps:33.3 ms 帧时间的 65 % =
21.7 ms,scenario-unity-expert);最低配置设备的内存(决定是否需要流式加载);世界大小和移动速度;角色(半径、高度、坡度限制、台阶高度、跳跃距离)及其相机(枢轴、肩部偏移、悬臂、俯仰角);美术风格和雾效规范;内容来源(手工制作、程序化、混合)以及由谁绘制;用户的编辑器是否锁定了项目
(ut_env.project_lock)。默认值:URP、1 km 地形、高度图 1025、1 m 灰盒网格、2.5 m 套件网格、层高 3 m、胶囊体 0.4 x 1.8 m、坡度 45、台阶 0.3、跳跃 2.5 m [added]。
工作流
每个阶段对应一次 ut_world 调用;引擎调用、参数和记录的结果见
references/procedures.md。
- 规格。 指标、分辨率、网格、预算、锚点、内存预算。GATE:每项后续检查都有明确数值。
- 地形。
build_island(先确定分辨率,再进行 fBm、侵蚀、平整、A* 道路、规则化纹理混合、LOD 树木、实例化细节),DCC 高度图使用raw_roundtrip,使用set_terrain_settings设置 Toolbox 无法批量处理的逐瓦片设置。GATE:2^n+1、区块 16、细节种子各不相同、道路坡度 <= 10 %,在全新编辑器中运行audit后无错误。 - 训练场,然后灰盒。
build_gym(P, metrics)(控制器发生任何更改后运行gym_is_stale),然后运行build_village。GATE:门的尺寸通过 NavMesh 检查,且已知相机裁剪比例;每栋建筑都能通过PathComplete到达;所有对象都有 UV2;名称中包含尺寸。 - 套件。 运行
build_kit,然后运行kit_nav_gate。GATE:网格、层高、偏航角、插槽和周边审计均无问题;烘焙时忽略门扇;屋顶没有孤岛;楼层之间已连通。 - 引导。 运行
setup_views(书签、锚点、视线、出生点)、audit_guidance,并运行fill_coast,直到最长空白弧段符合要求。GATE:每个锚点都能看到地标或位于主路径上;每个 POI 都可步行返回;出生点圆点 >= 0.7。 - 外观。 关闭雾效时运行
capture(布局),开启雾效时运行capture(外观);在细节、LOD 和剔除距离处运行capture_pops。打开每张图表;依据references/critique.md进行评判。GATE:没有空白、黑色、白色或洋红色画面;已记录跳变尺寸。 - 流式加载(仅在需要时)。 先运行
scene_report;然后运行split_streaming、build_proxies、streaming_tests、stream_probe。GATE:PlayMode 5/5;Player Integrate 标记在优先级预算内;扫描后内存恢复至基线。 - 巡游。 运行
tour_profile,每次更改前后都运行compare_runs。GATE:每个锚点都通过budget_check;在编辑器中依据数量判定,在设备上依据毫秒数判定。
数值
| 数值 | 对应内容 | 来源 |
|---|---|---|
| 2^n+1(513、1025、2049) | 高度图;侵蚀至少需要 1025 | 6.3 Terrain manual |
| 16 | 每个区块的细节分辨率(仅稀疏的远处草地需要更高值) | 6.3 manual |
| 4 | 每张带高度混合的 splat map 可包含的地形图层数 | smnLYvF40s4 [00:04:23] |
| 2 / 4 / 10 / 50 ms | 每帧 Integrate 预算:Low / BelowNormal / Normal / High,仅限 Player | 6.3 Scripting API |
| 2.5 x 3 m,Y = 3 n | 模块化墙体,层高 | 0o-QnNs-stc [00:07:35] |
| 1.0 m | 0.4 m 胶囊体可通过的最窄门宽(0.8 时无法通过) | gym,实测 |
| 80 % / 27 % | 摄像机支臂(3.5 m,20 度)被 1.4 x 2.4 m / 2 x 3 m 门口遮挡的比例 | gym,实测 |
| 40 通过,45 失败 | 斜坡角度;斜率上限为 45 度时,NavMesh 和 CharacterController 结果一致 | gym,实测 |
| 0.13 至 0.06 m | 楼梯上的 NavMesh 高度误差;未启用 / 启用 Build Height Mesh | gym,实测 |
| 0.5 至 1.13 / 2 ms | Low 下每帧 Player Integrate 最大值(村庄区块,加载耗时 34 至 371 ms) | stream_probe,实测 |
| 7.12 / 32.5 ms | iPad Mini 4 上的 GPU 植被替身开销 | YOtDVv5-0A4 frame [00:19:53] |
| ~200 帧 | 前后对比的每一侧帧数 | YOtDVv5-0A4 [00:17:00] |
| 150 m,300 m | POI 半径、最长的空旷海岸弧段(默认值待调整) | [added] |
质量门槛
- 可测量: 包络
ok,编译错误为零;地形审计 0 个错误(桌面端和mobile=True);白盒、模块槽位和周边审计均无问题;模块 NavMesh 门槛;gym 表格;指导门槛;NUnit EditMode 8/8 和 PlayMode 5/5;Player 探针判定;每个锚点的budget_check;compare_runsp 值。 - 视觉: 已打开关闭雾、开启雾、弹出效果和代理表;
ut_review无标记;使用相同书签进行前后对比;细节应有层次:普通岩石和树木只需呈现形状,叙事道具则需刻画细致;三块岩石够用时,不要再加第四块(Firewatch,ZYnS3kKTcGg [00:24:27]、[00:25:50])。
常见错误
| 错误 | 表现 | 修复 |
|---|---|---|
SetAlphamaps 后调用 CreateAsset(terrainData) | 在全新的编辑器中,地形全部显示为第一层 | 先创建资源,再添加图层 |
未记录移动后调用 ReplacePrefabAssetOfPrefabInstance | 替换后的墙体堆叠在房屋原点,出现孔洞;网格审计正常 | 放置后调用 RecordPrefabInstancePropertyModifications;恢复变换;进行槽位审计 |
| 同一区域有两个 NavMesh Surface | 过时的 Surface 上,路径显示为“完整”,却穿过墙壁 | 每个区域只保留一个 Surface;重新烘焙重叠部分 |
| 烘焙时保留关闭的门扇 | 房间无法到达 | 在门扇上设置 NavMeshModifier.ignoreFromBuild |
| 放置杂物时未考虑 Agent 半径 | 门已打开,房间仍被分隔:可到达的地板区域仅占 25%(实测) | 保持门口区域畅通;拒绝会隔断地板的物品;对整层地板进行采样 |
| 将屋顶和上层楼板纳入烘焙 | 出现无法到达的孤岛 | 将屋顶区域设为 Not Walkable;使用楼梯或 NavMeshLink |
| 仅按胶囊体尺寸确定门的大小 | 每到门口,摄像机会突然拉近 | 在测试场中测量摇臂;使用室内摄像机 |
| 再次编辑 PolyShape | 拉伸部分消失 | 锁定轮廓;重放配方 |
为 LOD 树调整 treeDistance | 完全没有变化 | 调整 LOD Group,并捕获剔除情况 |
| 在实例化细节上设置 Healthy/Dry Color | 颜色没有变化 | 在着色器中改变颜色 |
| 仅启用 Bake Light Probes For Trees(默认开启) | 没有效果 | 树木渲染器从 Light Probes 获取 GI |
| 持续等待激活以进行预加载 | 卸载操作会卡住 | 立即加载,只在加载屏幕中设置门控 |
| 流式加载器中没有 Start 扫描 | 在编辑器中打开的区块会加载两次(观测到 1 份与 2 份副本) | 在 Start 中扫描已加载的场景 |
| 在编辑器中评估流式加载或内存 | 计数器为 0,优先级设置被忽略 | 在开发版 Player 中使用 stream_probe |
对标记调用 new ProfilerRecorder(handle) | 永远显示 0 ms | 添加 ProfilerRecorderOptions.StartImmediately(或使用 StartNew);将从未采样的标记视为无数据 |
使用 FrameTimingManager 获取各系统的 GPU 耗时 | 显示“地形 2 ms”,实际却是整帧耗时 | 切换系统并比较差异,或进行 GPU 捕获 |
| 透过雾效或俯视正交视角评估布局 | 鸟瞰画面发白;树木被 LOD 剔除 | 捕获关闭雾效的鸟瞰画面 |
交接
- 接收来自 scenario-3d、scenario-textures、scenario-skyboxes 和 scenario-blender-expert 的资源;来自 scenario-unity-gameplay 的角色控制器和摄像机装备,以及 来自 scenario-unity-animation 的角色控制器和摄像机装备(Cinemachine);来自 scenario-unity-architecture 的输入。
- 交付给 scenario-unity-rendering-lighting:带静态标志、UV2 的场景,以核心场景作为光照所有者,包含核心场景和所有区块的一个 APV Baking Set,在所有场景都打开时烘焙(包括遮挡烘焙)[此处未运行],雾效基线,每个图块的探针设置;给 scenario-unity-shaders:作为全屏通道规格的 Firewatch 渐变条雾效,细节着色器中的草地颜色变化;给 scenario-unity-performance:导览 CSV 和 JSON、
compare_runs、Player 探针、LOD 发现、区块道具中的 GPU Resident Drawer 候选项(Forward+、SRP Batcher、仅 Mesh Renderer、第 5 节中的差值);给 scenario-unity-mobile:audit(mobile=True)、流送优先级;给 scenario-unity-gameplay:NavMesh 表面、链接、训练场表格、生成点;给 scenario-unity-pipeline-automation:Addressable 场景、构建列表、作为AssetPostprocessor的导入规则。 - 数据包:项目、通道、场景、带数字的门槛、所有表格、未解决的问题。
Unity 6.3 说明
- Polybrush 已弃用,且从未能在 Terrain 上运行:通过射线投射散布。ProBuilder 6.1.2:没有窗口(Scene 视图工具上下文),
PivotLocation.FirstVertex(文档中的“First Corner”),默认材质是顶点颜色 Shader Graph。 - 内置 Terrain Tools 5.3.2;Splines 2.9.0;AI Navigation 2.0.14(NavMesh Surface、Modifier、Link、Build Height Mesh);Build Profiles 共用
EditorBuildSettings.scenes;Memory Profiler 1.1.12 和 Profile Analyzer 1.4.0 是程序包。 FindObjectsByType需要指定排序模式(在 6.4 中已弃用);在 6.6 中,新项目进入 Play 模式时不会重新加载域。
参考资料
references/procedures.md:24 项操作流程,包含完整调用、实时测试路径和记录的结果。references/expert-notes.md:专家原则与判断,附来源和时间戳。references/critique.md:地形、训练场、白盒关卡、套件、指引、氛围、流送和性能的评估标准。references/gui-paths.md:Terrain 工具栏、ProBuilder 工具上下文、Splines、NavMesh、多场景、性能分析窗口。references/sources.md:每个来源及其凭据、URL、最佳时间戳和修订历史。