下载 App

《变成黑洞》开发日志

10/2419 浏览综合
为玩家推翻重来设计新玩法,导致游戏全是bug, ai都不听话的那种。以后我慢慢修吧。当前版本可能是最后的版本了。已经将tap tap创造已经开发到极致了。
horizontal linehorizontal line

一、本期主线:一次撞击被当成了无数次

这一期所有问题都指向同一件事:
Impact 被反复调用。
Contact 每帧处理一次接触,但接触记录会被距离判定清掉重建。撞击后两块球贴合在一起(位置重叠、速度相同),PruneContacts 每隔几帧就把记录清掉,下次 broadphase 又发现它们重叠 → Impact 再来一次。
于是出现三个看起来毫无关联的现象,其实是同一个 bug:
表面现象真实原因
高速对撞最后都会融合第二次 Impact 把接近速度从 800 覆盖成 20
一次对撞喷出上百个碎片每次 Impact 都喷一批碎片
两块差不多大的球,一方被吃掉反复撞击把一方剥到降阶
horizontal linehorizontal line

二、高速对撞必融合

现象

用户反馈「碰撞逻辑有问题」。实测碰撞矩阵:
正心 800 速度  → 融合
正心 1500 速度 → 融合
悬殊 3 撞 6    → 融合
悬殊 3 撞 9    → 融合
而融合门槛只有 266(vEsc × 1.25)。800 和 1500 都远超门槛,不该融合。

排查过程

第 1 次尝试:以为是「接触记录被重建,contact.approachSpeed 丢了」。
把接近速度从 contact 搬到天体自身 body.impactSpeed。结果:没用。
第 2 次尝试:加时间窗口,防止 impactSpeed 永久残留。
结果:还是没用。
第 3 次:直接打印 Impact 每次调用的参数。
step=30  speed=813   ← 真撞击
step=53  speed=20    ← 又一次 "撞击"
撞击发生了两次。 第二次时两球已经贴合、一起以 400 飞,接触记录重建又触发一次,把 impactSpeed 从 813 覆盖成了 20。
融合判据读到 20 < 255 → 判定「引力束缚」→ 1.5 秒后融合。

修复

只记录更强的撞击,不被低速余震覆盖:
lua
local prevSpeed = a.impactSpeed or 0 if speed >= prevSpeed then a.impactSpeed, b.impactSpeed = speed, speed a.impactSpeedTick, b.impactSpeedTick = step, step end
验证:
step=30  speed=813  采用=true
step=53  speed=20   采用=false
结果:未死亡 ✓
horizontal linehorizontal line

三、一次对撞喷出上百个碎片

现象

用户说「碎石旁边突然冒出一小堆」。实测两块第 5 阶天体(r=161)对撞:
f=3   实体 2 → 42   (新增 40)
f=6   实体 42 → 82  (新增 40)
f=9   实体 82 → 112 (新增 30)
一次对撞,实体数从 2 涨到 169。

根因

同第二节:Impact 被反复调用,每次都调用 SprayShards 喷一批碎片。

修复

加撞击节流,同一对天体在 graceTime 内只做一次完整撞击:
lua
if (step - a.physicsGraceTick) * fixedStep < graceTime then -- 冷却中:只做速度处理,不剥落、不喷碎片 ShareHeat(a, b, Impulse(a, b, nx, ny, 0, 0)) return end
验证:
f=40  撞击碎片=6  (峰值=6)
f=200 撞击碎片=6  (峰值=6)
峰值稳定在 FragmentsPerImpact = 6,不再增长。
horizontal linehorizontal line

四、碎石互撞,一方凭空消失

现象

用户贴图指出「这玩意是碎石与碎石撞出来的碎片」。实测两块等质量自然碎石(各 1728)对撞:
f=22  r1活=false(质量 0)   r2活=true(质量 1728 → 3456)
3456 = 1728 × 2——一块把另一块吞了,不是碎片。

根因

Collect 的双碎石分支没有质量门槛:
lua
elseif aPrey0 and bPrey0 then if b.mass > a.mass then host, food = b, a end -- 大一点点就吃
两块同为 1728 的碎石,浮点差一点点就一方吞另一方。
物理上,两块等大的岩块对撞会各自崩碎或互相弹开,不会凭空合并。

修复

碎石之间也加门槛,复用 BounceRatio:
lua
if small.mass / big.mass > rr then contacts[key] = nil return -- 差不多大:互不相吃 end
验证:修复后两块都存活,各保持 1728。
门槛对碎片的影响(确认没误伤):
情况质量比结果
两枚自然碎石1.00互不相吃 ✓
撞击碎片大块(0.40) vs 小块(0.06)0.15小块被吸收 ✓
horizontal linehorizontal line

五、势均力敌时玩家获胜

需求

「差不多大小的就是玩家获胜。」

第一次修改(失败)

