天空盒bug,内置资源不存在?求官方帮忙瞅瞅

修改于05/0982 浏览问题诊断
# BUG-001: 天空盒 BrightDay1 纹理缺失
# 对话连接:TapTap 制造
| 字段 | 值 |
|------|-----|
| 状态 | ✅ 已修复 |
| 严重程度 | 中(不影响功能,但每次启动报 6 个错误) |
| 影响版本 | Engine build 1e93ef1e |
| 修复日期 | 2026-05-09 |
| 关联任务 | P0-T1 场景搭建 |
---
## 现象
每次启动游戏,控制台固定输出 6 个错误:
```
ERROR: Could not find resource Textures/BrightDay1_PosX.dds
ERROR: Could not find resource Textures/BrightDay1_NegX.dds
ERROR: Could not find resource Textures/BrightDay1_PosY.dds
ERROR: Could not find resource Textures/BrightDay1_NegY.dds
ERROR: Could not find resource Textures/BrightDay1_PosZ.dds
ERROR: Could not find resource Textures/BrightDay1_NegZ.dds
```
无论游戏代码是否引用这些资源,错误始终存在。
## 根因
引擎内置资源 `Textures/Skybox.xml` 被标记为 `#blocking`(启动时强制预加载)。该 XML 是一个 cubemap 定义,引用了 6 个 `BrightDay1_*.dds` 面贴图,但**这些 DDS 文件在引擎资源包中不存在**。
加载链路:
```
引擎启动
  → 预加载 Textures/Skybox.xml (#blocking)
  → 解析 XML,发现 6 个 <face> 引用 BrightDay1_*.dds
  → 6 个文件均不存在 → 6 个 ERROR
同时:
  Materials/Skybox.xml (#blocking) → 引用 Textures/Skybox.xml → 触发相同链路
  Materials/SingleLayerWater.xml(水面材质) → 内部也引用 Materials/Skybox.xml
```
这是**引擎自身的资源缺失问题**,与用户代码无关。
## 排查过程
| # | 尝试方案 | 结果 | 失败原因 |
|---|---------|------|---------|
| 1 | 代码中不引用 `Materials/Skybox.xml` | ❌ 6 错误不变 | 引擎预加载与用户代码无关 |
| 2 | 去掉 `SingleLayerWater.xml`,改用 PBR 材质 | ❌ 6 错误不变 | 同上,但丢失了水面波光效果 |
| 3 | 提供自制 `BrightDay1_*.dds` 文件放入 `assets/Textures/` | ❌ 6 个 CDN 404 | 构建系统将文件上传 CDN 后路径解析异常 |
| 4 | 覆盖 `Skybox.xml`,face 引用自制 PNG 面贴图 | ❌ 6 个 CDN 404 + 1 解析错误 | 同上,cubemap XML 的 face 引用在 CDN 环境下不可靠 |
| 5 | 将 DDS cubemap 数据直接命名为 `Skybox.xml` | ❌ 3 个 XML 解析错误 | WASM 引擎严格按扩展名解析,`.xml` 必须是合法 XML |
| 6 | 空 cubemap XML `<cubemap />` | ⚠️ 降到 1 个错误 | 引擎回退路径将目录名 "Textures" 当资源加载 |
| 7 | cubemap XML 引用引擎内置 `DefaultNormal.tga` | ✅ 0 错误 | 该纹理存在且可正常加载 |
**核心发现**:cubemap XML 中 `<face>` 引用的文件,经构建系统 CDN 化后路径解析异常,导致自提供的面贴图(无论 DDS 还是 PNG)均无法加载。只有引用引擎已有的内置资源才能正常工作。
## 修复方案
用两个覆盖文件切断引擎的错误加载链:
### 文件 1: `assets/Textures/Skybox.xml`
覆盖引擎内置的 cubemap 定义,将 6 个 face 指向引擎自带的小纹理(47 字节,确保存在):
```xml
<cubemap>
    <face name="Textures/DefaultNormal.tga" />
    <face name="Textures/DefaultNormal.tga" />
    <face name="Textures/DefaultNormal.tga" />
    <face name="Textures/DefaultNormal.tga" />
    <face name="Textures/DefaultNormal.tga" />
    <face name="Textures/DefaultNormal.tga" />
</cubemap>
```
### 文件 2: `assets/Materials/Skybox.xml`
覆盖引擎内置的天空盒材质,不引用 cubemap 纹理:
```xml
<material>
    <technique name="Techniques/DiffSkybox.xml" />
    <cull value="none" />
</material>
```
### 实际天空渲染
游戏的天空渲染完全不依赖上述两个文件,而是在 `DayNight.lua` 中程序化创建:
```lua
local skyMat = Material:new()
skyMat:SetTechnique(0, cache:GetResource("Technique", "Techniques/DiffSkybox.xml"))
skyMat:SetTexture(0, cache:GetResource("TextureCube", "Textures/Skybox.dds"))
```
`Skybox.dds` 是通过 AI 生成蓝天白云全景图,再用 `convert-panorama` 工具转换的 cubemap 文件。
## 关键经验
1. **引擎 `#blocking` 资源无法通过代码规避** — 即使不在代码中引用,引擎启动时仍会强制加载
2. **CDN 环境下 cubemap face 引用不可靠** — 自提供的面贴图文件上传 CDN 后路径解析失败,只能引用引擎已内置的资源
3. **WASM 引擎严格按扩展名解析** — `.xml` 扩展名的文件必须是合法 XML,不能塞入二进制数据
4. **资源覆盖优先级** — `assets/` 目录下同名文件可覆盖引擎内置资源,这是解决引擎资源缺陷的有效手段
@天一 求天哥帮忙瞅瞅
3