diff --git a/tools/asset-catalog/README.md b/tools/asset-catalog/README.md
new file mode 100644
index 0000000..991782e
--- /dev/null
+++ b/tools/asset-catalog/README.md
@@ -0,0 +1,161 @@
+# Asset Catalog — UE5 资产扫描与语义增强工具
+
+扫描 UE5 项目中的 StaticMesh / Material / Blueprint 资产,提取几何与材质数据,再通过 GLM API 批量推断语义信息(朝向、功能、交互属性等),生成一份可直接用于关卡搭建的资产数据库。
+
+## Pipeline 流程
+
+```
+┌─────────────────────────────────────────────────────────────────────┐
+│ 阶段 1:UE5 扫描(需要 UE5 编辑器) │
+│ │
+│ run_all.bat │
+│ └─ 启动 UE5 无头模式,执行 run_all.py │
+│ ├─ discover → outputs/index.json (资产清单) │
+│ ├─ mesh → outputs/meshes/*.json (几何数据) │
+│ ├─ material → outputs/materials/*.json (材质参数) │
+│ └─ blueprint → outputs/blueprints/*.json (蓝图结构) │
+└──────────────────────────┬──────────────────────────────────────────┘
+ │
+┌──────────────────────────▼──────────────────────────────────────────┐
+│ 阶段 2:离线汇总(不需要 UE5) │
+│ │
+│ python build_database.py │
+│ └─ 合并 meshes/*.json → outputs/asset_database.json │
+└──────────────────────────┬──────────────────────────────────────────┘
+ │
+┌──────────────────────────▼──────────────────────────────────────────┐
+│ 阶段 3:AI 语义增强(离线,需要 GLM_API_KEY) │
+│ │
+│ python ai_inference.py │
+│ └─ 调用 GLM API,为每个资产推断: │
+│ facing_direction / surface_height_cm / function_description │
+│ placement_notes / interaction_hints / plausible_substitutes │
+│ └─ 就地更新 outputs/asset_database.json │
+└─────────────────────────────────────────────────────────────────────┘
+```
+
+## 前置条件
+
+| 依赖 | 说明 |
+|------|------|
+| **Unreal Engine 5.7** | 阶段 1 需要,阶段 2/3 纯离线 |
+| **Python 3.10+** | 脚本运行环境 |
+| **openai 包** | `pip install openai`(ai_inference.py 依赖) |
+| **GLM API Key** | 智谱开放平台 API Key,[获取地址](https://open.bigmodel.cn) |
+
+## 使用步骤
+
+### 1. 扫描资产
+
+```cmd
+cd tools\asset-catalog
+run_all.bat
+```
+
+启动 UE5 无头模式,自动执行 discover → mesh → material → blueprint 四步扫描。
+完成后编辑器自动关闭,结果写入 `outputs/` 目录。
+
+> **自定义扫描范围:**
+> ```cmd
+> set AC_SCAN_ROOT=/Game/MyFolder
+> set AC_STEPS=discover,mesh
+> run_all.bat
+> ```
+
+### 2. 汇总数据库
+
+```cmd
+python build_database.py
+```
+
+将所有 `outputs/meshes/*.json` 合并为单一的 `outputs/asset_database.json`。
+
+### 3. AI 语义增强
+
+```cmd
+set GLM_API_KEY=你的密钥
+python ai_inference.py
+```
+
+按类别分批调用 GLM API,为每个资产推断语义字段。支持断点续跑——中断后重新执行只会处理未完成的资产。
+
+先预览批次划分(不调用 API):
+
+```cmd
+python ai_inference.py --dry-run
+```
+
+## 环境变量
+
+### UE5 扫描阶段
+
+| 变量 | 默认值 | 说明 |
+|------|--------|------|
+| `AC_SCAN_ROOT` | `/Game/BlockingStarterPack` | 要扫描的 UE5 Content 路径 |
+| `AC_OUTPUT_DIR` | `<工具目录>/outputs` | JSON 输出目录 |
+| `AC_STEPS` | `discover,mesh,material,blueprint` | 要执行的步骤(逗号分隔) |
+| `AC_NO_QUIT` | `0` | 设为 `1` 扫描完成后不关闭编辑器 |
+| `UE5_ROOT` | 自动检测 | UE5 安装根目录(如 `C:\Program Files\Epic Games\UE_5.7`) |
+
+### AI 推理阶段
+
+| 变量 | 默认值 | 说明 |
+|------|--------|------|
+| `GLM_API_KEY` | — | **(必填)** 智谱 API Key |
+| `GLM_API_BASE` | `https://open.bigmodel.cn/api/coding/paas/v4` | API 地址 |
+| `GLM_MODEL` | `glm-5.1` | 使用的模型名称 |
+
+## 输出目录结构
+
+```
+outputs/
+├── index.json # 资产清单(644 个资产的分类索引)
+├── catalog_log.json # 扫描运行日志(耗时、状态)
+├── asset_database.json # ⭐ 最终产物:425 个 Mesh 的完整数据库
+├── meshes/ # 每个子文件夹一个 JSON
+│ ├── Architecture_Walls.json
+│ ├── Furniture.json
+│ └── ...
+├── materials/ # 每个子文件夹一个 JSON
+│ ├── MI_Architecture.json
+│ └── ...
+└── blueprints/ # 每个子文件夹一个 JSON
+ ├── BP_Doors.json
+ └── ...
+```
+
+## CLI 参数
+
+### build_database.py
+
+```
+python build_database.py [--input DIR] [--output FILE]
+
+ --input 扫描输出目录,默认 tools/asset-catalog/outputs
+ --output 输出文件路径,默认 /asset_database.json
+```
+
+### ai_inference.py
+
+```
+python ai_inference.py [--input FILE] [--output FILE] [--batch-size N] [--dry-run]
+
+ --input 输入 asset_database.json 路径,默认 outputs/asset_database.json
+ --output 输出路径,默认就地更新
+ --batch-size 每批资产数量,默认 5
+ --dry-run 只打印批次信息,不调用 API
+```
+
+## 文件清单
+
+| 文件 | 用途 |
+|------|------|
+| `run_all.bat` | 入口:启动 UE5 无头模式 |
+| `run_all.py` | UE5 内编排器:依次调用各分析脚本 |
+| `_common.py` | 共享模块:环境变量、JSON I/O、工具函数 |
+| `discover_assets.py` | 步骤 discover:资产发现与分类 |
+| `analyze_meshes.py` | 步骤 mesh:StaticMesh 几何分析 |
+| `analyze_materials.py` | 步骤 material:材质参数提取 |
+| `analyze_blueprints.py` | 步骤 blueprint:蓝图结构分析 |
+| `build_database.py` | 离线汇总:合并为 asset_database.json |
+| `ai_inference.py` | 离线推理:GLM API 语义增强 |
diff --git a/tools/asset-catalog/_common.py b/tools/asset-catalog/_common.py
index 33de6ce..3e49540 100644
--- a/tools/asset-catalog/_common.py
+++ b/tools/asset-catalog/_common.py
@@ -5,7 +5,7 @@
环境变量:
AC_SCAN_ROOT — 要扫描的 UE5 Content 路径(默认 /Game/BlockingStarterPack)
- AC_OUTPUT_DIR — JSON 输出目录(绝对路径,默认 /output/asset-catalog/)
+ AC_OUTPUT_DIR — JSON 输出目录(绝对路径,默认 /outputs/)
AC_NO_QUIT — 设为 "1" 运行后不退出编辑器
AC_STEPS — 逗号分隔的步骤列表(默认 discover,mesh,material,blueprint)
"""
@@ -42,16 +42,8 @@ def get_output_dir() -> Path:
if raw:
p = Path(raw)
else:
- # 默认放在项目 output/asset-catalog/ 下
- # 尝试通过 unreal API 获取项目目录
- if HAS_UNREAL:
- try:
- project_dir = Path(unreal.Paths.project_dir()).parent
- p = project_dir / "output" / "asset-catalog"
- except Exception:
- p = Path("output") / "asset-catalog"
- else:
- p = Path("output") / "asset-catalog"
+ # 默认放在工具所在目录的 outputs/ 下
+ p = _SCRIPT_DIR / "outputs"
p.mkdir(parents=True, exist_ok=True)
return p
diff --git a/tools/asset-catalog/ai_inference.py b/tools/asset-catalog/ai_inference.py
index 72da73c..0db104c 100644
--- a/tools/asset-catalog/ai_inference.py
+++ b/tools/asset-catalog/ai_inference.py
@@ -30,9 +30,9 @@ from _common import read_json, write_json, iso_now
TAG = "[AIInference]"
# ---- 配置 ----
-DEFAULT_API_BASE = "https://open.bigmodel.cn/api/paas/v4"
-DEFAULT_MODEL = "glm-4-flash"
-DEFAULT_BATCH_SIZE = 20
+DEFAULT_API_BASE = "https://open.bigmodel.cn/api/coding/paas/v4"
+DEFAULT_MODEL = "glm-5.1"
+DEFAULT_BATCH_SIZE = 5
# ---- Prompt 模板 ----
SYSTEM_PROMPT = """你是一个 UE5 游戏开发助手,专注于为 3D 模型资产提取语义信息。
@@ -72,9 +72,9 @@ BATCH_PROMPT_TEMPLATE = """以下是 {category} 类别的 {count} 个 StaticMesh
{assets_json}
-请为每个资产推断语义信息,返回 JSON 数组。每个元素包含:
-facing_direction, surface_height_cm, function_description,
-placement_notes, interaction_hints, plausible_substitutes"""
+请为每个资产推断语义信息,必须返回如下格式的 JSON 对象:
+{{"results": [{{"facing_direction": ..., "surface_height_cm": ..., "function_description": ..., "placement_notes": ..., "interaction_hints": [...], "plausible_substitutes": ...}}, ...]}}
+重要:results 数组必须恰好包含 {count} 个元素,与输入资产一一对应。"""
def _get_api_config():
@@ -175,6 +175,7 @@ def _call_glm_api(config: dict, category: str, assets_json: str) -> list:
{"role": "user", "content": user_prompt},
],
temperature=0.1,
+ max_tokens=4096,
response_format={"type": "json_object"},
)
except Exception as e:
@@ -321,6 +322,8 @@ def run_inference(
if batch_idx < len(batches) - 1:
time.sleep(1)
+ if "ai_inference_metadata" not in db["metadata"]:
+ db["metadata"]["ai_inference_metadata"] = {}
db["metadata"]["ai_inference_metadata"]["completed_at"] = iso_now()
write_json(db, output_file)
@@ -337,7 +340,7 @@ def main():
parser = argparse.ArgumentParser(description="GLM API 批量推理 — 资产语义增强")
parser.add_argument(
"--input", type=str,
- default=str(_SCRIPT_DIR.parent.parent / "output" / "asset-catalog" / "asset_database.json"),
+ default=str(_SCRIPT_DIR / "outputs" / "asset_database.json"),
help="输入 asset_database.json 路径",
)
parser.add_argument(
diff --git a/tools/asset-catalog/build_database.py b/tools/asset-catalog/build_database.py
index 919f13b..43ee471 100644
--- a/tools/asset-catalog/build_database.py
+++ b/tools/asset-catalog/build_database.py
@@ -8,7 +8,7 @@ asset_database.json,以资产名为 key 扁平化存储。
用法:
python build_database.py [--input DIR] [--output FILE]
- --input 扫描输出目录,默认 output/asset-catalog
+ --input 扫描输出目录,默认 tools/asset-catalog/outputs
--output 输出文件路径,默认 /asset_database.json
"""
@@ -126,8 +126,8 @@ def main():
parser = argparse.ArgumentParser(description="汇总资产扫描数据为统一 JSON 数据库")
parser.add_argument(
"--input", type=str,
- default=str(_SCRIPT_DIR.parent.parent / "output" / "asset-catalog"),
- help="扫描输出目录 (默认: output/asset-catalog)",
+ default=str(_SCRIPT_DIR / "outputs"),
+ help="扫描输出目录 (默认: tools/asset-catalog/outputs)",
)
parser.add_argument(
"--output", type=str, default=None,
diff --git a/tools/asset-catalog/run_all.bat b/tools/asset-catalog/run_all.bat
index dbb705c..2f336bc 100644
--- a/tools/asset-catalog/run_all.bat
+++ b/tools/asset-catalog/run_all.bat
@@ -31,7 +31,7 @@ if "%UE_EDITOR%"=="" (
)
if not defined AC_SCAN_ROOT set "AC_SCAN_ROOT=/Game/BlockingStarterPack"
-if not defined AC_OUTPUT_DIR set "AC_OUTPUT_DIR=%PROJECT_ROOT%\output\asset-catalog"
+if not defined AC_OUTPUT_DIR set "AC_OUTPUT_DIR=%SCRIPT_DIR%outputs"
if not defined AC_STEPS set "AC_STEPS=discover,mesh,material,blueprint"
if not defined AC_NO_QUIT set "AC_NO_QUIT=0"