先声明一个前提:下面讨论中出现的“10P / 12P / 1P / 2P”在不同版本的 MUGEN 人物包里含义并不完全一致。有些作者用 P 数表示第几套配色,有些作者把 P 数当 AI 强度或技能脚本版本的开关。本文不会去猜拉莱耶人物包的作者意图,而是使用 MUGEN 人物调试的通用思路,把“某个 P 数在 P1 位置上能打出演出杀伤,换到 P2 位置或换边后失效”这一类问题拆开讲清楚。
如果你正在改演出型人物,或者手里的像素人物经常出一些“站左边就正常,站右边就哑火”的怪问题,这篇排查思路应该能省下不少时间。
1. 先定位:这个 Bug 到底发生在哪一层
遇到“打不中、杀不死、换边失效”,第一步不是翻检测代码,而是先判断失效发生在哪个阶段。MUGEN 里一个演出技从按下到击败对手,至少要经过四个层次:
| 层次 | 负责内容 | 失效表现 |
|---|---|---|
| 触发层 | 是否满足出招条件、是否进入对应状态 | 招式完全不出现 |
| 命中层 | HitDef 是否产生有效判定并命中对手 | 看见攻击动作,但对方不掉血 |
| 演出层 | Helper、Explod、ChangeAnim 等是否按预期播放 | 特效出现在错误位置或直接找不到 |
| 结算层 | 是否把对方打进必死状态、是否造成击杀 | 命中有效但对方“锁血”不死 |
回看标题里描述的现象,核心矛盾其实集中在“隔离检测”和“演出杀伤”。所谓隔离检测,在 MUGEN 人物的状态机里并不是一个官方触发器,更像是人物作者自己定义的一串前置条件,比如先检测目标是否孤立、目标是否处于某个能被演出捕获的状态、双方距离是否满足等等。
因此,建议把“隔离检测”理解成一个由多个 trigger、VarSet、ChangeState 组合出来的判断链。这类判断链只要有一个条件带了左右坐标假设,就会表现成“P1 能用、P2 失效”;只要有一个变量在换边后没有重置,就会表现成“第一局还能用,第二局换位置后彻底沉默”。
这类问题通常不是 MUGEN 引擎随机出错,而是人物状态机里隐藏了不对称逻辑。
2. MUGEN 的 10P、12P 到底意味着什么
MUGEN 的 P 数最早来自角色配色。一个 .def 文件里会写 pal1、pal2,直到 pal10、pal12,每一行指向一套 .act 调色板。正常情况下,玩家在选人界面按左右键,会切换配色编号,但这并不会改变战斗逻辑。
问题在于,很多人物的后续修改版并不老老实实只换颜色。部分作者会在 .cns 里通过当前 P 数来设置不同的 AI 难度或技能文本分支。例如:
; 示意,不代表拉莱耶原版 [State -2, P Number AI Switch] type = VarSet trigger1 = var(0) = 0 var(59) = floor(palno / 2)如果 10P 和 12P 的区别不只是颜色,而是它们启动了不同的 AI 分支,就会导致两个 P 数进入“隔离检测”状态的条件完全不同。
排查时可以按下面的顺序做一次差异检查:
diff 拉莱耶_10P.cns 拉莱耶_12P.cns diff 拉莱耶_10P.st 拉莱耶_12P.st diff 拉莱耶_10P.txt 拉莱耶_12P.txt如果两个文件的差异集中在 var 初始值、AI 等级、触发阈值这些位置,那问题重点应该放在“为什么这个分支在 P2 位置不成立”。如果 diff 后完全一样,那么建议不要纠结 10P 和 12P 的差异,先把它们当作同一个逻辑版本处理,直接检查 P1、P2 和换边问题。
判断依据也很简单:P 色本身不会让一个角色只在左边能杀人。会改变战斗表现的,一定是某个分支条件读到了 palno,或者 var 数值不一致,让同一条路径只在某个 P 色下成立。
3. 核心概念:facing、坐标符号与自动转向的误区
MUGEN 与传统格斗游戏一样,两个人默认站在屏幕两侧对战。但如果写状态机时以为“P1 一定在左、P2 一定在右”,就会无意间写出一堆只对一边生效的代码。
MUGEN 玩家“换位置”是非常常见的,比如跳逆向、瞬移、投技换边、强制换位演出,都会让双方的屏幕坐标关系发生变化。此时,人物自身的facing会变成 1 或 -1,表示当前朝向哪边。大多数动画会自动翻转,但代码里的坐标计算并不会自动翻转。
最容易出问题的写法是直接判断对手在左边还是右边:
; 错误示范:默认对手在右边才触发 [State 3100, 只向右打] type = HitDef trigger1 = p2bodydist X > 0 attr = S, NA damage = 100 p1stateno = 3200 p2stateno = 3300当该角色站在 P1 初始位置时,对手通常在其右侧,p2bodydist X > 0很容易成立。把这个角色放到 P2 位置后,对手在左侧,p2bodydist X变成负数,这个 HitDef 就永远不触发。由于 MUGEN 中不同的 P1、P2 初始坐标是天然相反的,这种看起来“没什么问题”的简写,正是“P1 能杀人、P2 杀不了人”的最常见来源。
正确写法应该使用绝对值,不关心敌人在左侧还是右侧:
; 推荐写法:只要距离足够近就触发 [State 3100, 双向触发] type = HitDef trigger1 = abs(p2bodydist X) < 90 attr = S, NA damage = 100 p1stateno = 3200 p2stateno = 3300如果担心 p2bodydist 的符号受自己版本影响,可以先用 DisplayToClipboard 或 MUGEN 的调试输出把如下信息打出来观察:
p2bodydist X = 实际有符号距离 facing = 当前朝向 abs(p2bodydist X) = 无视方向的直线距离不要相信肉眼猜测,只要把有符号距离和 facing 打印到屏幕上,立刻就能看出代码是从什么时候开始左右不对称的。
4. “隔离检测演出杀伤”为什么容易受换边影响
现在把“隔离检测演出杀伤”拆成三个连续阶段来理解。
第一个阶段是检测。人物需要确认当前场景中存在目标、目标没有被其他状态保护、目标与自己的距离合适,并且当前已经满足进入“演出模式”的条件。第二个阶段是命中。此时 HitDef 要正常生效,把目标拉入专属的 p2stateno,开始播放受击演出。第三个阶段是演出击杀。常见做法是创建大量 Helper 或 Explod,播放一段华丽演出,并在演出结束时让目标进入无敌或不可恢复的死亡状态。
这三个阶段各自对“换边”的敏感度完全不同。
检测阶段最容易出错的地方是距离判断。如果你写的判定是p2bodydist X > 120,那它在换位置前后会得到完全不同的布尔结果。命中阶段最容易出错的地方是面向。很多演出技在命中后会把对手拖到固定坐标,但如果 HitDef 的p2stateno目标状态里没有重新让双方面对面,就会出现“模型明明在面前,判定却往身后飞”的诡异现象。演出阶段最容易出错的地方则是 Helper 和 Explod 的坐标。
以演出型角色常见的“召唤一个超出屏幕的巨物”为例,如果 Helper 的 pos 写成了固定屏幕坐标:
; 不推荐:死死贴在屏幕左侧 [State 4000, 位置写死] type = Helper trigger1 = Time = 0 helpertype = normal name = "RlyehShow" ID = 4500 pos = 300, -200 postype = left stateno = 4510这个 Helper 在正常开局时可能正好出现在对手身后,演出效果看起来很完整。但只要玩家移动到右侧,或者被换到 P2 侧,这个写死的 300 坐标就会把演出特效放到完全错误的方向。修复方向是让 pos 参考当前朝向:
; 推荐:根据 facing 决定前后方向 [State 4000, 跟随朝向] type = Helper trigger1 = Time = 0 helpertype = normal name = "RlyehShow" ID = 4500 pos = 200 * facing, -120 postype = p1 facing = facing stateno = 4510这样无论人物站在左边还是右边,Helper 始终会生成在人物“前方”的演出位置。
很多人看演出型角色代码时会误以为“反正 HitDef 会自动跟踪对手,演出就随便摆”。真实情况是:HitDef 是否跟踪对手由引擎决定,但演出用的 Helper、Explod、ChangeAnim 都是需要人物作者手动维护朝向的独立对象。只要有一个位置写死,整个演出就会在一边正常、一边错位。
5. 一步步复现:固定 P 数和固定位置分别测试
在改代码之前,先做一组干净的复现实验。这组实验能把问题从“偶尔出现”变成“稳定出现”,后面修起来才有依据。
第一步,固定 P 数。使用拉莱耶 10P 分别在 1P 位置和 2P 位置各打三局,如果 10P 在 1P 能出演出技,在 2P 不能出,则问题与 P 数无关,直接指向 P1/P2 的不对称代码。再用 12P 在 1P 位置测试。
第二步,固定位置。让拉莱耶 10P 一直站在 P1,但使用角色后跳、瞬移、投技或后台切换,让它和对手交换屏幕位置。如果第一局能做到,换边后做不到,则问题不是单纯 P1/P2 问题,而是换边后的 facing 或坐标关系变化导致状态机路径不稳定。
第三步,做一次“隔离检测减法”。把演出技的前置条件全部删掉,只留一个最朴素的 HitDef,例如 3000 号状态必须命中。如果这个最小 HitDef 在 P2 位置依然能命中并造成伤害,说明触发层和命中层本身是通的,问题出在更复杂的隔离检测条件上。
; 最小复现:不要演出,只测命中 [Statedef 3200] type = S movetype = A physics = S ctrl = 0 anim = 3200 [State 3200, 简单命中] type = HitDef trigger1 = Time = 3 attr = S, NA hitflag = MA damage = 100 getpower = 0 givepower = 0 p1stateno = 3210 p2stateno = 3220 fall = 1如果这个最小命中在 P1 有效、P2 无效,那就不要浪费时间检查演出部分,问题必然在更入底层的触发条件里。如果这个最小命中两边都有效,再逐步把“隔离检测限制条件”加回去,每次只加一个 trigger,直到找到让 P2 失效的那一个条件。
这组测试的结论需要记录下来:是位置相关、P 数相关,还是 facing 相关。
6. 寻找编码错误:常见不对称逻辑
经过第 5 节的小步测试后,多数人会找到一两处可疑 trigger。下面列出演出型人物最常见的几类不对称逻辑,可以作为排查清单来对比。
第一类是距离方向写死。p2bodydist X > 0、pos X > 0、enemy, pos X > 0这类判断都属于有符号坐标依赖。它们在一侧会因为成立而