角色为何穿墙?5大陷墙原因全解析
2026/8/20 5:04:22 网站建设 项目流程

上一篇讲解穿透,开头我甩了几句"移动平台挤、传送重生、数值边界"就带过了成因,重点放在怎么把角色顶出来。有读者留言问,移动逻辑我写得挺仔细的,sweep 检测也做了,角色到底怎么还会陷进墙里?

这问题问得好。因为你要是不理解它怎么陷进去的,解穿透那套兜底逻辑你就只是照抄,遇到具体的穿模 bug 还是两眼一抹黑。这篇就专门把"陷进墙"这件事扒开,一个个来源讲清楚。搞明白了,你才知道解穿透到底在给谁擦屁股。

先立个前提:sweep 只防"移动中撞墙"

要理解角色怎么陷进去,得先明白你的 sweep 检测到底防的是什么。

Collide-and-Slide 里的 sweep,检测的是"角色从 A 点移动到 B 点,这一路上撞不撞得到东西"。它是沿着运动轨迹扫描的。这意味着它有两个隐含前提:

一是角色得主动在动。sweep 是由角色的位移触发的,你不动,它就没有轨迹可扫。

二是起点 A 得是干净的。sweep 假设你出发时没跟任何东西重叠,它只负责这段路。

几乎所有"陷进墙"的情况,都是因为打破了这两个前提中的某一个。要么角色不是主动撞的墙(墙来撞它),要么起点本来就脏。下面挨个看。

来源一:墙主动来撞你(移动平台)

这是最经典的一类。玩家站着不动,或者慢慢走,一块移动平台——电梯、升降台、传送带、机关门——朝他挤过来。

问题就出在,sweep 是由角色的位移触发的。平台在动,角色没动(或者动得慢),角色这一帧的位移很小甚至为零,它的 sweep 扫出来的轨迹也就一丁点,根本覆盖不到平台冲过来的那段距离。

第 N 帧: 第 N+1 帧: ● 角色站着 ████ 平台挤过来了 ● 角色纹丝没动, ████ 平台在这 但已经被平台包住 → 平台朝角色移动 角色 sweep 位移≈0, 压根没检测到平台

角色的检测逻辑心想"我这帧没怎么动,前方也没主动撞上啥",于是啥也没做。可平台不管这个,它自顾自地移动,把角色整个吞进去了。等下一帧一看,角色中心已经在平台内部——陷进去了。

这就是为什么有移动平台的场景,解穿透几乎是刚需。平台的运动和角色的检测是两套独立的东西,角色的 sweep 管不了别人主动往自己身上撞。

来源二:位置被"啪"地设过去(传送、重生、拉拽)

第二类是位置瞬移,不走移动逻辑。

正常移动是"算出速度,sweep 检测,滑动,更新位置",一整套流程,中间有碰撞把关。但游戏里大量的位置变更是绕过这套流程的,直接把坐标赋值过去:

玩家死亡后重生,pos = spawnPoint,啪,设过去了。

被钩爪、被技能拉拽、被爆炸击飞到某个点,pos = targetPoint

场景切换、剧情演出把角色摆到指定位置。

这些操作里,落点是策划配的或者技能算的,谁也不保证那个点一定在空地上。重生点可能被临时生成的物件占了,拉拽的终点可能正好嵌在墙里,击飞的落点可能穿进了地板。因为是直接赋值,中间没有任何 sweep 拦一下,角色"唰"地就出现在几何体内部了。

这类穿透和运动完全无关,纯粹是"落点没校验"。解穿透在这里的作用就是:不管你被啪到哪,只要陷进去了,我下一帧立刻把你顶到最近的空地。

来源三:多个碰撞体夹击,滑动解不干净

第三类是角色被夹住。

上一篇讲滑动,提到墙角、V 字夹缝这种地方,滑动会撞满MAX_SLIDE次数上限然后放弃,剩下的位移不走了。这是防死循环的必要妥协,但代价是——放弃的那一刻,角色可能正贴着两面墙,残留一点点重叠没解干净。

墙 A ██ ██ ●← 角色被 A、B 两面墙夹在角落 ████████ 滑向 A 就撞 B,滑向 B 就撞 A 墙 B 滑动次数用完,残留一丝重叠

单帧这点重叠很小,不处理也不明显。但如果玩家持续往墙角里顶(比如按着前进键怼墙角),这点重叠会一帧帧累积、被移动逻辑反复放大,慢慢就陷进去了。

