MUGEN 角色调试中最让人头疼的往往不是单帧连接难接而是同一份角色文件在 1P 位置表现正常换到 2P 之后触发判断完全错乱。最近排查“拉莱耶文本10P”和“拉莱耶文本12P”这类多版本资源时现象和标题描述很像拉莱耶文本10P 作为 1P 时可以通过先手隔离检测演出杀伤正常完成对战流程拉莱耶文本12P 作为 2P 时隔离检测杀伤无法击败对手把 10P 从 1P 换到另一边后先手检测也会因为换位而变得不稳定。这类问题在 MUGEN 里非常典型。它和角色强度、资源命名、AI 等级都没有必然关系更多是角色状态文件里写满了“方向相关触发条件”的结果。MUGEN 坐标系和玩家面朝方向并不是代码里想的那么直接。下面我会从换边失效的常见原因入手给出一套适合 MUGEN 角色制作者和资源修复者使用的排查流程。这里的“隔离检测”“演出杀伤”后续当作某个人物补丁中的自定义判定流程来理解它不是 MUGEN 引擎标准功能而是角色文件夹内用状态机实现的一套逻辑。1. 先弄清楚换边之后MUGEN 的坐标和朝向发生了什么变化1.1 10P、12P 这类名字只是资源版本标识真正执行逻辑的是状态机MUGEN 角色文件以.def为入口后续会加载.cns、.air、.cmd等资源。玩家常说的“10P”“12P”可能是同一角色补丁的不同版本也可能只是不同配色或不同 AI 强度的.def入口。无论资源怎么命名进入战斗后角色一切行为都由状态号和状态控制器决定。如果一个 10P 文本在 1P 位置能触发“隔离检测演出杀伤”而 12P 文本在 2P 位置不能最简单的排查思路是先确认两份角色定义文件确实加载了同一套检测逻辑。很多补丁会用不同 def 文件引入不同 AI 难度或不同攻击判定参数两份文件的差异可能并不是左右方向问题。建议先做一次文件对比。把要测试的 def、cns、cmd、air 分别放在一个干净目录里用文本对比工具逐条看差异。重点看状态号、触发条件、HitDef 参数、攻击框定义、Var 变量初始值这几类内容。如果两份文件差异很小问题更容易集中在方向或者距离判断上。1.2 P1/P2 不是简单的舞台镜像关系MUGEN 战斗初始布局是 1P 在左侧2P 在右侧。1P 默认面朝右2P 默认面朝左。这是很多第一次接触 MUGEN 角色开发的人容易忽略的坐标值不是“谁在左边就为负谁在右边就为正”这么简单具体正负还和玩家面朝方向、玩家相对位置有关。在 MUGEN 触发器里P2Dist X这类参数通常表示两个角色在水平方向上的距离并且是带符号的。x 轴向右为正方向。也就是说如果 P2 在整个舞台的右侧那么从 P1 坐标看向 P2 时距离可能是正数如果换边之后P2 在左侧同样的距离就可能变成负数。问题在于角色脚本并不会因为玩家从 1P 换到 2P 就自动把你写好的P2Dist X 0翻译成“检测敌方在身前”。简单说写“敌人在右侧”很容易写“敌人在我面前”需要额外结合Facing。很多换边失效就发生在这一步。10P 恰好站在 1P 时代码里所有“右侧”判断都成立但换到 2P 后敌方在左侧于是同样一套代码不再触发。1.3 “隔离检测演出杀伤”从工程角度可以拆成三块原文里的“隔离检测”很像是为某个表演型连段单独做的一组触发判断。“演出杀伤”可以理解为一套比较固定的连段或一击流程目的是让角色在特定条件下稳定击杀对手。从状态机角度它至少包含触发条件判断当前双方距离、位置、状态、Var 值是否满足进入演出。演出过程通过 ChangeAnim、VelSet、HitDef 等控制器播放一段固定动作并完成攻击。终止处理打完、被防、被击倒、对手死亡或自身被打断后的收尾逻辑。任何一段位置相关的判定错误都可能出现在这三个环节里。比如触发条件判断错了那么演出不会启动动画播放方向和对手实际位置不一致那么 HitDef 虽然出现但无法命中或者演出已经正常启动但因为速度、位移或受击框方向不匹配最后一击落空。从排查角度最好先把这段逻辑理解成一次从“是什么条件进入”到“打中了没有”的链路而不是直接怀疑某个特定伤害数字或动画参数。2. 搭建最小复现环境让同一套流程在左右两侧各跑一遍2.1 准备一个干净的角色测试房间先用普通角色或木桩角色做对手避免其他补丁的 AI 干扰。推荐把被测试角色同时登记为可选角色这样可以用同一个 MUGEN 程序快速切换 1P/2P 位置。在角色调试阶段select.def 中通常只需要让两个被测角色都出现在列表里。常见结构大致如下具体格式要看你使用的主程序或 screenpack 版本[Characters] chars/rlyeh10/rlyeh10.def chars/rlyeh12/rlyeh12.def chars/dummy/dummy.def这一步的关键不是配置文件格式本身而是保证你能够在选人界面快速做到1P 选择拉莱耶文本10P2P 选择普通对手或拉莱耶文本12P。1P 在左2P 在右执行一次先手隔离检测演出杀伤。把两个角色的先后顺序换过来再执行一次。如果资源支持队伍模式或模拟换边也可以直接用“交换玩家位置”的测试方式。前提是不要改变被测角色自身状态文件。2.2 记录现象时不要只看“能不能杀死”“能触发”和“能命中”是两个不同阶段。很多角色在 2P 位置失效时其实演出已经启动了只是 HitDef 的攻击框没有出现在正确方向。因此复现记录表格至少要区分以下四列是否成功进入目标状态是否能播放目标动画是否发出有效 HitDef是否能击败对手用一张表格记录会更清楚测试组合位置是否进入演出状态是否出现攻击判定是否完成击杀拉莱耶文本10P 打 普通对手1P 左是是是拉莱耶文本10P 打 普通对手2P 右有时否否拉莱耶文本12P 打 拉莱耶文本10P1P 左是是是拉莱耶文本12P 打 拉莱耶文本10P2P 右是否否如果记录结果出现“能进入但不能击杀”那说明问题不一定在 AI 是否触发而在方向、距离、动画、攻击框这些后续环节。2.3 使用调试面板查看关键数值MUGEN 自带调试信息可以帮助确认角色当前状态号、状态类型、移动量等基础信息。很多整合版主程序会在开启 debug 模式后显示当前状态号和动画号。如果你没有独立调试面板至少可以通过在 CNS 中写 VarSet 的方式把关键信息打印到自定义状态或 Helpers 上。这里要强调测试环境不需要加载一堆自制特效和其他逆天角色越接近原始 MUGEN 越容易定位方向 bug。生产补丁、展示录像、正式整包发布的场景另外再单独验证。3. 换边失效的三个主要代码原因3.1 用舞台全局坐标判断“前方”导致右侧专属生效这是最典型的换边失效原因。假设角色代码某一段写成[State 3000, CheckRightSide] type ChangeState triggerall StateNo 200 triggerall P2Dist X 0 triggerall P2Dist X 160 trigger1 command startSpecial value 3000这段逻辑在 1P 于左侧、P2 在右侧时是成立的。因为P2Dist X是正数敌人距离又处于 160 以内。但如果角色换到 2PP2Dist X 的符号会反过来于是触发条件不再满足。更隐蔽的是当双方擦身而过后P2Dist X 可能在某个瞬间小于等于 160但此时敌人已经越过角色身后触发条件依然成立只是角色面向错了。稳妥的做法是不要直接判断P2Dist X 0而是先用Facing把左右方向归一化成“前方/后方”。例如[State 3000, CheckFront] type ChangeState triggerall StateNo 200 triggerall P2Dist X * Facing 0 trigger1 abs(P2Dist X) 160 trigger1 var(0) 0 value 3000Facing是角色当前朝向通常取值 1 或 -1。P2Dist X * Facing为正时说明敌人在角色面朝方向的那一侧。abs(P2Dist X)再用来限制距离就不会写死“必须位于舞台右侧”。3.2 距离触发没有配合“身前/身后”的条件另一类常见问题是不做方向判断只写距离。比如trigger1 abs(P2Dist X) 200看起来这个条件在左右两侧都成立但其实它没有区分敌人是在角色面前还是身后。当角色面向右、敌人从身后接近时abs(P2Dist X)也会小于 200如果你的命令触发恰好满足角色就会在对敌方向错误的情况下进入演出状态。一旦演出把角色往前推而敌人实际在角色身后之后的 HitDef 大概率挥空。“隔离检测”这类逻辑如果写得非常严格通常会同时检查敌人状态类型敌人距离是否位于角色身前双方是否处于地面角色自身状态某个启用开关变量是否为 1任何一个条件只用绝对值而丢掉了方向都可能造成换边后失效。建议把“是否在身前”单独提取为一个变量不要在每个触发里都重写一次。3.3 进入演出状态后没有修正移动和转向也有一种情况是触发正常、状态号进入正常但状态内部使用了固定方向的速度或者固定坐标的受击框。比如[State 3000, MoveForward] type VelSet trigger1 AnimElem 2 x 6如果角色在左侧面朝右这个速度是向敌人方向移动如果角色在右侧面朝左x 为正值反而会让角色进一步远离敌人。类似问题也会出现在 HitDef 的sparkxy、hitvelx、推砖偏移等参数上很多与方向有关的偏移值都需要根据Facing或攻击框方向自动适配。如果你发现“演出能进入但打不中”要优先检查状态内部的位移值和攻击框偏移。这类问题通常表现如下现象常见原因演出触发角色朝错误方向移动VelSet 或 VelAdd 使用固定正负号HitDef 有攻击帧但是打不中攻击框位置写成绝对坐标或未随 Facing 变化在 1P 位置使用正常2P 位置先手失败触发条件里使用 P2Dist X 0 等左右限定换边后检测条件总在最后一刻改变未在状态前更新身前/身后的 Var 标志4. 把“隔离检测演出杀伤”拆成四层逐层定位失效点4.1 第一层确认是否进入目标状态号给被测试角色的-2状态加一个临时变量监控比如定义 var(59) 记录自己是否处于目标演出状态。使用通用片段说明[State -2, DebugFlag] type VarSet trigger1 1 var(59) ifElse(StateNo 3000, 1, ifElse(StateNo 3001, 1, 0))然后在测试时观察角色是否进入 3000 或 3001。如果进入说明触发链是通的如果没有进入问题还在外侧的 ChangeState 触发条件。这一步不要直接去改伤害或 HitDef。先确认状态入口是否正常。4.2 第二层确认演出过程是否完整播放进入目标状态后观察动画是否正常播放到攻击帧。通常演出型状态会做类似下面这样[StateDef 3000] type S movetype A physics S juggle 4 ctrl 0 velset 0,0 [State 3000, Anim] type ChangeAnim trigger1 AnimTime 0 value 3000 [State 3000, HitDef] type HitDef trigger1 AnimElem 2 attr S, SA damage 100, 10 hitflag MA guardflag MA animtype Hard priority 4, Hit这里的 HitDef 只是示例。实际角色补丁里的攻击参数会比这个复杂它可能还带着sparkno、hitsound、guardsound、getpower、givepower、p2getp2state等参数。排查时先去掉这些附加效果只保留一个最小 HitDef确认攻击框能否在左右两侧都正常出现。如果演出过程中存在位移建议暂时把 VelSet 去掉。这样可以区分“是触发方向问题”还是“是移动造成的间距问题”。4.3 第三层确认 HitDef 方向、攻击框和受击框进入 3000 状态攻击帧播放后仍然不能命中你需要在调试状态前看清楚目标攻击框的偏移。很多角色的攻击框并不是从轴心直接生成而是写成了[State 3000, HitDef] type HitDef trigger1 AnimElem 3 sparkxy 5, -80这个偏移是否随 Facing 自动翻转取决于 MUGEN 版本和状态定义。如果不自动翻转那么角色面向左时火花和攻击框仍会出现在面向右的一侧。判断方法非常简单把 MUGEN 的 debug 攻击框显示打开看 1P 位置和 2P 位置下动画第 3 帧的攻击框分别出现在哪个方向。如果攻击框出现在角色身后问题就在攻击框偏移上。4.4 第四层隔离“杀伤”本身而不是隔离“检测”如果状态触发正常、HitDef 攻击框也正常但换边后仍然无法击败对手就要检查“击杀”是否依赖了额外的变量或生命值比较条件。有些演出型角色会在最后一击前判断对手生命值trigger1 Enemy, Life 100这个条件在 1P 位置成立不代表换到 2P 位置后一定成立。因为对手不同、被攻击次数不同、变量记录不同都会影响进入结果。不要因为有特殊演出动画就把击杀条件固定成某个单一阈值。正确的做法是先移掉这类击杀限制让普通 HitDef 完整命中确认角色基础伤害能击杀。之后再把“演出”条件加回来判断是否某个变量在换边后没有被正确赋值。5. 一种稳定的换边兼容写法把“前方距离”统一成运行时变量5.1 在每帧更新身前标志和水平距离不建议在每个状态里都重写一遍方向和距离判断这样后期维护非常痛苦。更合适的方式是在-2或-3状态里统一计算一份“运行时方向数据”。例如[State -2, UpdateFrontFlag] type VarSet trigger1 1 var(10) ifElse(P2Dist X * Facing 0, 1, 0) [State -2, UpdateFrontDist] type VarSet trigger1 1 var(11) abs(P2Dist X)var(10) 表示敌人在角色面朝方向的一侧为 1 表示在前方。var(11) 表示双方绝对水平距离。这样后续所有演出触发都可以写成统一风格[State 3000, EnterKillCondition] type ChangeState triggerall var(10) 1 triggerall var(11) 160 triggerall StateNo 200 trigger1 var(30) 1 value 3000这里 var(11) 在没有敌人时可能不是有效数字所以在triggerall前最好先保证NumEnemy条件为真。不同 MUGEN 版本对触发器空值处理有差异生产补丁里不能指望某个触发永远可用。5.2 左右对称模板和排查表下面是一组用于自查的对照表。它不引导你直接照抄参数而是提供一个筛问题方向检查项错误表现推荐处理P2Dist X 判定只适合单侧加 Facing 归一化距离使用没有配合身前标志用 var(10) 区分身前身后状态内位移使用固定速度正负根据 Facing 计算移动方向HitDef 偏移火花和攻击框反向检查偏移框是否随 Facing 翻转击杀条件换边后变量未更新在状态进入前统一更新变量常见修复模板[State 3000, Move] type VelSet trigger1 AnimElem 2 x 6 * Facing[State 3000, HitSpark] type HitDef trigger1 AnimElem 3 attr S, SA damage 110, 8 sparkxy 10 * Facing, -80当然实际角色补丁不推荐每个 HitDef 都手写10 * Facing。如果引擎版本本身已经支持攻击框偏移自动随面朝方向翻转就不要额外乘 Facing否则会得到双倍翻转。这里的关键是在你自己使用的 MUGEN 版本上做一次验证而不是凭经验硬套。5.3 学习环境与最终发布环境要分开处理调试阶段可以直接修改.cns文件并在 MUGEN 内重启测试。最终发布时还应该注意以下几点是否把调试用 Var 监视写进了正式状态文件是否把测试用随机触发或无条件触发残留是否因为换边修正而破坏了原来 1P 位置的手感是否在两个角色补丁之间复制代码时遗忘了版本差异是否保留了备份便于回滚这些内容不属于 MUGEN 的玩法逻辑但往往决定一个修复方案能否真正交付。很多补丁最后坏掉不是坏在方向判断思路而是坏在