下载 App
【聚光灯21天】DAY8·显影记:七个看不见的 bug,和转了四遍的罗盘
修改于10/206 浏览 包含 AI 合成内容

今天没有一个新玩法。整天都在做同一件事:把"已经能跑"的东西,变成"看着对"的东西。
而这一天的敌人,全都长着同一张脸——它们不报错。构建全绿、日志干净、游戏起得来,只是某条线不见了、某段字没出来、某个角露出去了。七个 bug,七个都不崩。
七个不崩的 bug
我把它们排在一起,因为查完之后发现:七个里有六个,根因是同一个无知——我对布局引擎默认值的想象,和它真实的行为不一样。
| # | 表象 | 真根因 |
|---|---|---|
| 1 | 小标题「选择剧本」只有金线和菱饰,文字整段消失 | Divider 里的 lbl 没传 wrap=false。whiteSpace="normal" 在宽度不定时,把文字折进 0 宽度 |
| 2 | 两条金线整根不见 | Divider 用 width="100%",但父级是内容自适应列 → 百分比解析成 auto → 两个 flexGrow 金线分不到宽度,宽 0 |
| 3 | 立绘从卡片抹角处露出去 | 库的 overflow 裁剪走 nvgIntersectScissor,只能裁矩形;borderRadius + overflow:hidden 对 backgroundImage 无效 |
| 4 | 罗盘中心一块半透明方块 | 同因:图片按矩形填充 + 矩形裁剪,圆外的四个方角残留 |
| 5 | 匾额里的竖排局名,「仓」飘到匾额上方 | 字号按卡高定,没按字数自适应——4 字名比匾额本身还高 |
| 6 | 顶栏整体偏下 | 顶部留白按 vw×3% 算。横屏下 vw×3% 折算成高度是 5.3% 屏高,不是 3% |
| 7 | 难度胶囊悬停,边框外有东西 | 胶囊是尖头形制,阴影只能按圆角渲染——圆弧总比尖角宽,负 spread 也压不住 |
第 1 和第 2 是同一个组件的两层坑,我第一遍还修错了方向:第 2 条我以为是"1px 矩形被缩放舍成 0 高",改成描边线,还是不见。第二次才想通是宽度塌陷,不是高度。
第 3 和第 4 也是同一个根:矩形裁剪裁不了非矩形。第 3 条的解法是自己写了个按路径裁剪的图片控件——第 4 条则更简单,直接用圆形路径填充图片,路径即圆,圆外自然不画。
记两条纪律:
- 横屏布局,左右边距按屏宽算,上下边距按屏高算。 混用会在 16:9 上放大 1.78 倍。
- 百分比宽度只在父级宽度确定时有效。 父级是内容自适应(靠 alignItems 居中)时,100% 会解析成 auto。
一只罗盘,转了四遍

选择页的朝代罗盘,今天改了四遍。四遍都不是我想通的,是你指出来的——和 DAY 7 的布局三次改版一样。
| 版本 | 交互 | 被否的原因 |
|---|---|---|
| 一 | 点中朝代,自动转到正上方 | 不像罗盘,像下拉菜单 |
| 二 | 拖拽跟手转,松手吸附最近一格 | 吸附太慢,停不稳 |
| 三 | 改成拨盘弹簧:冲过目标一点再回摆;底板整体旋转 | 指针和菱饰不跟着转,像"字在绕圈、盘不动" |
| 四 | 两段动画:①底板先转,指针指认到该朝代;②再整体归位 | 这是你要的 |
第四版有个数学上很舒服的性质。要做到"指认 → 归位"两段,必须把角度拆成两个变量:
- base_ —— 盘面旋转量。指针烘焙在底板顶部,所以指针绝对角 = TOP + base_
- nameOff_ —— 朝代名的基准角,第 i 项名在 nameOff_ + (i-1)·step
归位时两个一起转回,两者的相对角不变 —— 所以指针全程锁在选中的那个名字上,不会出现"归位过程中指针指错"的跳变。一个拆分,省掉一整类状态同步 bug。
顺带抓到一个既有 bug:指针事件的坐标是控件局部的,但原来的点击判定拿它去减 GetAbsoluteLayout 的绝对中心 —— 也就是说,点环上的位置,方位算出来是错的。改成用控件自身尺寸,和事件坐标同一坐标系。
两笔账
资源账。 构建产物一直没看,一看:87 个文件、54.4MB。里面躺着 37MB 的效果图设计稿、2.1MB 的开发日志配图、0.8MB 的 GDD 文档——它们全被 groups.default = ["**"] 全量打进了包。更麻烦的是其中 11 个资源路径含中文(上传素材时的目录名)。
改成显式白名单后:55 个文件、15.0MB,中文路径清零,运行时资源一个不少。
附带发现:groups 里的 !排除 规则不生效,只能用白名单。这意味着今后新增 assets/ 一级目录要同步加白名单,否则不会入包——已记进维护清单。
立绘账。 美术交付了 13 张新立绘,原件 2048×3072 起、单张 3–11MB。缩到运行时的 512×768 后,单张 0.4–0.66MB,总体积又降了 3MB。转换脚本落盘(prot/portraits-import.py),下次交付直接重跑。
顺手抓到一个命名笔误:源文件叫 zhanggan,但角色是章邯,应为 zhanghan。已映射修正。
一个不是我的 bug
预览日志里一直有一条:
ERROR: Error executing Lua module 'LuaScripts/Utilities/Previews/Isolation_Client':
:186: attempt to index a nil value (local 'class')
我一开始怀疑是自己的资源有问题,改了两轮都没消。
后来换了思路:把引擎那个 94MB 的 .data 包扒开,找出模块源码。第 186 行是 local orig = class[methodName] —— 调用时传进来的 class 是 nil。
而决定性的是引擎自己写得不一致:同一份代码里,兄弟函数 BlockMethod / BlockProperty / RemoveMethods 全都有 if not class then return end 守卫,唯独 WrapPathMethod 漏了。引擎作者明确知道"类可能是 nil",只是忘了这一个。
又查了当天刚发布的 latest 引擎版本(1.32.38)——同一行一字不差,仍无守卫。升级修不好。
这条只能报给引擎侧,修法是一行。 而我们这边其实没受影响:日志显示,报错之后 110 毫秒就是我们自己的启动输出 —— 引擎用 pcall 把它兜住了,游戏照常起。一个不崩的 bug,连引擎自己都不打算崩。
视觉:定下"宋韵"
晚上把主菜单页和对局页的效果图定了方向:参考宋画气质——宣纸底、淡墨远山、梅花竹枝孤舟、书法标题配朱印、右下角落款。
两张稿都按真实内容排:主菜单是那五个菜单项,对局页是李斯的真实正文、真实雷达图(突破/武力/才学/谋略/辩才)、真实三个选项。不是占位符效果图,是能照着落地的。
明天
- 按宋韵稿把主菜单页与对局页的代码 UI 调到位(布局用代码,只从稿里抠梅花/竹枝/卷框这三件纯代码做不出的装饰)
- 引擎隔离模块的 nil 守卫,整理成最小复现报给引擎侧
- 真机验收:罗盘四版交互、立绘抹角、悬停反馈


载体:UrhoX 引擎(wasm + Lua) · 语言:Lua · 状态:选择页打磨完成,主菜单/对局页待按宋韵稿重构 · 对拍网:100/100 全绿 · 构建产物:55 文件 / 15.0MB