还有相向挤压的情况:两块移动平台从两边同时夹过来,或者一面移动的墙把角色压向一面固定的墙。角色被两个约束同时拉扯,滑动这种"沿单一表面走"的逻辑根本处理不了双向挤压,只能靠解穿透去反复顶。

来源四:数值边界和 sweep 自身的精度

第四类比较底层,是检测本身留下的残渣。

sweep 检测算的是"角色形状沿轨迹移动,第一次碰到表面是在哪个点"。理想情况它让角色停在刚好贴着表面的位置——不重叠,也不留缝。但"刚好贴着"这件事,在离散的数值世界里很难做到分毫不差。

擦着表面走、贴着墙角拐、高速移动一帧跨过很大距离,这些情况下 sweep 算出的停靠点可能带一点点误差,让角色停在了"陷进去一丁点"的位置。单帧这点误差微不足道,但它是个种子——下一帧移动从这个"已经陷进去一点"的脏起点出发,又违反了"起点得干净"的前提,误差被放大,滚雪球。

这也是为什么上一篇讲解穿透时要留一层 skin width(皮肤厚度)。让角色始终"贴着但不压进"表面,留一层薄缓冲,就是为了给 sweep 的精度误差留余地,不让角色真的压到表面上去积累这种残渣。

来源五:几何体自己变了

最后一类容易被忽略:角色没动、也没被挤,是环境变了。

可破坏的墙被炸开又生成、机关门关闭、场景里动态刷出一块几何体、平台旋转扫过角色所在的位置。这些情况下,是碰撞几何在角色脚下(或身上)发生了变化,角色原本站的干净位置,突然就变成了几何体内部。

角色压根没机会检测——它上一帧还站在空地上,这一帧空地变成了实体。这跟移动平台是一类问题(环境主动改变角色的处境),但触发方式更隐蔽,因为连"有东西朝我移动"都没有,是几何体凭空出现在了原地。

归纳:两条主线

五个来源看着杂,其实归到那两个前提上就清楚了:

违反"角色主动在动"这条的:移动平台、相向挤压、几何体变化——共同点是角色被动挨撞,不是它自己撞上去的,sweep 由角色位移触发,它管不了别人往自己身上撞。

违反"起点干净"这条的:传送重生落点没校验、滑动残留、sweep 精度残渣——共同点是角色某一帧的起始位置就已经脏了,后续移动在脏起点上继续,越陷越深。

理解了这两条主线,你就明白解穿透为什么是兜底而不是主逻辑:它不负责预防穿透(那是移动逻辑和落点校验的事),它负责的是"预防没做到、或者根本没法预防"的那些情况,每帧开头擦一遍,保证不管角色以什么离谱方式陷进去,都能被顶回合法位置。

一个实践建议:别指望预防,老实兜底

新手常有个误区,想把穿透"从源头彻底堵死"——把 sweep 做得无比精细、把每个传送落点都校验、把移动平台也做 sweep。这条路走不通,成本极高还堵不干净,因为像"几何体凭空变化"这种情况你根本没法在移动侧预防。

大厂的思路是反过来的:承认穿透必然会发生,与其耗尽力气去预防每一种,不如做一个稳健的解穿透兜底,每帧无脑擦一遍。预防做到八九成够用就行,剩下的一两成交给兜底。这样代码简单、行为可预测,而且因为解穿透是定点的、逐比特一致的,客户端和服务器擦出来的结果还完全一样,不会因为"这台机器预防住了那台没预防住"而分叉。

预防是尽力而为,兜底是万无一失——这个分工想清楚了,穿模这类 bug 才不会没完没了。

收尾

角色怎么会陷进墙?根子上就两句话:要么它是被动挨撞的(墙、平台、变化的几何体主动往它身上招呼,而 sweep 只由角色自己的位移触发,防不住),要么它的起点本来就脏了(传送落点没校验、滑动残留、检测精度残渣,让后续移动在错误的位置上滚雪球)。

sweep 检测防的是"我主动移动时撞不撞墙",它有清晰的能力边界。边界之外的所有情况——被挤、被传送、被夹、被环境改变——都会让角色陷进去,而这些恰恰是解穿透存在的理由。搞清楚它在给谁擦屁股,你写解穿透才不是照抄,遇到具体穿模才知道该往哪查。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询