只改了融合路径的判定:
lua
local tie = 质量比 >= PlayerTieRatio if tie and (a.isPlayer or b.isPlayer) then -- 玩家当宿主
测试通过。但用户说「你没改好啊」。

根因:两个门槛互相矛盾

BounceRatio = 0.94 和 PlayerTieRatio = 0.9 在 0.90~0.94 区间给出相反结论:
  • BounceRatio:0.94 以下才允许吞
  • PlayerTieRatio:0.90 以上算平手、玩家赢
判定顺序写成了「先用 BounceRatio 卡门槛,再判玩家优先」,于是 0.90~0.94 区间被第一道门槛拦下,玩家没赢。

修复:调整判定顺序

lua
-- ① 势均力敌 + 有玩家 → 玩家获胜(最高优先级) if (a.isPlayer or b.isPlayer) and massRatio >= playerTie then -- 玩家当宿主 else -- ② 其余:按 BounceRatio 门槛 if massRatio > ratio then return end host, food = big, small end

验证

完全隔离测试(场上只剩玩家和 NPC):
NPC / 玩家结果
1.00(等大)玩家胜
1.05(NPC 大 5%)玩家胜
1.08(NPC 大 8%)玩家胜
1.10(NPC 大 10%)玩家胜 ← 临界
1.12(NPC 大 12%)玩家输 ← 临界
1.20(NPC 大 20%)玩家输
1.50(NPC 大 50%)玩家输
horizontal linehorizontal line

六、天体碰撞应该完全非弹性

一次走错方向

修完「两球撞上粘住」后,我加了 BounceRestitution = 0.35,让它们弹开。用户立刻指出:
「角色之间的相撞哪那么容易被弹开啊,大部分都化成了热量和爆炸对不对。」
确实错了。真实天体撞击的恢复系数 e 在 0.1~0.3,尺度越大越低(星球级 e≈0),绝大部分动能变成热、塑性变形、碎裂。

修复

所有冲量调用统一用 e = 0:
lua
local lost = Impulse(a,b,nx,ny,0, ...) local launch = removed > 0 and lost * 0.2 or 0 -- 20% 给碎屑 ShareHeat(a,b,lost-launch) -- 80% 给热量
删掉了 BounceRestitution 配置和所有相关变量。

验证

初始动能 4.879e10
撞后动能 2.962e5      ← 剩 0.0006%
热量     3.518e10     ← 几乎全部转成热
horizontal linehorizontal line

七、本期的方法教训

三次排查都验证了同一件事:
不要猜,打印出来看。
问题我猜的原因实际原因
高速对撞融合contact 记录被重建撞击发生两次,第二次覆盖了速度
碎片喷不停(没猜到)同上,Impact 被调用多次
玩家没赢改错了路径两个门槛参数互相矛盾
第一、二个问题我猜了两轮都没猜对(先搬 contact、再加时间窗口),最后靠打印 Impact 的每次调用参数才看到 step=30 speed=813 和 step=53 speed=20 这两行。
很多轮排查中,我还遇到一个干扰:改了源码但没构建,跑的仍是旧构建产物,导致「改了没效果」的假象。这一期至少遇到两次。
horizontal linehorizontal line

八、验证

  • 高速对撞不再融合(800/1500 实测各自保留质量)
  • 一次对撞碎片峰值稳定在 6
  • 两块碎石互撞都存活,各保持 1728
  • 势均力敌玩家获胜:NPC 大 10% 以内玩家赢,大 12% 以上玩家输
  • 碰撞完全非弹性:动能 99.999% 转成热
  • LSP 0 Error,构建通过
horizontal linehorizontal line

九、已知边界

  • PlayerTieRatio = 0.9 意味着玩家能吃下比自己大 10% 的天体。这是游戏性取舍,不是物理结果。
  • 撞击节流用 graceTime = 0.75 秒。理论上短时间内多次真实撞击会被合并成一次,但实际游戏里天体碰撞不会这么密集。
  • 食物密度与刷新速度的矛盾仍未解决(第 13 期遗留)。视野内 5 块 + 视野外刷新,玩家找目标太慢。
  • 手机实机帧率仍未测。
