EP9 收尾复盘时我留了一句诚实的话游戏里那三个道具按钮——撤销 / 炸弹 / 换一换——UI 做好了、点了会扣计数、会响一声但按下去棋盘根本没变。这是当时整个游戏唯一按了没实际效果的地方。这一集EP10回头把它补完让它真正可玩到底。道具是 Block Blast 这类游戏的重要付费/留存抓手道具靠玩、连签、内购获得EP5/EP6 已经把怎么得到道具做好了但前提是道具得真的有用。三个道具三种对棋盘的操作撤销落子前留一张快照撤销的本质是把棋盘退回上一步。做法是在每次成功落子和每次炸弹之前给整盘 托盘 分数拍一张快照撤销就是把快照贴回去int[,]_undoBoard;ListPiece_undoTray;int_undoScore;bool_canUndo;voidSnapshot(){_undoBoardBoard.CloneCells();// 整盘拷一份_undoTraynewListPiece(Tray);_undoScoreScore.Value;_canUndotrue;}publicboolUndo(){if(!CanUndo)returnfalse;Board.LoadCells(_undoBoard);// 贴回去Tray.Clear();Tray.AddRange(_undoTray);Score.Value_undoScore;GameOverfalse;// 撤销能把你从死局里救回来_canUndofalse;// 一次只能撤一步returntrue;}注意GameOver false——撤销不只是反悔它能从死局复活这正是它作为付费道具的价值卡死了花一个撤销续命。而且一次只能撤一步_canUndo撤完即关不能无限回退。炸弹点哪炸哪清掉 3x3炸弹给棋盘开一个BombArea点中的格子周围 3x3 全清返回清掉的数量publicintBombArea(intcx,intcy,intradius){intn0;for(intxcx-radius;xcxradius;x)for(intycy-radius;ycyradius;y)if(InBounds(x,y)_cell[x,y]!0){_cell[x,y]0;n;}returnn;}视图层把炸弹做成两步点道具按钮 → 进入待引爆状态顶上提示点击方块引爆→ 再点棋盘任意格 → 引爆那一片。只有真炸到东西才扣道具点空地不消耗而且炸弹也留了撤销点手滑了能撤回来。下面这两张是真机实拍——左边是道具操作前棋盘堆了一片点炸弹、再点左下角那一片 3x3 就被炸空了填充数从 13 掉到 4橙色迸裂粒子正好盖在炸空的那一片上换一换重发一手新托盘最简单的一个当前三块不顺手换一换重发三块新的不可撤销会清掉撤销点并重判死局——万一换出来全放不下就是真死局了publicvoidRefreshTray(){DealTray();_canUndofalse;GameOver!Board.AnyPlaceable(UnusedTray());}顺手逼出一个真 bug写自检的时候单独跑这一集的道具测试是 16/16 全绿但接在前面 9 集后面一起跑就挂一条「开局不可撤销」失败。追下去是个真 bugNewGame重置了棋盘、分数、死局标志却没清撤销快照——所以开了新一局_canUndo还是上一局最后一步留下的true于是你能在新局里撤回上一局的棋盘。修复就一行在NewGame里补上_canUndo false; _undoBoard null;。这种 bug 单测一个系统时根本暴露不出来——必须多个系统按真实顺序连起来跑才会浮出水面。这也是为什么我每加一集都把全部自检从头跑一遍而不只跑新写的那几条。验证16 条断言 MCP 真机三连点逻辑层 16 条断言钉死撤销还原棋盘/分数/托盘且一次性、炸弹清区域且空炸不消耗、炸弹可撤销、换一换重发满 3 块且清撤销点……A 开局不可撤销 / 落子后可撤销 / 撤销还原棋盘(filled0)/分数(0)/托盘(3块) / 不能连撤两次 B 引爆已填格清掉东西(0) / 填充数下降 / 炸弹可撤销 / 空炸清0 / 空炸不留撤销点 C 换一换后托盘满3块 / 换一换清掉撤销点 16/16 PASS 断言之外还是老规矩——用 MCP 在真 PlayMode 里把三个按钮一个个点了一遍点撤销simulate_mouse_click→ 顶栏分数从 23 退回 12上一步消掉的方块全回来了道具计数 17→16点炸弹→ 顶上弹出点击方块引爆再点棋盘 → 那片 3x3 炸空上面两张截图点换一换→ 托盘三块瞬间换成全新的三块。每一步都capture_game_view截图回看确认棋盘真的按预期变了。三个按钮从按了没反应变成按了真改局面。撤销最商业的用法死局复活把撤销做对之后顺手补上了一个真正用到它的地方——死局结算面板。原来死局只有一行GAME OVER文字太糙。现在死局会弹一个结算面板本局得分、最高分、新纪录标记以及两个按钮——再来一局和复活用撤销复活就是撤销那条命脉的商业化用法死局 上一步把自己堵死了而落子前正好留了撤销快照所以复活 消耗一个撤销道具 Undo()棋盘退回死局前、GameOver翻回 false接着玩。这就是 F2P 里卡死了花点东西续命的钩子——道具的需求正是这么被设计出来的。死局广播也走事件总线控制器Send(GameOverMsg)→ UI 弹面板和前面所有系统一个套路。我用 MCP 把这条也点了一遍触发死局 → 面板弹出带★新纪录★→ 点复活 → 分数 25 退回 23、撤销 24→23、GameOver翻回 false、回到对局再点再来一局 → 空棋盘新开。顺手把首页和局内分开 道具换成图标对照成熟商业休闲游戏的通行结构后又补了两处正经游戏该有的结构首页 / 局内分离。原来所有东西堆在一屏现在是标准的先首页、点开始才进对局首页是个干净的大厅——标题、最高分、一个大大的开始游戏加上商城/每日/皮肤导航点开始才进棋盘局内左上角有← 首页随时退回。道具按钮换成图标。原来是撤销/炸弹/换一换三个文字按钮太工程师了。改成图标按钮——一张程序化生成的圆角光泽底套上撤销循环箭头/炸弹/换一换双向箭头三个图标右下角一个数量角标。一眼就懂、也更像那么回事这两处都是用 MCP 点着改、截图比着调出来的——首页点开始游戏进局内、点图标道具触发效果撤销 score 10→7、道具数 35→34、点← 首页退回大厅全程simulate_mouse_click验证。这一集的产物与诚实的话BlockGameController加撤销快照/Undo/Bomb/RefreshTrayBoardModel加CloneCells/LoadCells/BombAreaGameView接道具入口 炸弹待引爆交互。16 条断言全绿修了NewGame不清撤销快照的 bug MCP 真机三连点验证。死局结算面板最终分/最高分/新纪录 复活/再来一局死局走GameOverMsg事件广播复活复用撤销道具。至此游戏里再没有按了没效果的按钮死局也不再是一行干文字。诚实地讲道具的玩法逻辑做完了表现也接了一部分——炸弹引爆已经有迸裂粒子复用 EP7 那套缓动 白色光泽方块碎片和消行一个效果。还差的是撤销的方块飞回动画、换一换的洗牌动效这些纯 juice 是锦上添花EP7 框架已备好接上去就行不影响能不能玩。功能闭环这一层三个道具已经真正合上了。工具funplay-unity-mcp开源工程本系列做出来的完整 Unity 工程已开源上一篇EP9 收尾与复盘