15.1 逻辑层单元测试
把《合成小岛》最易出错的合成规则收敛成可测的纯函数,用 Node 内置 node --test 写四类断言:边界值(空/上限/越界)、确定性(同 seed 同输入同输出)、异常路径(非法输入被拒绝而非静默通过)、属性不变量(价值守恒、占用单调不增),并讲清哪些该测、哪些不值得测。
category
把《合成小岛》最易出错的合成规则收敛成可测的纯函数,用 Node 内置 node --test 写四类断言:边界值(空/上限/越界)、确定性(同 seed 同输入同输出)、异常路径(非法输入被拒绝而非静默通过)、属性不变量(价值守恒、占用单调不增),并讲清哪些该测、哪些不值得测。
把每项优化写成一对整数增量:有的降包体却升内存,有的反过来。枚举所有子集,在包体 × 内存的平面上求帕累托前沿,找出「无法同时再降两者」的那些点,再用 B 基准扰动最不确定的内存增量看前沿怎么变——显式声明这是解析模型而非真机实测,帮你在取舍曲线上选点。
把一次运行拆成稳定帧与长帧两种:长帧占比极小时,平均帧耗时几乎不动,卡顿感知却直线下滑。用整数模型算出长帧频率、有效帧率与感知评分,再用 B 基准扫长帧频率,看评分在哪一档跌破软底线——全程显式声明这是解析模型而非真机实测,避免被平均值误导。
把冷启动耗时拆成下载 / 解析 / 编译 / 首帧四段可加的整数毫秒模型,比较同一包体在 Wi-Fi、4G、弱网三档下的分布,再用 B 基准扫包体看首屏时间在哪里越过预算——全程显式声明这是解析模型而非真机实测,用来判断该砍下载还是砍解析。
渐进式教学按连续失败次数把提示抬到三档,卡住不动时自动给提示,容错侧再给一个有限深度的撤销栈让误操作原路撤回;P 层内核加单测保证状态迁移,W 层单文件 HTML 原型用 Playwright 无头驱动,断言「连续失败→提示升级」与「误操作→撤销」并截图。
引导漏斗回答的是另一类问题:一万个玩家走到第几步会掉。用可播种 LCG 逐玩家逐步骤推进,每步含跳过、失败重试、直接流失三条分支,再跑两遍做对照——允许可跳过步骤跳过与强制逐步完成的最终完成率差多少,产出 JSON、CSV 与纯 Python SVG。
引导状态机把「教玩家认识玩法」变成一串可断言的步骤:每步只认自己的完成事件,未开始、已结束、事件不匹配、不可跳过的步被跳过、第一步没有可回退的步这五种非法迁移一律拒绝且不改状态;再配跳过、回退与幂等重入,用 P 层内核与单测把整条新手路径钉死。
音效与震动是同一个反馈模型的另外两个通道:用一张分级表把「事件 → 音效 → 震动档位 → 是否可关」写死,再用内核处理静音、震动开关、宿主能力探测与同一事件连点的频控,最后用可播种仿真统计一次会话的反馈预算、画出震动分级分布图供策划评估手感。
把「打击感」拆成可量化的三要素:屏幕震动(幅度按几何比衰减、方向交替)、命中停顿帧、缩放脉冲。三者全用整数、无随机,同一权重与同一时刻必得同一结果,最后用单文件 HTML 原型配 Playwright 断言「命中→震动→衰减到静止」的完整数值序列。
把手感拆成可计算的缓动曲线与时间轴:用整数定点实现线性、二次、三次、回弹、弹性五种缓动(进度取千分比、避开浮点),再搭一个支持并行串行、延迟、打断与 onComplete 的时间轴调度器,最后用单文件 HTML 原型配 Playwright 无头推进时间、采样动画值。
把 UI 性能拆成可算的整数:元素按「纹理 + 材质」合并绘制调用,作者顺序里相邻元素键不同就打断合批;给出收益模型脚本、CSV 与 SVG,再用 B 基准扫元素数看 UI 帧占比在哪一档越过预算——同一份配置跑 Python 仿真,数字全来自本机实跑。
把弹窗从「随手 new 一个框」升级成可算的弹窗栈:按层级压栈、同去重键拒绝重复、超时自动关闭、模态遮罩拦截点击穿透、点遮罩只关最上层模态——配可跑内核、单文件 HTML 原型与 Playwright 无头验收,全程整数毫秒、可确定性回放,无需真实时钟。
把 UI 布局拆成可算的整数像素:锚点(左右上下与拉伸)+ 偏移 + 边距递归求每个节点的最终矩形,用层级决定绘制顺序与遮挡,用点命中判断谁在最上面,再用虚拟滚动只实例化可视区间——配可跑内核、单文件 HTML 原型与 Playwright 无头验收。
把微信 / 抖音 / QQ / 百度与浏览器摆成一张五维能力兼容矩阵:登录、支付、广告形态、分享、云存档逐平台对比,每个平台再配一份「已知差异」清单,并用可跑的 S 层脚本统计差异条目数、按复用系数估算边际适配工时与总成本,并给出差异维度分布与三个可执行结论。
把同一份会话逻辑分别注入 Node mock 宿主与浏览器宿主,用同一组输入序列驱动,断言两侧终局摘要逐位相同。给出可跑的 session.ts、单测、浏览器宿主构建脚本与 Playwright 无头验收,正文给出两侧真实摘要值与 ok/fail/cancel 三态分布。
把登录、支付、广告、分享、云存档五类平台能力收敛成一组统一签名:每个方法返回 ok/fail/cancel 三态结果对象而不抛异常,业务代码里没有一处 try/catch。给出可跑的 PlatformAPI 接口定义、确定性 mock 宿主与三条路径都有断言的单测。
把「自研还是用引擎」变成一个可算的分界问题:用整数递推把引擎路径(前置 120 人时、每项功能按 70% 消耗、对定制功能加 55% 约束代价)与自研路径(前置 260 人时、逐项提速)逐步累加,看累计人时何时交叉,再用 5×5 网格扫出什么条件下自研划算。
给八条引擎 × 八条选择维度配上可调权重,算出加权总分与排名,再做单权重 ±20% 敏感度分析与 33 个场景的排名稳定性基准:LayaAir 与 Cocos Creator 总分只差 1 分、榜首随权重切换,Defold 与 Phaser 名次纹丝不动,回答哪些选型结论可以信、哪些不能。
小游戏引擎不是只有 Cocos。本节把 Cocos Creator、LayaAir、Egret、Defold、Phaser、PixiJS、Unity WebGL 与原生 Canvas 八条路线放进一张公开可观察的格局对照表,并用一段 S 层脚本统计各引擎开箱内置的能力轴覆盖:从 8 条全内置到 0 条全自建,看它们如何排成一条引擎到框架再到渲染库的谱系。
《小游戏开发实战》卷二《引擎、实现与体验打磨》全书目录与阅读路径:16 章 48 节,覆盖引擎选型评分、工程骨架与构建管线、渲染适配、资源管线、游戏循环与状态机、输入交互、物理碰撞、存档反作弊、对象池内存、平台能力适配层、UI、动效、新手引导、性能优化、测试与工程化,每节都配可跑的 Python 仿真、TypeScript 内核或单文件 HTML 原型。