下载 App

编辑器实体 zIndex 层级

问题

编辑器中墙段被房间面板覆盖不可见。原因:给房间设 zIndex=1 会创建 stacking context,其内部带背景色/TiledImage 的 floorLayer 作为 paint layer 在合成时盖过了同层级 zIndex=2 的墙段——差距太小不够可靠。

解决:底层不设 zIndex,上层用明显间距

错误做法(zIndex 间距太小 + 给底层也设 zIndex):
lua
-- ❌ 房间 zIndex=1 创建 stacking context,墙 zIndex=2 差距太小不可靠 -- 房间面板 return UI.Panel { zIndex = 1, ... } -- 墙段面板 local wallPanel = UI.Panel { zIndex = 2, ... }
正确做法(底层无 zIndex 按 DOM 顺序,上层用高 zIndex 强制浮起):
lua
-- ✅ 房间不设 zIndex,保持默认 auto/0,按 DOM 文档流在底层 return UI.Panel { position = "absolute", left = (room.x or 0) * gridScale, top = (room.y or 0) * gridScale, width = width, height = height, pointerEvents = "box-none", -- 不设 zIndex,默认 DOM 顺序 children = { floorLayer, interactionLayer }, } -- ✅ 墙段 zIndex=10,足够高确保浮在房间之上 local wallPanel = UI.Panel { position = "absolute", left = (segment.x or 0) * gridScale, top = (segment.y or 0) * gridScale, width = math.max(1, (segment.w or 1) * gridScale), height = math.max(1, (segment.h or 1) * gridScale), backgroundColor = wallColor, zIndex = 10, -- 关键:不设=2,设=10,和底层拉开足够间距 borderWidth = selected and 1 or 0, ... }

编辑器固定层级方案

编辑器 campusChildren 实体层级(固定 zIndex,不做 Y-sorting):

zIndex=0(默认/auto)
  ├── 地面区域 floorAreas
  └── 房间 rooms(含 floorLayer 地面纹理/颜色)
  
zIndex=10
  └── 墙段 wallSegments(房间墙+自由墙,浅灰{190,188,180}/门棕黄{200,155,60})

zIndex=20
  └── 地面物件 objects(扫把、课桌等)
  
zIndex=30
  └── 人员 characters(老师、保安等)
  
zIndex=50+
  └── 各类拖拽预览(房间框选、墙体拖拽、放置预览等)

关键教训

  1. 给元素设 zIndex 会创建 stacking context——其内部有 backgroundColor/TiledImage 的子元素会在该 z 平面上渲染 paint layer
  2. 两个兄弟节点 zIndex 差距要大(至少 5-10),差距 1-2 在 Yoga 合成时可能被内部 paint layer 覆盖
  3. 底层元素不要设 zIndex——让它按 DOM 文档流在底层,上层元素用高 zIndex 浮起最可靠
  4. 编辑器用固定层级不做 Y-sorting——编辑器是俯视布局工具,不需要前后遮挡排序;运行时地图才用 zIndex = Z_TIER + Y 动态 Y-sorting
  5. 运行时 vs 编辑器层级方案不同
  6. 运行时(校园地图.lua):动态 Y-sorting,zIndex = CharZ(y) = 2000 + math.floor(y)
  7. 编辑器(地图画布.lua):固定 zIndex 分层,墙=10 / 物件=20 / 人员=30 / 预览=50
