feat(tools): 命令行白模构建——build_level.bat 一键生成UE5关卡
This commit is contained in:
@@ -87,35 +87,53 @@ python main.py validate -i output/level_v01.json
|
|||||||
|
|
||||||
**生成文件**: `output/validation_result.json`
|
**生成文件**: `output/validation_result.json`
|
||||||
|
|
||||||
### 第三步:UE5 编辑器内构建(需要 UE5 编辑器运行)
|
### 第三步:UE5 构建
|
||||||
|
|
||||||
在 UE5 编辑器 Python 控制台中执行:
|
有两种方式,**推荐使用命令行方式**(全自动,无需手动操作编辑器):
|
||||||
|
|
||||||
|
#### 方式 A:命令行一键构建(推荐)
|
||||||
|
|
||||||
|
```bat
|
||||||
|
REM 从项目根目录运行
|
||||||
|
tools\level-builder\build_level.bat
|
||||||
```
|
```
|
||||||
方式 A — Output Log Python 控制台:
|
|
||||||
exec(open(r"tools/level-builder/main.py").read())
|
|
||||||
main(["build", "-i", "output/level_v01.json"])
|
|
||||||
|
|
||||||
方式 B — 仅构建指定区域:
|
**高级用法**:
|
||||||
main(["build", "-i", "output/level_v01.json", "--zones", "Z1,Z3"])
|
```bat
|
||||||
|
build_level.bat --json output/v02.json --map LVL_SuburbanV02 # 指定 JSON 和关卡名
|
||||||
方式 C — 增量构建(不清除已有 Actor):
|
build_level.bat --no-quit # 构建后保留编辑器
|
||||||
main(["build", "-i", "output/level_v01.json", "--no-clear"])
|
build_level.bat --no-null-rhi # 显示编辑器窗口(调试)
|
||||||
|
build_level.bat --dry-run # 只打印命令不执行
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**环境变量**:
|
||||||
|
- `UE5_ROOT` — UE5 安装目录(未设置时自动检测 5.7/5.6 常见路径)
|
||||||
|
|
||||||
**预期输出**:
|
**预期输出**:
|
||||||
```
|
```
|
||||||
[LevelBuilder] 加载 265 个 Actor 定义
|
[LevelBuilder] 加载 265 个 Actor 定义
|
||||||
[LevelBuilder] 清除 0 个已有 LVL_* Actor...
|
[LevelBuilder] SUCCESS: 265 | FAILED: 0 | TOTAL: 265
|
||||||
进度: 20/265 (20 成功, 0 失败)
|
[LevelBuilder] ✅ 关卡已保存: /Game/Maps/LVL_SuburbanV01
|
||||||
...
|
|
||||||
[LevelBuilder] 构建完成!
|
|
||||||
成功: 265
|
|
||||||
失败: 0
|
|
||||||
日志: output/build_log.json
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**生成文件**: `output/build_log.json`
|
**生成文件**:
|
||||||
|
- `Content/Maps/LVL_SuburbanV01.umap` — UE5 关卡文件
|
||||||
|
- `tools/level-builder/output/build_log.json` — 构建日志
|
||||||
|
|
||||||
|
#### 方式 B:编辑器内手动执行
|
||||||
|
|
||||||
|
在 UE5 编辑器 Python 控制台中:
|
||||||
|
|
||||||
|
```
|
||||||
|
方式 B1 — Output Log Python 控制台:
|
||||||
|
exec(open(r"tools/level-builder/build_in_editor.py").read())
|
||||||
|
|
||||||
|
方式 B2 — File > Execute Python Script > 选择 build_in_editor.py
|
||||||
|
|
||||||
|
方式 B3 — CLI 方式(仅构建指定区域):
|
||||||
|
exec(open(r"tools/level-builder/main.py").read())
|
||||||
|
main(["build", "-i", "output/level_v01.json", "--zones", "Z1,Z3"])
|
||||||
|
```
|
||||||
|
|
||||||
### 第四步:生成搭建报告(离线,Claude 可执行)
|
### 第四步:生成搭建报告(离线,Claude 可执行)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
"""UE5 命令行白模关卡构建脚本。
|
||||||
|
|
||||||
|
由 build_level.bat 通过 UE5 的 -ExecutePythonScript 参数调用。
|
||||||
|
在 UE5 编辑器 Python 环境中运行,无需手动打开编辑器。
|
||||||
|
|
||||||
|
用法:
|
||||||
|
build_level.bat # 默认配置
|
||||||
|
build_level.bat --json output/v02.json # 指定 JSON
|
||||||
|
build_level.bat --no-quit # 构建后不退出编辑器
|
||||||
|
|
||||||
|
环境变量(由 build_level.bat 设置):
|
||||||
|
LB_JSON_PATH — JSON 数据文件路径(相对于项目根目录)
|
||||||
|
LB_MAP_NAME — 目标关卡资产名
|
||||||
|
LB_MAP_PACKAGE — 关卡包路径(如 /Game/Maps)
|
||||||
|
LB_NO_QUIT — 设为 "1" 不退出编辑器
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# ---- 从环境变量读取配置 ----
|
||||||
|
json_rel = os.environ.get("LB_JSON_PATH", "tools/level-builder/output/level_v01.json")
|
||||||
|
map_name = os.environ.get("LB_MAP_NAME", "LVL_SuburbanV01")
|
||||||
|
map_package = os.environ.get("LB_MAP_PACKAGE", "/Game/Maps")
|
||||||
|
no_quit = os.environ.get("LB_NO_QUIT", "0") == "1"
|
||||||
|
map_asset_path = f"{map_package}/{map_name}"
|
||||||
|
|
||||||
|
# ---- 检查 unreal 模块 ----
|
||||||
|
try:
|
||||||
|
import unreal
|
||||||
|
except ImportError:
|
||||||
|
print("[LevelBuilder] FATAL: unreal 模块不可用,必须在 UE5 环境中运行")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# ---- 项目根目录 ----
|
||||||
|
# UE5 -ExecutePythonScript 模式下 CWD 是引擎目录,不是项目目录
|
||||||
|
# 所以必须通过环境变量传入项目路径
|
||||||
|
_project_root_str = os.environ.get("LB_PROJECT_ROOT", "")
|
||||||
|
if _project_root_str:
|
||||||
|
PROJECT_ROOT = Path(_project_root_str)
|
||||||
|
else:
|
||||||
|
# Fallback: 尝试从 .uproject 文件定位
|
||||||
|
_cwd = Path(os.getcwd())
|
||||||
|
if (_cwd / "ChildHood.uproject").exists():
|
||||||
|
PROJECT_ROOT = _cwd
|
||||||
|
else:
|
||||||
|
# 最后尝试 unreal API
|
||||||
|
try:
|
||||||
|
PROJECT_ROOT = Path(unreal.Paths.project_dir()).parent
|
||||||
|
except Exception:
|
||||||
|
PROJECT_ROOT = _cwd
|
||||||
|
|
||||||
|
json_path = PROJECT_ROOT / json_rel
|
||||||
|
|
||||||
|
print(f"[LevelBuilder] ==========================================")
|
||||||
|
print(f"[LevelBuilder] ChildHood Level Builder — Command Line")
|
||||||
|
print(f"[LevelBuilder] ==========================================")
|
||||||
|
print(f"[LevelBuilder] Project: {PROJECT_ROOT}")
|
||||||
|
print(f"[LevelBuilder] JSON: {json_rel}")
|
||||||
|
print(f"[LevelBuilder] Map: {map_asset_path}")
|
||||||
|
print(f"[LevelBuilder]")
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 等待编辑器子系统就绪 ----
|
||||||
|
def wait_for_editor(timeout=90):
|
||||||
|
"""轮询等待 EditorActorSubsystem 可用。"""
|
||||||
|
print("[LevelBuilder] 等待编辑器初始化...")
|
||||||
|
start = time.time()
|
||||||
|
while time.time() - start < timeout:
|
||||||
|
try:
|
||||||
|
subsys = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
|
||||||
|
if subsys is not None:
|
||||||
|
elapsed = time.time() - start
|
||||||
|
print(f"[LevelBuilder] 编辑器就绪 ({elapsed:.1f}s)")
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
time.sleep(1)
|
||||||
|
print(f"[LevelBuilder] FATAL: 编辑器初始化超时 ({timeout}s)")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if not wait_for_editor():
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 设置 sys.path ----
|
||||||
|
lb_dir = str(PROJECT_ROOT / "tools" / "level-builder")
|
||||||
|
for p in [str(PROJECT_ROOT), lb_dir]:
|
||||||
|
if p not in sys.path:
|
||||||
|
sys.path.insert(0, p)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 确保目标关卡存在 ----
|
||||||
|
def ensure_map(asset_path):
|
||||||
|
"""创建或加载目标关卡。成功返回 True。"""
|
||||||
|
# 已存在 → 加载
|
||||||
|
if unreal.EditorAssetLibrary.does_asset_exist(asset_path):
|
||||||
|
print(f"[LevelBuilder] 加载已有关卡: {asset_path}")
|
||||||
|
unreal.EditorLevelLibrary.load_level(asset_path)
|
||||||
|
return True
|
||||||
|
|
||||||
|
print(f"[LevelBuilder] 创建新关卡: {asset_path}")
|
||||||
|
|
||||||
|
# 方法 1: new_level(asset_path) — UE5.7 EditorLevelLibrary 直接创建
|
||||||
|
try:
|
||||||
|
unreal.EditorLevelLibrary.new_level(asset_path)
|
||||||
|
print("[LevelBuilder] ✅ 关卡创建成功 (new_level)")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[LevelBuilder] new_level 失败: {e}")
|
||||||
|
|
||||||
|
# 方法 2: AssetTools + WorldFactory(某些版本可用)
|
||||||
|
try:
|
||||||
|
asset_tools = unreal.get_editor_subsystem(unreal.AssetToolsSubsystem)
|
||||||
|
factory = unreal.WorldFactory()
|
||||||
|
new_asset = asset_tools.create_asset(
|
||||||
|
asset_name=map_name,
|
||||||
|
package_path=map_package,
|
||||||
|
asset_class=None,
|
||||||
|
factory=factory,
|
||||||
|
)
|
||||||
|
if new_asset:
|
||||||
|
unreal.EditorLevelLibrary.load_level(asset_path)
|
||||||
|
print("[LevelBuilder] ✅ 关卡创建成功 (WorldFactory)")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[LevelBuilder] WorldFactory 失败: {e}")
|
||||||
|
|
||||||
|
print("[LevelBuilder] FATAL: 无法创建关卡")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if not ensure_map(map_asset_path):
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 验证 JSON ----
|
||||||
|
if not json_path.exists():
|
||||||
|
print(f"[LevelBuilder] FATAL: JSON 文件不存在: {json_path}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 导入并执行构建 ----
|
||||||
|
from builder.scene_builder import build_level
|
||||||
|
|
||||||
|
print(f"[LevelBuilder] 开始构建...")
|
||||||
|
build_log = build_level(str(json_path), clear_existing=True)
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 保存关卡 ----
|
||||||
|
print("[LevelBuilder] 保存关卡...")
|
||||||
|
try:
|
||||||
|
unreal.EditorLevelLibrary.save_current_level()
|
||||||
|
print(f"[LevelBuilder] ✅ 关卡已保存: {map_asset_path}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[LevelBuilder] ⚠️ 保存失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 构建结果汇总 ----
|
||||||
|
if build_log:
|
||||||
|
ok = sum(1 for b in build_log if b.get("status") == "ok")
|
||||||
|
fail = len(build_log) - ok
|
||||||
|
print(f"")
|
||||||
|
print(f"[LevelBuilder] {'=' * 40}")
|
||||||
|
print(f"[LevelBuilder] SUCCESS: {ok} | FAILED: {fail} | TOTAL: {len(build_log)}")
|
||||||
|
print(f"[LevelBuilder] {'=' * 40}")
|
||||||
|
if fail > 0:
|
||||||
|
print(f"[LevelBuilder] 失败列表:")
|
||||||
|
for b in build_log:
|
||||||
|
if b.get("status") != "ok":
|
||||||
|
print(f" ❌ {b.get('name', '?')}: {b.get('reason', '未知')}")
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 退出编辑器 ----
|
||||||
|
if not no_quit:
|
||||||
|
print("[LevelBuilder] 退出编辑器...")
|
||||||
|
unreal.SystemLibrary.execute_console_command(None, "quit")
|
||||||
|
|
||||||
|
print("[LevelBuilder] Done.")
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
|
||||||
|
REM === ChildHood Level Builder - Command Line Build ===
|
||||||
|
REM
|
||||||
|
REM Usage:
|
||||||
|
REM build_level.bat (default config)
|
||||||
|
REM build_level.bat --json output/v02.json (specify JSON)
|
||||||
|
REM build_level.bat --map LVL_SuburbanV02 (specify map name)
|
||||||
|
REM build_level.bat --no-quit (keep editor open)
|
||||||
|
REM build_level.bat --no-null-rhi (show editor window)
|
||||||
|
REM build_level.bat --dry-run (print command only)
|
||||||
|
|
||||||
|
set "SCRIPT_DIR=%~dp0"
|
||||||
|
set "PROJECT_DIR=%SCRIPT_DIR%..\.."
|
||||||
|
for %%i in ("%PROJECT_DIR%\.") do set "PROJECT_ROOT=%%~fi"
|
||||||
|
set "UPROJECT=%PROJECT_ROOT%\ChildHood.uproject"
|
||||||
|
|
||||||
|
REM ---- Defaults ----
|
||||||
|
set "JSON_REL=tools/level-builder/output/level_v01.json"
|
||||||
|
set "MAP_NAME=LVL_SuburbanV01"
|
||||||
|
set "MAP_PACKAGE=/Game/Maps"
|
||||||
|
set "NO_QUIT=0"
|
||||||
|
set "NO_NULL_RHI=0"
|
||||||
|
set "DRY_RUN=0"
|
||||||
|
|
||||||
|
REM ---- Parse Arguments ----
|
||||||
|
:parse_args
|
||||||
|
if "%~1"=="" goto done_args
|
||||||
|
if /i "%~1"=="--json" (
|
||||||
|
set "JSON_REL=%~2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
)
|
||||||
|
if /i "%~1"=="--map" (
|
||||||
|
set "MAP_NAME=%~2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
)
|
||||||
|
if /i "%~1"=="--package" (
|
||||||
|
set "MAP_PACKAGE=%~2"
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
)
|
||||||
|
if /i "%~1"=="--no-quit" (
|
||||||
|
set "NO_QUIT=1"
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
)
|
||||||
|
if /i "%~1"=="--no-null-rhi" (
|
||||||
|
set "NO_NULL_RHI=1"
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
)
|
||||||
|
if /i "%~1"=="--dry-run" (
|
||||||
|
set "DRY_RUN=1"
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
)
|
||||||
|
if /i "%~1"=="--help" goto show_help
|
||||||
|
if /i "%~1"=="-h" goto show_help
|
||||||
|
echo [WARN] Unknown argument: %~1
|
||||||
|
shift
|
||||||
|
goto parse_args
|
||||||
|
:done_args
|
||||||
|
|
||||||
|
REM ---- Find UE5 Editor ----
|
||||||
|
set "UE_EDITOR="
|
||||||
|
if defined UE5_ROOT (
|
||||||
|
for %%b in (UnrealEditor.exe UE5Editor.exe) do (
|
||||||
|
if exist "%UE5_ROOT%\Engine\Binaries\Win64\%%b" (
|
||||||
|
set "UE_EDITOR=%UE5_ROOT%\Engine\Binaries\Win64\%%b"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%UE_EDITOR%"=="" (
|
||||||
|
for %%p in (
|
||||||
|
"C:\Program Files\Epic Games\UE_5.7"
|
||||||
|
"C:\Program Files (x86)\Epic Games\UE_5.7"
|
||||||
|
"D:\Program Files\Epic Games\UE_5.7"
|
||||||
|
"E:\Program Files\Epic Games\UE_5.7"
|
||||||
|
"C:\Program Files\Epic Games\UE_5.6"
|
||||||
|
"C:\Program Files (x86)\Epic Games\UE_5.6"
|
||||||
|
"D:\Program Files\Epic Games\UE_5.6"
|
||||||
|
"E:\Program Files\Epic Games\UE_5.6"
|
||||||
|
) do (
|
||||||
|
if not defined UE_EDITOR (
|
||||||
|
for %%b in (UnrealEditor.exe UE5Editor.exe) do (
|
||||||
|
if exist "%%~p\Engine\Binaries\Win64\%%b" (
|
||||||
|
set "UE_EDITOR=%%~p\Engine\Binaries\Win64\%%b"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%UE_EDITOR%"=="" (
|
||||||
|
echo.
|
||||||
|
echo [ERROR] UE5 Editor not found!
|
||||||
|
echo Set UE5_ROOT to your UE5 install directory, e.g.:
|
||||||
|
echo set UE5_ROOT=C:\Program Files\Epic Games\UE_5.7
|
||||||
|
echo.
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
REM ---- Path conversion (UE5 uses forward slashes) ----
|
||||||
|
set "SCRIPT_PATH=%SCRIPT_DIR%build_cmdline.py"
|
||||||
|
set "SCRIPT_PATH=!SCRIPT_PATH:\=/!"
|
||||||
|
set "UPROJECT_FWD=!UPROJECT:\=/!"
|
||||||
|
|
||||||
|
REM ---- Build command line ----
|
||||||
|
set "CMD_ARGS=-unattended -NoSound"
|
||||||
|
if "!NO_NULL_RHI!"=="0" set "CMD_ARGS=!CMD_ARGS! -NullRHI"
|
||||||
|
set "CMD_ARGS=!CMD_ARGS! -ExecutePythonScript=!SCRIPT_PATH!"
|
||||||
|
|
||||||
|
REM ---- Pass config to Python via env vars ----
|
||||||
|
set "LB_PROJECT_ROOT=!PROJECT_ROOT!"
|
||||||
|
set "LB_JSON_PATH=%JSON_REL%"
|
||||||
|
set "LB_MAP_NAME=%MAP_NAME%"
|
||||||
|
set "LB_MAP_PACKAGE=%MAP_PACKAGE%"
|
||||||
|
if "!NO_QUIT!"=="1" set "LB_NO_QUIT=1"
|
||||||
|
|
||||||
|
REM ---- Print info ----
|
||||||
|
echo.
|
||||||
|
echo ============================================
|
||||||
|
echo ChildHood Level Builder - Command Line
|
||||||
|
echo ============================================
|
||||||
|
echo UE5: !UE_EDITOR!
|
||||||
|
echo Project: !UPROJECT_FWD!
|
||||||
|
echo JSON: %JSON_REL%
|
||||||
|
echo Map: %MAP_PACKAGE%/%MAP_NAME%
|
||||||
|
echo NullRHI: %NO_NULL_RHI%
|
||||||
|
echo ============================================
|
||||||
|
echo.
|
||||||
|
|
||||||
|
REM ---- Dry Run ----
|
||||||
|
if "%DRY_RUN%"=="1" (
|
||||||
|
echo [DRY RUN] Command:
|
||||||
|
echo.
|
||||||
|
echo "!UE_EDITOR!" "!UPROJECT_FWD!" !CMD_ARGS!
|
||||||
|
echo.
|
||||||
|
exit /b 0
|
||||||
|
)
|
||||||
|
|
||||||
|
REM ---- Check JSON exists ----
|
||||||
|
set "JSON_ABS=%PROJECT_ROOT%\%JSON_REL%"
|
||||||
|
set "JSON_ABS=!JSON_ABS:/=\!"
|
||||||
|
if not exist "!JSON_ABS!" (
|
||||||
|
echo [ERROR] JSON not found: !JSON_ABS!
|
||||||
|
echo Run first: python tools/level-builder/main.py parse
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
REM ---- Execute ----
|
||||||
|
echo [LevelBuilder] Launching UE5 Editor (command line mode)...
|
||||||
|
echo [LevelBuilder] Editor will auto-save and quit after build.
|
||||||
|
echo.
|
||||||
|
|
||||||
|
"!UE_EDITOR!" "!UPROJECT_FWD!" !CMD_ARGS!
|
||||||
|
|
||||||
|
set "EXIT_CODE=!ERRORLEVEL!"
|
||||||
|
echo.
|
||||||
|
if "!EXIT_CODE!"=="0" (
|
||||||
|
echo [LevelBuilder] Build complete. Editor exited.
|
||||||
|
) else (
|
||||||
|
echo [LevelBuilder] Editor exit code: !EXIT_CODE!
|
||||||
|
)
|
||||||
|
exit /b !EXIT_CODE!
|
||||||
|
|
||||||
|
:show_help
|
||||||
|
echo.
|
||||||
|
echo ChildHood Level Builder - Command Line Build
|
||||||
|
echo.
|
||||||
|
echo Usage: build_level.bat [options]
|
||||||
|
echo.
|
||||||
|
echo Options:
|
||||||
|
echo --json PATH JSON data file (relative to project root)
|
||||||
|
echo --map NAME Target map asset name (default: LVL_SuburbanV01)
|
||||||
|
echo --package PATH Map package path (default: /Game/Maps)
|
||||||
|
echo --no-quit Keep editor open after build
|
||||||
|
echo --no-null-rhi Show editor window (for debugging)
|
||||||
|
echo --dry-run Print command without executing
|
||||||
|
echo --help, -h Show this help
|
||||||
|
echo.
|
||||||
|
echo Environment:
|
||||||
|
echo UE5_ROOT UE5 install directory
|
||||||
|
echo.
|
||||||
|
exit /b 0
|
||||||
@@ -21,14 +21,15 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_UNREAL = False
|
HAS_UNREAL = False
|
||||||
|
|
||||||
# 将项目根目录加入 sys.path 以支持 config 导入
|
# 将 level-builder 根目录加入 sys.path 以支持 config 导入
|
||||||
_SCRIPT_DIR = Path(__file__).resolve().parent
|
# 注意: 目录名含连字符 (level-builder),不能用 tools.level_builder 形式导入
|
||||||
_TOOLS_DIR = _SCRIPT_DIR.parent.parent.parent
|
_SCRIPT_DIR = Path(__file__).resolve().parent # builder/
|
||||||
if str(_TOOLS_DIR) not in sys.path:
|
_LB_DIR = _SCRIPT_DIR.parent # tools/level-builder/
|
||||||
sys.path.insert(0, str(_TOOLS_DIR))
|
if str(_LB_DIR) not in sys.path:
|
||||||
|
sys.path.insert(0, str(_LB_DIR))
|
||||||
|
|
||||||
from tools.level_builder.config.asset_mapping import MESH_ASSETS
|
from config.asset_mapping import MESH_ASSETS
|
||||||
from tools.level_builder.config.material_mapping import MATERIAL_PATHS
|
from config.material_mapping import MATERIAL_PATHS
|
||||||
|
|
||||||
logger = logging.getLogger("level_builder.builder")
|
logger = logging.getLogger("level_builder.builder")
|
||||||
|
|
||||||
@@ -168,7 +169,7 @@ def _spawn_mesh_actor(editor_subsystem, actor_def: dict):
|
|||||||
|
|
||||||
# 设置 Transform
|
# 设置 Transform
|
||||||
rot = actor_def.get("rotation", [0, 0, 0])
|
rot = actor_def.get("rotation", [0, 0, 0])
|
||||||
actor.set_actor_rotation(unreal.Rotator(rot[0], rot[1], rot[2]))
|
actor.set_actor_rotation(unreal.Rotator(rot[0], rot[1], rot[2]), False)
|
||||||
|
|
||||||
scale = actor_def.get("scale", [1, 1, 1])
|
scale = actor_def.get("scale", [1, 1, 1])
|
||||||
actor.set_actor_scale3d(unreal.Vector(scale[0], scale[1], scale[2]))
|
actor.set_actor_scale3d(unreal.Vector(scale[0], scale[1], scale[2]))
|
||||||
@@ -201,7 +202,7 @@ def _spawn_player_start(editor_subsystem, actor_def: dict):
|
|||||||
)
|
)
|
||||||
if actor:
|
if actor:
|
||||||
rot = actor_def.get("rotation", [0, 0, 0])
|
rot = actor_def.get("rotation", [0, 0, 0])
|
||||||
actor.set_actor_rotation(unreal.Rotator(rot[0], rot[1], rot[2]))
|
actor.set_actor_rotation(unreal.Rotator(rot[0], rot[1], rot[2]), False)
|
||||||
actor.set_actor_label(actor_def["actor_name"])
|
actor.set_actor_label(actor_def["actor_name"])
|
||||||
folder = actor_def.get("folder", "")
|
folder = actor_def.get("folder", "")
|
||||||
if folder:
|
if folder:
|
||||||
@@ -218,7 +219,7 @@ def _spawn_directional_light(editor_subsystem, actor_def: dict):
|
|||||||
)
|
)
|
||||||
if actor:
|
if actor:
|
||||||
rot = actor_def.get("rotation", [-45, 315, 0])
|
rot = actor_def.get("rotation", [-45, 315, 0])
|
||||||
actor.set_actor_rotation(unreal.Rotator(rot[0], rot[1], rot[2]))
|
actor.set_actor_rotation(unreal.Rotator(rot[0], rot[1], rot[2]), False)
|
||||||
actor.set_actor_label(actor_def["actor_name"])
|
actor.set_actor_label(actor_def["actor_name"])
|
||||||
folder = actor_def.get("folder", "")
|
folder = actor_def.get("folder", "")
|
||||||
if folder:
|
if folder:
|
||||||
|
|||||||
Reference in New Issue
Block a user