数据库隔离
05/121 浏览攻略
现在我有完整的理解了。情况如下:
根本原因:
地图编辑器里有「📌 绑定关卡」按钮,调用 DraftBindings.BindMap() 把地图绑定保存到本地沙盒文件
但没有「🚀 发布」按钮,CrossPlayerChannel.PublishLevels() 从未被调用
levels.json(构建包)永远是空的,玩家(非 Admin)进入关卡只会用 GenerateDefaultMap()
Admin 路径(路径 0)会从 DraftBindings 加载 → 所以开发者测试时能看到自己绑定的地图
解决方案:在地图编辑器 UI 中,「绑定关卡」旁边加一个「🚀 发布」按钮,构建 ExportAllMaps 格式数据并调用 CrossPlayerChannel.PublishLevels(),这样 maps/levels_cache.json 就会被填充,非 Admin 玩家进入关卡时也能读到正确的地图。
同时需要一个 buildExportAllMaps() 工具函数,收集所有已保存地图 + DraftBindings 拼装成完整的 levelsData。
先看看 DraftBindings 里是否有 GetAllMapBindings 和地图数据读取能力
好,现在我有了完整的架构理解。来实现方案:
方案:
在 DraftBindings.lua 里加一个 ExportAllMaps(callback) 函数 — 读取所有本地沙盒地图文件 + bindings,组装成 levelsData 格式
在 MapEditorUI.lua 工具栏里加「🚀 发布」按钮,调用 ExportAllMaps → CrossPlayerChannel.PublishLevels
问题根因 + 修复说明
为什么玩家进关卡牙龈会消失
根因是一条三级失效链:
levels.json 为空
→ LevelManager 无任何 binding
→ doLoadMap 路径 A/B 均无数据
→ 回退到 Map.GenerateDefaultMap()
→ 默认地图里没有按编辑器设计放置牙龈
→ 玩家看到的不是编辑器里设计的地图
Admin 路径(路径 0)走的是 DraftBindings 本地草稿文件,所以开发者自己测试能看到正确地图,但普通玩家不走这条路。
修复内容
1. DraftBindings.lua — 新增 ExportAllMaps(callback)
收集所有已绑定器官的地图文件,从本地沙盒 maps/*.json 读取数据,组装成 LevelManager.Init() 所需的格式(含 maps、bindings、npcBindings、version)。
2. MapEditorUI.lua — 工具栏新增「🚀 发布」按钮
点击后:
调 DraftBindings.ExportAllMaps() 打包数据
调 CrossPlayerChannel.PublishLevels() 写入沙盒缓存 maps/levels_cache.json
下次启动时 LevelManager.Load() 优先读取 cache → GetMapData(organId) 返回正确地图数据 → 玩家看到编辑器设计的地图
正确使用流程
地图编辑器:设计地图 → 保存 → 📌 绑定关卡 → 🚀 发布
↓
写入 maps/levels_cache.json
↓
玩家进入口腔关卡 → LevelManager 读 cache → 加载绑定地图
根本原因:
地图编辑器里有「📌 绑定关卡」按钮,调用 DraftBindings.BindMap() 把地图绑定保存到本地沙盒文件
但没有「🚀 发布」按钮,CrossPlayerChannel.PublishLevels() 从未被调用
levels.json(构建包)永远是空的,玩家(非 Admin)进入关卡只会用 GenerateDefaultMap()
Admin 路径(路径 0)会从 DraftBindings 加载 → 所以开发者测试时能看到自己绑定的地图
解决方案:在地图编辑器 UI 中,「绑定关卡」旁边加一个「🚀 发布」按钮,构建 ExportAllMaps 格式数据并调用 CrossPlayerChannel.PublishLevels(),这样 maps/levels_cache.json 就会被填充,非 Admin 玩家进入关卡时也能读到正确的地图。
同时需要一个 buildExportAllMaps() 工具函数,收集所有已保存地图 + DraftBindings 拼装成完整的 levelsData。
方案:
在 DraftBindings.lua 里加一个 ExportAllMaps(callback) 函数 — 读取所有本地沙盒地图文件 + bindings,组装成 levelsData 格式
在 MapEditorUI.lua 工具栏里加「🚀 发布」按钮,调用 ExportAllMaps → CrossPlayerChannel.PublishLevels
找到根本原因了!CELL_TOWER = 4 不在 Config.OverlayTiles 里,所以 Map.SetCell(r, c, CELL_TOWER) 会走 else 分支,直接把 groundLayer[r][c] 覆盖成 CELL_TOWER:
lua
复制
Map.SetCell(r, c, CELL_TOWER)
→ Config.IsOverlayTile(CELL_TOWER) = false
→ groundLayer[r][c] = CELL_TOWER ← 牙龈地面层被污染!
调用方是 Pathfinding.WouldBlockAllPaths,每次检查放塔是否堵路时都会临时污染 groundLayer。
两处修复已完成并构建成功。
修复内容说明:
Fix 1 — Config.lua:将 CELL_TOWER 加入 OverlayTiles
[Config.CELL_TOWER] = true, -- 防御塔是覆盖层,绝不覆盖地面层
效果:Map.SetCell(r, c, CELL_TOWER) 调用时,IsOverlayTile(CELL_TOWER) 现在返回 true,只写 overlayLayer,groundLayer 完全不受影响。
Fix 2 — Pathfinding.lua:WouldBlockAllPaths 改为无论结果都还原
lua
复制
-- 无论是否阻断,都恢复原始状态
Map.SetCell(towerRow, towerCol, origCell)
Map.RebuildAllConnectivity()
效果:寻路连通性检测成为纯函数,不产生任何副作用,groundLayer 在检测后始终回到原始状态。
两个修复的组合作用:
即使只有 Fix 1,SetCell(CELL_TOWER) 就已经不会污染 groundLayer 了;Fix 2 是额外的防御层,确保就算将来有其他代码路径临时调用 SetCell 也不会留下残留状态,完全实现了用户要求的"无论玩家怎么操作,不能影响设计好的地图地形"数据隔离。
必须立即回答这个问题:
它是"永久地形"(草地、牙龈、路径)→ 不加 OverlayTiles,SetCell 写地面层
它是"运行时动态对象"(塔、单位、临时标记)→ 必须加 [CELL_XXX] = true 到 OverlayTiles,否则放置时会静默销毁下方地面贴图
临时改写状态再检测 = try/finally 思维
任何"先改、后检、再还原"的函数,还原逻辑必须无条件执行,不能放在 if 的某个分支里。
lua
复制
-- 正确模式(类比 try/finally)
local orig = Map.GetCell(r, c)
Map.SetCell(r, c, tempValue) -- 临时改
local result = doCheck() -- 检测(可能有多个 return 分支)
Map.SetCell(r, c, orig) -- 无条件还原(无论结果如何)
return result