以鼠标为锚点缩放
核心数学原理 缩放前后,鼠标指向的那个世界坐标点必须保持在同一屏幕位置。 已知:旧缩放 oldZoom、新缩放 newZoom、鼠标锚点屏幕坐标 (ax, ay)、当前偏移 (panX, panY) 步骤1:算出旧缩放下鼠标指向的世界坐标 wx = (ax - panX) / oldZoom wy = (ay - panY) / oldZoom 步骤2:新缩放后反解新偏移,让 wx/wy
官方
1 赞
右键拖拽平移
一、问题本质 不是平移公式写错,而是 UrhoX UI 库指针事件派发的两个不对称陷阱叠加: 陷阱 现象 根因文件 OnPointerMove 不向父冒泡 右键按下 isPanning_=true,但 move 事件永远到不了 mapView urhox-libs/UI/Core/Widget.lua(OnPointerDown/Up 有 parent 冒泡,OnPointerMove 没有) H
官方
4 赞
地图编辑器仿真 tick 重建抑制
UI 重建频率 = 事件分发的可靠性上限。 只要有一帧 SetRoot 销毁了正在处理 pointer 事件的控件,跨重建边界的 Down/Up 对就会被吞。高频仿真 tick 必须在 UI 边界按页面过滤。 关键代码(scripts/main.lua HandleUpdate) 四步走:先原地处理人员 → 聚合所有仿真 changed → 地图页强制压制 → 只放行显式/登录态变化。 -- ma
官方
4 赞
修复"地图编辑器刷新数据丢失"
问题诊断过程 用户报告:编辑器建好房间 → 保存 → 刷新页面 → 进编辑器 → 数据全没了。 关键线索:用户发现"校园日"模式刷新后能看到房间,但一进编辑器就没了。 这直接指向了编辑器页面自身的初始化逻辑,而非持久化链路。 根因 地图编辑模式.lua 的 EnsureBlankEditorLayout() 设计意图是"首次打开编辑器提供空白画布",用模块级布尔 editorLayoutClear
官方
4 赞
槽位变更只走原子方法
经验 下标 = 视觉格子,空槽是合法状态。定长 9 槽,inventory[i]=nil 即第 i 格空着,中间允许空。任何"把物品往前挪/压缩/重排"的操作都会让"你看到的格子"和"数组真实下标"脱节 → 物品消失。渲染直映 inventory[i],数据层绝不重排。 稀疏表禁用 #。带 nil 洞的表 #inv 是未定义的(可能=0 直接读成空包,或=洞前边界)。所有遍历上界一律 Player
官方
4 赞
地图编辑器地面交互与视觉优化
一、问题链 用户截图反馈了三个递进的问题: 问题 1:点击地面类型(如食堂地砖),弹窗不关闭,挡住画布无法操作 ↓ 修复 v0.10.94 问题 2:地面贴图太大,一块地砖比小人还宽,比例失调 ↓ 修复 v0.10.96(改配置值) 问题 3:改了配置值后刷新仍然太大——旧存档的 tileSize=256 优先级高于新 config ↓ 修复 v0.10.97(反转渲染优先级) 二、关键代码
官方
4 赞
自动寻路赠送
核心功能 携带模式(点击物品跟鼠标)下: ≤8格:点击小人直接赠送(金色边框) >8格:点击远距离小人 → 自动寻路走向目标 → 到达8格内自动赠送 取消:玩家按方向键/WASD/摇杆手动移动 → 立即取消,恢复物品 关键经验(3条踩坑教训) 经验1:类型标识不是中文,是英文枚举值 地图编辑器放置的角色 type/job 字段是英文标识(teacher_3、doctor、cleaner_2、tea
官方
1 赞
精灵平滑移动、墙碰撞体积
一、 渲染层用连续坐标(scripts/页面/校园地图.lua,三处统一): -- NPC 定位(第408-410行) local contLeft = (character.x or 0) * 5 - 18 - charLeft local contTop = (character.y or 0) * 5 - 36 - charTop -- 主角定位(第504-506行) local con
官方
1 赞
UI动画的技巧
悬停动画(缩放+旋转) 技巧:分离X/Y轴缩放时间,配合随机旋转方向,使用EASE_OUT + TRANS_BACK曲线。 关键代码: func hover() -> void: if disabled: return pivot_offset = size / 2.0 var scale_ratio = clampf(width_full_rot / size.x, 0.5, 1.0) var
官方
3 赞
图片加载三层优化设计
目标场景:地图编辑器"物品/墙体/地面/房间/人员"调色板弹窗的图片首帧显示 文档目的:沉淀"图片为什么慢、怎么治、发布后玩家体验如何、未来加资源时 preload_groups 怎么取舍"的完整结论,避免重复踩坑。 一句话结论 WASM 下图片"慢"不是单一问题,而是下载 / 解码 / 上传 GPU 三件事全堆在"玩家点弹窗那一刻"做导致的。优化的本质是把这三件事提前到启动期做(让玩家点的时候图
官方
1 赞