已通关,放心玩截图
已通关,放心玩
官方
1 赞
《变成黑洞》开发日志
日期:2026-10-23 代码规模:14022 行 / 20 个文件 一、本期主线:三个「不应该是这样」的物理 这一期的问题全部来自同一个地方:物理规则是对的,但套错了对象。 两块陨石撞一下,变成碎石被吃掉 —— 「同归于尽」变成了「一方吃掉另一方」 两块等大的球撞上,双双停在原地 —— 像粘住,不像天体 玩家撞成重伤,进度条纹丝不动 —— 掉血和进度是两套独立计量 三次排查都经历同一个过程:先
官方
2 赞
《变成黑洞》开发日志第 5 期 · 补全真实天体演化链与黑洞重做截图
《变成黑洞》开发日志第 5 期 · 补全真实天体演化链与黑洞重做
日期:2026-10-02 当日构建次数:5 次 本期进展 这一期主要做了一件事:把「碎石 → 黑洞」这条链上的物理缺失补上。 之前有玩家在评论区问「黑洞是怎么来的」,我回头查了一遍天体物理资料,发现游戏的进化链在科学上站不住脚。于是做了一次系统性修正。 1. 补上中子星,进化链扩展到 14 阶 问题:真实演化里,红巨星之后应该是白矮星 / 中子星 / 黑洞三选一,取决于坍缩后的核心质量。之前红巨
官方
1 赞
《变成黑洞》开发日志第 1 期截图
《变成黑洞》开发日志第 1 期
项目:变成黑洞 引擎:UrhoX 类型:宇宙题材吞噬进化(街机) 第 1 期 · 项目起步与核心玩法 日期:2026-09-18 当日构建次数:19 次 本期进展 完成了项目从零到「能玩」的全过程,核心是一个宇宙版的「大鱼吃小鱼」:玩家从一块碎石开始,靠吞噬比自己小的天体不断成长。 定下 9 阶进化链 一开始的进化链设计得比较粗,只有 9 阶: 星尘 → 碎石 → 陨石 → 小行星 → 矮行星#聚光灯GameJam开发者日志
官方
2 赞
《变成黑洞》开发日志第 3 期 · 物理真实化起步
日期:2026-09-21 ~ 2026-09-26 构建次数:3 次(09-21)+ 3 次(09-26) 本期进展 激励视频广告(09-21) 接入了「看广告复活」:玩家死亡后可看广告原地复活。 广告代码的关键设计是以回调的 result.success 作为唯一发奖依据,同步拒绝、异步回调、超时看门狗共享同一个「一次性完成」状态,避免重复发奖。 纯引力模式(09-26) 这是本期最大的改动,
官方
2 赞
《变成黑洞》开发日志第 4 期 · 3D 自转、进化链扩展与撞击反馈截图
《变成黑洞》开发日志第 4 期 · 3D 自转、进化链扩展与撞击反馈
日期:2026-09-27 ~ 2026-09-29 构建次数:7 次(09-27)+ 11 次(09-29) 本期进展 1. 真 3D 自转(09-27) 有玩家反馈「天体看起来像圆盘在转,不像球体」。 问题在于原来只是平面贴图旋转:贴图在圆内转圈,看起来就是一张纸在转。 重写后的做法是把表面特征(陨石坑、大陆、云团)建在单位球上: 出生时在单位球面撒 N 个特征点 每帧按自转角绕自转轴旋转 再
官方
2 赞
4 回复
《变成黑洞》开发日志第 2 期 · 玩法闭环与首次发布截图
《变成黑洞》开发日志第 2 期 · 玩法闭环与首次发布
日期:2026-09-19 当日构建次数:29 次 本期进展 这一期的目标很明确:让游戏能发布。 1. 补全玩法闭环 之前只有「吃」,没有「死」。这一期加上: 死亡判定:被更大的天体吞噬即死亡 死亡界面:显示本局得分、吞噬数、复活次数 结算:最高分记录 2. 首次发布上线 完成了发布所需的全套素材: 游戏图标(黑洞吸积盘特写,1024×1024) 宣传图(主标题 + 黑洞吞噬场景) 3 张商店截图
官方
2 赞
2 回复
《变成黑洞》经费已至,敬请期待
日期:2026-10-17 ~ 2026-10-18 本期构建序号:19 → 56(共 38 次构建) 代码规模:8469 行 / 14 个文件 一、本期进展 这一期的主线只有一件事:把「视野」这件事从头重做一遍。 围绕它牵出了一连串问题——阶段错乱、渲染预算、特效不跟随、性能卡顿。 下面按「主线 → 连带修复 → 工程债」的顺序说。 1. 视野重构:从「按玩家体型」到「固定广阔」 起点:用户反馈
官方
1 赞
《变成黑洞》开发日志
日期:2026-10-22 代码规模:13821 行 / 20 个文件(RenderEvolutionGiant.lua 920 → 954) 一、本期主线:把「能跑通」变成「说得清」 上一期把重复实现收敛掉了。这一期暴露的是另一类问题: 代码能跑,但跑出来的东西经不起一句追问。 每阶都是 20 口 —— 「碎石和红巨星凭什么一个节奏?」 黑洞吃 2000 口只长 4% —— 「那通关是怎么通的?
官方
《变成黑洞》开发日志
日期:2026-10-19 本期构建序号:57 → 101(共 45 次构建) 代码规模:9068 行 / 14 个文件 一、本期进展 这一期的主线是把「引力」从数值表里真正做出来。 上一期把视野固定下来之后,引力第一次变成了「看得见、摸得着」的东西—— 也就第一次暴露出它在物理上一直是错的。 1. 引力的两处根本错误 用户提了两个问题,都指向同一个地方: ①「碎石都不受引力影响,那你其他引力正不
官方
1 赞