捉虫(Bug)小记

本文简述了自己查找定位 Bug 过程中的一点思考

某日发现游戏(UE5)项目中出现了一个 Bug,表现大概是这样的:

怪物可以正常在地面上移动,但是在死亡时却会'诡异'的从地面上掉下去 ...

自己对于游戏项目的逻辑不是特别熟悉,大概跟踪了一下相关代码,发现怪物死亡时大体会走下面的逻辑流程:

  • 首先开启怪物模型(Mesh)的物理碰撞
    • SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics)
  • 接着调整怪物模型(Mesh)的碰撞响应
    • SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block)
  • 最后开启怪物模型(Mesh)的物理模拟
    • SetSimulatePhysics(true)

逻辑看上去还是挺完备的,似乎没有什么问题,但是几轮验证下来,确认只要关闭了上述逻辑,怪物的坠落问题就不存在了,所以一定是物理模拟引起了问题,但是问题究竟出在哪里呢 ? 一度让人费解 ...

好在这个 Bug 是可重现的(以我的经验,一般可重现的 Bug 都是能最终追溯到原因的,只是花费的时间长短不同),初步判断原因应该还是出在物理碰撞上,只是 UE 的碰撞处理相对复杂,跟踪物理碰撞的问题确实要花不少精力.

总之经历了多轮的 猜测验证, AI辅助, 断点调试 等操作,最终还是发现了问题点:

  • SetShapeCollisionEnabled

你可能会有些疑惑,上述的逻辑流程中并没有什么 'SetShapeCollisionEnabled' 的调用,问题怎么会出在这个接口上呢 ?

原来在怪物初始化时,项目逻辑会对碰撞 Shape 调用 'SetShapeCollisionEnabled' 来与 怪物模型(Mesh) 本身的 CollisionEnabled 做同步,而怪物模型(Mesh)本身的 CollisionEnabled 是 ECollisionEnabled::QueryOnly,这就导致碰撞 Shape 的 CollisionEnabled 也变为了 ECollisionEnabled::QueryOnly.

接着当怪物死亡处理物理碰撞时,逻辑虽然会设置 怪物模型(Mesh) 的 CollisionEnabled 为 ECollisionEnabled::QueryAndPhysics,但是碰撞 Shape 的 CollisionEnabled 依然还是初始化时设置的 ECollisionEnabled::QueryOnly,而 UE 在处理碰撞 Shape(碰撞 Shape 参与实际的物理碰撞检测)最终的 CollisionEnabled 时做了"最小化"处理(即取 怪物模型(Mesh) 本身的 CollisionEnabled 和 碰撞 Shape 的 CollisionEnabled 的最小值),继而会取 碰撞 Shape 的 CollisionEnabled 为 ECollisionEnabled::QueryOnly,即碰撞 Shape 不参与物理模拟,于是就出现了前面所说的怪物坠落问题 ...

上述流程可能说的有些繁复,但是流程本身并不是重点,不太理解的朋友不必过多关注,我们进一步要问的是,出现这个 Bug 的根本原因在哪里 ? 有没有可能避免 ?

个人认为出现这个 Bug 的根本原因还是在于细节不明 ,一般而言,在 UE 的碰撞处理上,游戏逻辑其实是不太需要去主动调用 SetShapeCollisionEnabled 的,保持默认设置即可,但是项目在怪物初始化阶段,因为细节不明 ,主动调用了 SetShapeCollisionEnabled,导致了问题隐患;同时项目在怪物死亡时,因为细节不明,又仅仅设置了 怪物模型(Mesh) 的 CollisionEnabled,而没有去处理碰撞 Shape 的 CollisionEnabled,于是触发了问题.

至于能否避免这类 Bug,个人觉得还是比较困难,除了要求个人对所编写代码尽量了解清晰明确之外(很难保证也很难执行 ...),似乎没有什么好的方法,尤其现在 AI 编码盛行,相关问题可能还会被进一步放大 ...

至此我不禁想起了多年前另一个让我印象深刻的 Bug,这个 Bug 的表现是玩家会在某个多人副本游玩过程中出现'卡死'情况,这里说的'卡死'并不是指玩家死机了,而是指玩家的游戏界面状态会和实际游戏状态不一致,继而导致玩家无法继续游戏,并且这个'卡死'是概率性的,本地测试时极难重现,线上环境也是偶尔重现.

玩家的游戏界面状态不正确,首先想到的自然是客户端是不是处理同步信息不当,但实际上客户端相关代码并不是特别复杂,看上去也没有什么问题;然后考虑是不是服务器没有正确下发同步信息,但实际看下来相关代码也比较正常,再加上 Bug 的偶现性,这个问题就被搁置下来了 ...

问题一搁就搁了好久,直到后来反馈这个问题的玩家越来越多,我们才不得不尝试在相关代码中埋点,外加测试同学不断帮忙复现,最后终于是定位到了问题:

原来在游戏逻辑层面,客户端和服务器的代码其实都没有问题,问题出在服务器给客户端同步数据的接口上,这个接口的内部实现中做了最大同步数量的优化(即一次只能给一定数量的客户端同步),超过最大数量的同步请求会被直接丢弃(并且没有任何日志 ...),于是当游戏中一次同步包含大量玩家的时候,部分玩家就不会收到同步信息,于是便出现了问题(而一般的游戏流程中,基本不会触发上述的接口问题,而出问题的多人副本玩法本身比较特殊,所以容易触发这个问题).

细细想,这个 Bug 其实也可算是 细节不明 造成的 ...


有没有解决之道呢 ? 想想还是如之前所言,没有什么好的方法.可能还是应了那句老话吧 : 软件行业没有银弹,即便在这个 AI 洪流的年代,对于有些问题,我们还是 不可不慎, 不可不察 啊 ~

相关推荐
jooloo3 小时前
Codex 间歇性 400 之谜:一条对话里,它为什么有时候用 chat/completions,有时候切到 responses?
人工智能
用户5191495848453 小时前
OpenSSL PKCS#12 PBMAC1 堆栈缓冲区溢出漏洞 (CVE-2025-11187) 分析与验证
人工智能·aigc
SmalBox3 小时前
【节点】[Polygon节点]原理解析与实际应用
unity3d·游戏开发·图形学
用户5191495848454 小时前
HP Sound Research SECOMNService 权限提升漏洞利用工具
人工智能·aigc
用户018349301695 小时前
给 AI 智能体能力包一层 BFF,前端只调一个接口
人工智能
_zhourui_h_5 小时前
MyFramework:整体代码结构与热更新分层解析
unity3d·游戏开发
这token有力气8 小时前
Function Calling 格式漂移
人工智能
onething3658 小时前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 5 —— SSE 流式输出 + 打字机效果
人工智能·后端·全栈
onething3659 小时前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 6 —— 业务完善 + 会话消息预览
人工智能·后端·全栈
IT_陈寒9 小时前
SpringBoot自动配置的坑,我爬了三天才出来
前端·人工智能·后端