docs(tech): Level Builder技能逻辑梳理报告——架构/流程/问题分析
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,448 @@
|
|||||||
|
# Level Builder 技能逻辑梳理报告
|
||||||
|
|
||||||
|
> 生成时间: 2026-06-09
|
||||||
|
> 梳理范围: `tools/level-builder/` 全部源码 + `.claude/skills/level-builder/SKILL.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、整体架构
|
||||||
|
|
||||||
|
```
|
||||||
|
搭建指南.md ──parse──▶ JSON 中间数据 ──validate──▶ 验证报告
|
||||||
|
│
|
||||||
|
build (UE5内)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
.umap 关卡文件 + build_log.json
|
||||||
|
│
|
||||||
|
report
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
搭建报告.md
|
||||||
|
```
|
||||||
|
|
||||||
|
四个阶段,顺序执行,前三步均可独立离线运行(无需 UE5),仅 `build` 需要 `unreal` 模块。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、文件清单与职责
|
||||||
|
|
||||||
|
```
|
||||||
|
tools/level-builder/
|
||||||
|
├── main.py # CLI 入口,子命令分派 (parse/validate/build/report)
|
||||||
|
├── build_level.bat # Windows 批处理,自动检测 UE5 并以命令行模式启动构建
|
||||||
|
├── build_cmdline.py # 命令行构建 Python 入口(由 bat 通过 -ExecutePythonScript 调用)
|
||||||
|
├── build_in_editor.py # 编辑器内手动执行的入口脚本(Output Log Python 控制台)
|
||||||
|
├── check_pivots.py / .bat # 锚点检查工具
|
||||||
|
├── parsers/
|
||||||
|
│ ├── markdown_table.py # 通用 Markdown 管道表格解析 + 坐标/旋转/缩放解析工具函数
|
||||||
|
│ └── build_guide_parser.py # 核心解析器——按 Phase 切割搭建指南,生成 ActorData 列表
|
||||||
|
├── config/
|
||||||
|
│ ├── asset_mapping.py # 38 种 BSP 资产 → UE5 路径 + 锚点偏移 + get_pivot_compensation()
|
||||||
|
│ ├── material_mapping.py # 13 种标识色材质 → UE5 路径
|
||||||
|
│ ├── zone_config.py # 7 区域定义 + Outliner 文件夹结构 + get_folder_path()
|
||||||
|
│ └── substitution_rules.py # 语义化物件名 → Primitives 替代方案(预留给未来,当前未被导入)
|
||||||
|
├── builder/
|
||||||
|
│ └── scene_builder.py # 核心构建器——UE5 Python 环境中 spawn Actor、设 Transform/材质/Outliner
|
||||||
|
├── validation/
|
||||||
|
│ └── asset_validator.py # 离线验证:资产 key / 材质 / .uasset 文件存在性
|
||||||
|
├── report/
|
||||||
|
│ └── report_generator.py # JSON + build_log → Markdown 搭建报告
|
||||||
|
└── output/ # 生成物目录 (JSON、build_log、报告)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 模块调用关系
|
||||||
|
|
||||||
|
| 模块 | 被谁调用 | 依赖模块 |
|
||||||
|
|------|---------|---------|
|
||||||
|
| `main.py` | 用户 / Claude 命令行 | `build_guide_parser`, `asset_validator`, `scene_builder`, `report_generator` |
|
||||||
|
| `build_level.bat` | 用户双击或命令行 | `build_cmdline.py`(通过 UE5 `-ExecutePythonScript`) |
|
||||||
|
| `build_cmdline.py` | `build_level.bat` | `scene_builder` (`build_level` + `setup_post_build`) |
|
||||||
|
| `build_in_editor.py` | 用户在 UE5 Python 控制台执行 | `scene_builder` (`build_level`) |
|
||||||
|
| `build_guide_parser.py` | `main.py cmd_parse()` | `markdown_table`, `zone_config` |
|
||||||
|
| `scene_builder.py` | `build_cmdline.py`, `build_in_editor.py`, `main.py cmd_build()` | `asset_mapping`, `material_mapping` |
|
||||||
|
| `asset_validator.py` | `main.py cmd_validate()` | `asset_mapping`, `material_mapping` |
|
||||||
|
| `report_generator.py` | `main.py cmd_report()` | `asset_mapping`(仅缩放记录部分) |
|
||||||
|
| `substitution_rules.py` | **无(死代码)** | — |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、核心流程详解
|
||||||
|
|
||||||
|
### 3.1 解析流程(`BuildGuideParser`)
|
||||||
|
|
||||||
|
解析器按 Phase 切割搭建指南文本,核心是**状态机**模式——维护 `current_zone` / `current_category` 状态,遇到标题行切换状态,遇到表格行按当前状态生成 Actor。
|
||||||
|
|
||||||
|
#### Phase 划分与解析顺序
|
||||||
|
|
||||||
|
```
|
||||||
|
_parse_global_info() → metadata(当前为硬编码,未从文档提取)
|
||||||
|
↓
|
||||||
|
_parse_phase_ground() → 地面铺设表格(#### Z1 家 地面 / #### 全局地面)
|
||||||
|
↓
|
||||||
|
_parse_phase_boundaries() → 边界围挡表格(支持 ~ 范围展开,如 01~15)
|
||||||
|
↓
|
||||||
|
_parse_phase_zones() → 逐区域搭建(### C1. Z1 — 家 → #### C1.1 结构体)
|
||||||
|
↓
|
||||||
|
_parse_phase_global_objects() → 全局物件(路灯、垃圾桶等)
|
||||||
|
↓
|
||||||
|
_parse_phase_lighting() → 光照配置(DirectionalLight / SkyLight / PointLight)
|
||||||
|
↓
|
||||||
|
_add_player_start() → 硬编码 PlayerStart 位置
|
||||||
|
↓
|
||||||
|
_deduplicate_actors() → 同名 + 同位置 + 同资产 → 去重
|
||||||
|
↓
|
||||||
|
_build_summary() → 构建统计摘要
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 关键设计点
|
||||||
|
|
||||||
|
**1. 范围展开(`_expand_range_row`)**
|
||||||
|
|
||||||
|
输入格式:`LVL_BND_East_01~15` + `(8000, 200+400n, 0) n=0~14`
|
||||||
|
|
||||||
|
解析流程:
|
||||||
|
- 正则 `(.+?)_(\d+)~(\d+)` 提取前缀、起始编号、结束编号
|
||||||
|
- 正则 `n\s*=\s*(\d+)~(\d+)` 提取 n 的范围
|
||||||
|
- 去掉 `n=xx~yy` 后缀后解析三个坐标表达式
|
||||||
|
- 对每个 n 值调用 `_eval_coord_expr()` 计算坐标
|
||||||
|
- 生成 N 个 ActorData,编号自动补零(`{prefix}_{num:02d}`)
|
||||||
|
|
||||||
|
**2. 坐标表达式计算(`_eval_coord_expr`)**
|
||||||
|
|
||||||
|
支持格式:
|
||||||
|
- 纯数字:`8000`
|
||||||
|
- 含 n 的简单算术:`200+400n` → 替换为 `200+400*{n}` → `eval()`
|
||||||
|
|
||||||
|
**3. 表格类型推断(`_parse_zone_row`)**
|
||||||
|
|
||||||
|
通过列名判断:
|
||||||
|
- 有 `"触发半径"` 列 → 交互物表(`_parse_interactable_row`)
|
||||||
|
- 有 `"稀有度"` 列 → 收集品表(`_parse_collectible_row`)
|
||||||
|
- 否则 → 结构体/布景表(`_parse_structure_or_prop_row`)
|
||||||
|
|
||||||
|
**4. 占位规则**
|
||||||
|
|
||||||
|
| 类型 | 占位资产 | 缩放 | 默认材质 | 说明 |
|
||||||
|
|------|---------|------|---------|------|
|
||||||
|
| 交互物 | Cube | (0.3, 0.3, 0.3) | MI_DevYellow | 交互物占位标记 |
|
||||||
|
| 收集品 | CirclePlatform | (0.03, 0.03, 0.03) | MI_DevWhite / MI_DevYellow | 普通=白,稀有用金色 |
|
||||||
|
|
||||||
|
**5. 去重逻辑**
|
||||||
|
|
||||||
|
- 同名 + 同位置 + 同资产 → 视为完全重复,移除
|
||||||
|
- 同名但位置或资产不同 → 合法保留(如 Z3 墙段)
|
||||||
|
|
||||||
|
### 3.2 构建流程(`scene_builder.build_level`)
|
||||||
|
|
||||||
|
#### 主循环
|
||||||
|
|
||||||
|
```python
|
||||||
|
for actor_def in actors:
|
||||||
|
match asset_type:
|
||||||
|
"player_start" → _spawn_player_start()
|
||||||
|
"directional_light" → _spawn_directional_light()
|
||||||
|
"sky_light" → _spawn_sky_light()
|
||||||
|
"point_light" → _spawn_point_light()
|
||||||
|
"exp_height_fog" → _spawn_exp_height_fog()
|
||||||
|
_ (default) → _spawn_mesh_actor()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `_spawn_mesh_actor` 详细流程
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 查 MESH_ASSETS 获取 UE5 资产路径
|
||||||
|
└─ 找不到 → 回退到 Cube + "[MISSING]" 前缀 + MI_DevPink
|
||||||
|
|
||||||
|
2. unreal.load_asset(mesh_path)
|
||||||
|
└─ 加载失败 → 同上 Cube 回退
|
||||||
|
|
||||||
|
3. 锚点补偿计算
|
||||||
|
offset = pivot_offset_xy × scale
|
||||||
|
rotated_offset = rotate(offset, yaw)
|
||||||
|
spawn_pos = guide_pos - rotated_offset
|
||||||
|
|
||||||
|
4. editor_subsystem.spawn_actor_from_object(static_mesh, spawn_pos)
|
||||||
|
|
||||||
|
5. 设置 Rotation(关键字参数:pitch=/yaw=/roll=,避免 UE5.7 位置参数歧义)
|
||||||
|
|
||||||
|
6. 设置 Scale
|
||||||
|
|
||||||
|
7. 设置材质(查 MATERIAL_PATHS → load_asset → set_material(0, material))
|
||||||
|
|
||||||
|
8. 设置 Actor Label 和 Outliner Folder
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 后处理(`setup_post_build` + `build_cmdline.py` 额外逻辑)
|
||||||
|
|
||||||
|
| 步骤 | 位置 | 功能 |
|
||||||
|
|------|------|------|
|
||||||
|
| 添加 ExponentialHeightFog | `build_cmdline.py` | 雾密度 0.015,自动检测是否已存在 |
|
||||||
|
| 设置 GameMode | `scene_builder.setup_post_build()` | BP_ThirdPersonGameMode(通过 SoftClassPath) |
|
||||||
|
| 启用大气效果 | `scene_builder.setup_post_build()` | DirectionalLight 的 `atmosphere_sun_light = True` |
|
||||||
|
| 保存关卡 | `build_cmdline.py` | `EditorLevelLibrary.save_current_level()` |
|
||||||
|
| 退出编辑器 | `build_cmdline.py` | `SystemLibrary.execute_console_command(None, "quit")` |
|
||||||
|
|
||||||
|
### 3.3 锚点补偿系统
|
||||||
|
|
||||||
|
`asset_mapping.py` 中每个资产记录了实测数据:
|
||||||
|
|
||||||
|
```python
|
||||||
|
"Wall_400x300": {
|
||||||
|
"path": "...",
|
||||||
|
"default_size": (400, 20, 300),
|
||||||
|
"actual_bounds": ((0, -10, 0), (400, 10, 300)), # min, max(实测)
|
||||||
|
"pivot_offset_xy": (200, 0), # 锚点偏离视觉中心的 XY 偏移
|
||||||
|
"category": "wall",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 锚点类型分类
|
||||||
|
|
||||||
|
| 类型 | 典型资产 | 锚点位置 | offset_xy |
|
||||||
|
|------|---------|---------|-----------|
|
||||||
|
| 角落锚点(墙体) | Wall_400x300, Wall_200x300 | 底边一端 | (半宽, 0) |
|
||||||
|
| 角落锚点(地板) | Floor_1000x1000, Floor_300x400 | 角落 | (半宽, 半深) |
|
||||||
|
| 角落锚点(Cube) | Cube | 角落 (0,0,0) | (50, 50) |
|
||||||
|
| 底面中心 | Cylinder, 家具类, 工业类 | 底面中心 | (0, 0) |
|
||||||
|
| 偏心锚点 | BedSingle, RoadLamp_01 | 接近角落/边缘 | 需逐个实测 |
|
||||||
|
|
||||||
|
#### 补偿公式
|
||||||
|
|
||||||
|
```
|
||||||
|
offset_scaled = pivot_offset_xy × [sx, sy]
|
||||||
|
offset_rotated = rotate_z(offset_scaled, yaw) // 绕 Z 轴旋转
|
||||||
|
spawn_pos = guide_pos - offset_rotated
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 验证流程(`asset_validator`)
|
||||||
|
|
||||||
|
三级检查:
|
||||||
|
|
||||||
|
1. **资产 key 检查**:`asset_key` 是否在 `MESH_ASSETS` 字典中注册
|
||||||
|
2. **材质检查**:`material` 是否在 `MATERIAL_PATHS` 字典中注册(warning 级别)
|
||||||
|
3. **文件存在性检查**:如果提供了 `project_root`,检查 `.uasset` 文件是否实际存在(warning 级别)
|
||||||
|
|
||||||
|
跳过规则:`asset_type != "static_mesh"` 的 Actor(光照、PlayerStart 等)直接标记为有效。
|
||||||
|
|
||||||
|
### 3.5 报告生成(`report_generator`)
|
||||||
|
|
||||||
|
输出结构:
|
||||||
|
|
||||||
|
```
|
||||||
|
# 白模搭建报告 — 自动生成
|
||||||
|
|
||||||
|
## 一、搭建概要
|
||||||
|
- 总 Actor 数、按类别统计、构建成功/失败数
|
||||||
|
|
||||||
|
## 二、逐区域对照
|
||||||
|
- 按 Z1~Z7 + GLOBAL 顺序
|
||||||
|
- 每区域一张表格:# / Actor名称 / 资产 / 位置 / 缩放 / 材质 / 状态(✅/❌)
|
||||||
|
|
||||||
|
## 三、资产使用统计
|
||||||
|
- 按使用次数降序排列的资产使用表
|
||||||
|
|
||||||
|
## 四、缩放记录
|
||||||
|
- 仅记录缩放 != (1,1,1) 的 Actor
|
||||||
|
- 包含实际尺寸计算(default_size × scale)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、构建入口对比
|
||||||
|
|
||||||
|
| 特性 | `build_level.bat` → `build_cmdline.py` | `build_in_editor.py` |
|
||||||
|
|------|---------------------------------------|---------------------|
|
||||||
|
| 运行方式 | 命令行一键启动 UE5 | 用户手动打开 UE5 编辑器 |
|
||||||
|
| 项目路径 | 通过环境变量 `LB_PROJECT_ROOT` 传入 | **硬编码** `E:/MiceCola/work/ChildHood` |
|
||||||
|
| JSON 路径 | 通过环境变量 `LB_JSON_PATH` 传入 | 硬编码 `output/level_v01.json` |
|
||||||
|
| 关卡创建 | `ensure_map()` 自动创建/加载 | 需用户手动打开目标关卡 |
|
||||||
|
| 后处理 | ✅ 含 ExponentialHeightFog + GameMode + 大气 | ❌ 无后处理 |
|
||||||
|
| 保存 | ✅ 自动保存 | ❌ 需用户手动保存 |
|
||||||
|
| 区域过滤 | 支持(通过 `--zones`) | 代码中写死 `zones=None` |
|
||||||
|
| 推荐度 | ⭐ 推荐 | 仅调试用 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、数据流总结
|
||||||
|
|
||||||
|
```
|
||||||
|
搭建指南.md
|
||||||
|
│
|
||||||
|
├─ 第〇章 全局参数 ──→ metadata(当前硬编码,未动态解析)
|
||||||
|
├─ 第一章 资产映射表 ──→(未解析,仅验证用)
|
||||||
|
├─ 第二章 地面铺设 ──→ _parse_phase_ground() ──→ STR Actors(地板)
|
||||||
|
├─ 第二章 边界围挡 ──→ _parse_phase_boundaries() ──→ BND Actors(含范围展开)
|
||||||
|
├─ 第三章 逐区域 ──→ _parse_phase_zones() ──→ STR / PROP / INTR / COLL Actors
|
||||||
|
├─ 第三章 全局物件 ──→ _parse_phase_global_objects() ──→ PROP / LGT Actors
|
||||||
|
├─ 第四章 光照 ──→ _parse_phase_lighting() ──→ LGT Actors(DL / SkyLight / PointLight)
|
||||||
|
└─ 硬编码 ──→ _add_player_start() ──→ PLAY Actor
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
JSON: { metadata, actors: [...], summary }
|
||||||
|
│
|
||||||
|
├─ validate ──→ 检查 asset_key / material / .uasset 存在性
|
||||||
|
│
|
||||||
|
├─ build ──→ UE5 spawn + 锚点补偿 + 后处理 ──→ .umap + build_log.json
|
||||||
|
│
|
||||||
|
└─ report ──→ Markdown 搭建报告(逐区域对照表 + 资产统计 + 缩放记录)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、发现的问题和改进建议
|
||||||
|
|
||||||
|
### ⚠️ 问题 1:`_eval_coord_expr` 使用 `eval()` 存在注入风险
|
||||||
|
|
||||||
|
**位置**: `parsers/build_guide_parser.py:411`
|
||||||
|
|
||||||
|
```python
|
||||||
|
result = eval(expr) # 受限输入,仅数字和基本运算
|
||||||
|
```
|
||||||
|
|
||||||
|
**风险**: `expr` 来自 Markdown 文本内容,理论上任何字符串都可能被注入执行。
|
||||||
|
|
||||||
|
**建议**: 改用简单的算术表达式解析器,只支持 `+`、`-`、`*`、`/`、数字和变量 `n`。例如用 `ast.literal_eval` 的思路做白名单解析,或用正则拆分后逐项计算。
|
||||||
|
|
||||||
|
**严重程度**: 低(当前为单人开发、固定格式文档,实际风险极小,但作为工程规范应修复)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ⚠️ 问题 2:`_parse_global_info` 硬编码 metadata
|
||||||
|
|
||||||
|
**位置**: `parsers/build_guide_parser.py:156-163`
|
||||||
|
|
||||||
|
```python
|
||||||
|
self.metadata = {
|
||||||
|
"source": "关卡-v01-搭建指南.md", # 硬编码!
|
||||||
|
"scene_size": [8000, 6000],
|
||||||
|
"ground_z": 0,
|
||||||
|
"character_height": 120,
|
||||||
|
"camera_height": 100,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**影响**: 切换到 v02 搭建指南时,metadata 中的 source 仍然是 v01,场景尺寸等参数也不会自动更新。
|
||||||
|
|
||||||
|
**建议**: 从搭建指南第〇章的表格中动态解析 metadata,与解析其他 Phase 表格使用相同的基础设施(`markdown_table.parse_table`)。
|
||||||
|
|
||||||
|
**严重程度**: 中(多版本场景下会导致报告信息不准确)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ⚠️ 问题 3:`build_in_editor.py` 硬编码绝对路径
|
||||||
|
|
||||||
|
**位置**: `build_in_editor.py:18`
|
||||||
|
|
||||||
|
```python
|
||||||
|
PROJECT_ROOT = Path(r"E:/MiceCola/work/ChildHood")
|
||||||
|
```
|
||||||
|
|
||||||
|
**影响**: 不同机器或目录结构下会失效。
|
||||||
|
|
||||||
|
**建议**: 参照 `build_cmdline.py` 的做法,优先使用环境变量,fallback 到 `unreal.Paths.project_dir()` 自动检测。
|
||||||
|
|
||||||
|
**严重程度**: 低(推荐入口是 `build_level.bat`,`build_in_editor.py` 仅用于调试)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ⚠️ 问题 4:`substitution_rules.py` 是死代码
|
||||||
|
|
||||||
|
**现状**: 该模块未被任何其他模块导入使用。设计意图是为未来"执行案解析器"预留——当直接从执行案而非搭建指南生成关卡时,将语义化物件名(如"冰箱")映射到 Primitives 替代方案。
|
||||||
|
|
||||||
|
**建议**: 当前无需处理,但建议在模块顶部 docstring 中明确标注"预留接口,当前未被使用"。
|
||||||
|
|
||||||
|
**严重程度**: 无(仅代码整洁性问题)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 💡 问题 5:SKILL.md 区域一览表与 `zone_config.py` 不一致
|
||||||
|
|
||||||
|
**SKILL.md 中的表格**:
|
||||||
|
|
||||||
|
| Zone | origin | bounds |
|
||||||
|
|------|--------|--------|
|
||||||
|
| Z5 巷子 | (2000, 0, 0) | 600×800 |
|
||||||
|
| Z6 水塘边 | (5500, 0, 0) | 1500×1000 |
|
||||||
|
| Z7 老居民楼 | (5000, 1300, 0) | 1500×1200 |
|
||||||
|
|
||||||
|
**`zone_config.py` 中的实际值**:
|
||||||
|
|
||||||
|
| Zone | origin | bounds |
|
||||||
|
|------|--------|--------|
|
||||||
|
| Z5 巷子 | (2300, 1300, 0) | 300×2000 |
|
||||||
|
| Z6 水塘边 | (1600, 3300, 0) | 1500×1400 |
|
||||||
|
| Z7 老居民楼 | (5800, 200, 0) | 1200×1800 |
|
||||||
|
|
||||||
|
**判断**: `zone_config.py` 是经过 v01 bugfix 修正后的实际在用值,SKILL.md 表格是旧版本。以代码为准。
|
||||||
|
|
||||||
|
**建议**: 更新 SKILL.md 中的区域一览表,使其与 `zone_config.py` 一致。
|
||||||
|
|
||||||
|
**严重程度**: 低(不影响功能,仅文档准确性)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 💡 问题 6:`_find_section_start` 简单字符串匹配可能误命中
|
||||||
|
|
||||||
|
**位置**: `parsers/build_guide_parser.py:787-791`
|
||||||
|
|
||||||
|
```python
|
||||||
|
def _find_section_start(self, lines, keyword):
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if keyword in line:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
```
|
||||||
|
|
||||||
|
**风险**: 如果关键词出现在非标题行(如表格内容、注释中),会误匹配。
|
||||||
|
|
||||||
|
**现状**: 搭建指南格式固定,当前不会出问题。
|
||||||
|
|
||||||
|
**建议**: 如需提高鲁棒性,可增加标题行检测(如检查行首是否有 `##` 前缀)。
|
||||||
|
|
||||||
|
**严重程度**: 低
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 💡 问题 7:LEVEL_NAME 硬编码为 `LVL_SuburbanV01`
|
||||||
|
|
||||||
|
**位置**: `config/zone_config.py:72`
|
||||||
|
|
||||||
|
```python
|
||||||
|
LEVEL_NAME = "LVL_SuburbanV01"
|
||||||
|
```
|
||||||
|
|
||||||
|
**影响**: Outliner 文件夹路径和 Global 子文件夹路径都依赖这个常量。v02 版本时需要手动修改。
|
||||||
|
|
||||||
|
**建议**: 将 LEVEL_NAME 提升为 CLI 参数或从 JSON metadata 中读取。
|
||||||
|
|
||||||
|
**严重程度**: 低(当前手动改一行即可)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、总结
|
||||||
|
|
||||||
|
### 架构评价
|
||||||
|
|
||||||
|
- **模块划分清晰**:解析 / 配置 / 构建 / 验证 / 报告各司其职,耦合度低
|
||||||
|
- **数据驱动设计好**:资产映射、材质映射、区域配置全部 externalize,新增资产/区域只需改 config
|
||||||
|
- **锚点补偿系统完善**:38 种资产逐一实测,含旋转补偿,解决了 BSP 资产锚点不一致的核心问题
|
||||||
|
- **双入口设计合理**:命令行自动构建(推荐)+ 编辑器内手动执行(调试)
|
||||||
|
|
||||||
|
### 代码质量
|
||||||
|
|
||||||
|
- 整体代码质量良好,注释充分
|
||||||
|
- 错误处理较完善(资产加载失败有回退,编辑器未就绪有超时等待)
|
||||||
|
- 命名规范统一(Actor 命名、文件夹结构、日志前缀)
|
||||||
|
|
||||||
|
### 风险点
|
||||||
|
|
||||||
|
| 风险 | 严重度 | 修复优先级 |
|
||||||
|
|------|--------|-----------|
|
||||||
|
| `eval()` 注入 | 低 | P3(单人开发场景风险极小) |
|
||||||
|
| metadata 硬编码 | 中 | P2(多版本场景下需修复) |
|
||||||
|
| `build_in_editor.py` 硬编码路径 | 低 | P3(推荐用 bat 入口) |
|
||||||
|
| SKILL.md 区域表过时 | 低 | P3(文档同步) |
|
||||||
|
| LEVEL_NAME 硬编码 | 低 | P3(手动改一行即可) |
|
||||||
|
| `substitution_rules.py` 死代码 | 无 | P4(代码整洁) |
|
||||||
|
| `_find_section_start` 误匹配风险 | 低 | P4(当前格式固定无问题) |
|
||||||
Reference in New Issue
Block a user