角色来回跑动、原地折返,属于脚本跳转闭环死循环,大多使用GOTO实现坐标移动任务,当到达目标坐标的判定条件永远无法满足,脚本就会不停重复执行移动指令,角色跑到点位识别失败,再次跳转回起点,形成来回跑的现象,严重时M2会报脚本死循环警告,占用大量服务端资源。GOM引擎执行移动命令MOVE、MOVETO之后,不会暂停脚本等待人物走到坐标,脚本会继续向下执行判断,这是产生往返循环最核心的根源。
基础错误脚本逻辑,[@跑A点]#IFCHECKPOS3100100#ACTSENDMSG6已经到达A点GOTO@完成#ELSEACTMOVETO3100100GOTO@跑A点。这段代码的问题是MOVETO发出移动指令后,脚本不会等待人物走完,立刻再次执行GOTO@跑A点,反复检测坐标。如果地图存在墙体、障碍物,人物无法抵达100100,CHECKPOS永远返回假,脚本无限执行MOVETO,角色持续反复尝试移动,出现来回跑或者原地踏步。就算坐标没有障碍物,脚本判断速度快于人物移动速度,也会触发来回折返。
GOM引擎处理移动任务,不能直接使用GOTO无限轮询,优先替换为DELAYGOTO延时跳转,DELAYGOTO可以等待指定秒数之后再跳转标签,给角色留出移动到位的时间,避免脚本瞬间重复判定。改写后的基础框架,[@跑A点]#IFCHECKPOS3100100#ACTSENDMSG6抵达目标坐标GOTO@完成#ELSEACTMOVETO3100100DELAYGOTO2@跑A点。DELAYGOTO2代表等待2秒之后,再回到@跑A点重新检测坐标,2秒的时间供角色移动,不会瞬间循环。GOTO是立刻跳转,DELAYGOTO为延时跳转,写跑动任务时优先选用DELAYGOTO,减少死循环概率。
增加循环计数器,防止永久卡死,设置数字变量记录循环次数,达到上限强制跳出脚本,就算角色卡在障碍物无法到达目标坐标,也不会无限来回跑。脚本示例,[@跑A点]#IFLARGEN110#ACTSENDMSG6多次尝试无法到达目标,任务终止BREAK#ELSEACT#IFCHECKPOS3100100#ACTSENDMSG6抵达目标坐标GOTO@完成#ELSEACTMOVETO3100100INCN11DELAYGOTO2@跑A点。N1作为计数变量,每循环一次N1自增1,循环超过10次,直接终止脚本,结束移动任务。每次开启任务前,增加MOVN10,重置计数器,避免上一轮任务残留变量干扰本次执行。
坐标判定CHECKPOS命令的坑点,CHECKPOS检测是人物所在坐标完全匹配才返回真,角色走到目标坐标旁边一格就判定失败。地图有墙体、台阶、怪物阻挡,角色无法精准踩入目标XY,会一直判定不满足,持续反复跑动。可以改用范围检测,判断人物在目标坐标周边区间,#IFCHECKPOSRANGE31001005,末尾数字5代表5格范围,角色进入目标点5格以内就判定到达,降低卡点判定失败概率。部分地图的坐标存在小数偏移,精确点位很难踩中,大范围检测可以解决绝大多数来回折返问题。
地图与人物状态检测,在脚本开头增加判断,角色死亡、被麻痹、处于交易状态时直接终止循环。#IFISDEAD#ACTSENDMSG6角色死亡,停止移动任务BREAK。角色死亡状态下无法移动,不增加这个判断,脚本持续发送MOVETO指令,复活之后立刻继续循环跑动。增加地图检测,#IFNOTCHECKMAPNAME地图名称#ACTSENDMSG6当前不在目标地图,任务结束BREAK,角色被传送离开目标地图之后,脚本停止循环,不会继续原地反复跑。
M2引擎GOTO循环保护参数,打开Mir200目录内!Setup.txt,找到ScriptGotoCountLimit参数,该参数控制单次脚本允许连续GOTO跳转上限,默认数值偏小,快速循环脚本容易直接中断或者报错。不建议单纯增大这个数值,修改参数只能防止M2直接报错,无法解决人物来回跑动的业务逻辑问题,治标不治本。脚本逻辑存在闭环,单纯放大跳转上限,只会让死循环持续更久,提升服务器CPU负载。
标签跳转语法错误,同一个#act内部写两条GOTO,会造成逻辑错乱,#act里面只能保留一条跳转命令,多条GOTO会引发分支混乱。脚本缺少BREAK终止语句,多段#IF判断匹配成功后没有BREAK,脚本继续向下执行其他分支,产生意外跳转。修改脚本完成后,在M2执行重载Quest脚本,旧脚本缓存不会自动更新,修改内容无法生效,依旧保留旧的循环逻辑。
障碍物与寻路问题,MOVETO命令依赖引擎内置寻路,如果目标点位被墙体包围,寻路算法会反复寻找路线,角色出现来回折返。更换点位,选择开阔无遮挡坐标,或者在脚本内增加随机石传送备呀案,多次寻路失败后,使用RANDOMMOVE随机传送,再继续尝试移动。地图的MONSTER、NPC阻挡也会干扰角色移动,怪物堵在目标点位,CHECKPOS判定持续失败,触发循环跑动。
调试定位死循环的方法,在循环脚本内添加SENDMSG输出提示,打印当前坐标和N1变量数值,观察M2窗口日志,查看每一轮循环输出信息,确认是坐标检测不通过,还是变量没有正常递增。注释掉MOVETO移动命令,只保留判定逻辑,单独测试条件判断是否正常,排除寻路带来的干扰。去掉所有延时,分步拆解脚本,先测试单次移动,确认坐标检测正常,再加入循环跳转。
多节点连续跑图任务,每一段点位都独立设置计数器和超时退出,不能把多个坐标点位写在同一个无限GOTO循环内。完成一个点位,重置计数变量,再进入下一段跑动逻辑,一个点位寻路失败,仅终止当前段落,不会卡死整个任务。使用变量标记任务状态,增加状态标识N2,N2=1正在前往A点,N2=2前往B点,依靠状态机切换,而不是单纯GOTO来回跳转,大幅降低死循环风险。
常见故障场景,角色跑到目标附近来回横跳,属于精准坐标CHECKPOS判定过于严格,更换CHECKPOSRANGE范围检测。角色原地不动反复触发移动指令,地图存在墙体阻挡,人物无法移动到目标XY,增加循环计数上限,超时退出。脚本偶尔正常,偶尔来回跑,地图刷新怪物挡住路径,增加怪物检测判断,点位周边怪物数量超标,暂停移动等待怪物清理。重载脚本之后循环依旧存在,检查全局变量残留,N1计数器没有重置,上次任务的变量数值保留,干扰新一轮任务判定。
基础错误脚本逻辑,[@跑A点]#IFCHECKPOS3100100#ACTSENDMSG6已经到达A点GOTO@完成#ELSEACTMOVETO3100100GOTO@跑A点。这段代码的问题是MOVETO发出移动指令后,脚本不会等待人物走完,立刻再次执行GOTO@跑A点,反复检测坐标。如果地图存在墙体、障碍物,人物无法抵达100100,CHECKPOS永远返回假,脚本无限执行MOVETO,角色持续反复尝试移动,出现来回跑或者原地踏步。就算坐标没有障碍物,脚本判断速度快于人物移动速度,也会触发来回折返。
GOM引擎处理移动任务,不能直接使用GOTO无限轮询,优先替换为DELAYGOTO延时跳转,DELAYGOTO可以等待指定秒数之后再跳转标签,给角色留出移动到位的时间,避免脚本瞬间重复判定。改写后的基础框架,[@跑A点]#IFCHECKPOS3100100#ACTSENDMSG6抵达目标坐标GOTO@完成#ELSEACTMOVETO3100100DELAYGOTO2@跑A点。DELAYGOTO2代表等待2秒之后,再回到@跑A点重新检测坐标,2秒的时间供角色移动,不会瞬间循环。GOTO是立刻跳转,DELAYGOTO为延时跳转,写跑动任务时优先选用DELAYGOTO,减少死循环概率。
增加循环计数器,防止永久卡死,设置数字变量记录循环次数,达到上限强制跳出脚本,就算角色卡在障碍物无法到达目标坐标,也不会无限来回跑。脚本示例,[@跑A点]#IFLARGEN110#ACTSENDMSG6多次尝试无法到达目标,任务终止BREAK#ELSEACT#IFCHECKPOS3100100#ACTSENDMSG6抵达目标坐标GOTO@完成#ELSEACTMOVETO3100100INCN11DELAYGOTO2@跑A点。N1作为计数变量,每循环一次N1自增1,循环超过10次,直接终止脚本,结束移动任务。每次开启任务前,增加MOVN10,重置计数器,避免上一轮任务残留变量干扰本次执行。
坐标判定CHECKPOS命令的坑点,CHECKPOS检测是人物所在坐标完全匹配才返回真,角色走到目标坐标旁边一格就判定失败。地图有墙体、台阶、怪物阻挡,角色无法精准踩入目标XY,会一直判定不满足,持续反复跑动。可以改用范围检测,判断人物在目标坐标周边区间,#IFCHECKPOSRANGE31001005,末尾数字5代表5格范围,角色进入目标点5格以内就判定到达,降低卡点判定失败概率。部分地图的坐标存在小数偏移,精确点位很难踩中,大范围检测可以解决绝大多数来回折返问题。
地图与人物状态检测,在脚本开头增加判断,角色死亡、被麻痹、处于交易状态时直接终止循环。#IFISDEAD#ACTSENDMSG6角色死亡,停止移动任务BREAK。角色死亡状态下无法移动,不增加这个判断,脚本持续发送MOVETO指令,复活之后立刻继续循环跑动。增加地图检测,#IFNOTCHECKMAPNAME地图名称#ACTSENDMSG6当前不在目标地图,任务结束BREAK,角色被传送离开目标地图之后,脚本停止循环,不会继续原地反复跑。
M2引擎GOTO循环保护参数,打开Mir200目录内!Setup.txt,找到ScriptGotoCountLimit参数,该参数控制单次脚本允许连续GOTO跳转上限,默认数值偏小,快速循环脚本容易直接中断或者报错。不建议单纯增大这个数值,修改参数只能防止M2直接报错,无法解决人物来回跑动的业务逻辑问题,治标不治本。脚本逻辑存在闭环,单纯放大跳转上限,只会让死循环持续更久,提升服务器CPU负载。
标签跳转语法错误,同一个#act内部写两条GOTO,会造成逻辑错乱,#act里面只能保留一条跳转命令,多条GOTO会引发分支混乱。脚本缺少BREAK终止语句,多段#IF判断匹配成功后没有BREAK,脚本继续向下执行其他分支,产生意外跳转。修改脚本完成后,在M2执行重载Quest脚本,旧脚本缓存不会自动更新,修改内容无法生效,依旧保留旧的循环逻辑。
障碍物与寻路问题,MOVETO命令依赖引擎内置寻路,如果目标点位被墙体包围,寻路算法会反复寻找路线,角色出现来回折返。更换点位,选择开阔无遮挡坐标,或者在脚本内增加随机石传送备呀案,多次寻路失败后,使用RANDOMMOVE随机传送,再继续尝试移动。地图的MONSTER、NPC阻挡也会干扰角色移动,怪物堵在目标点位,CHECKPOS判定持续失败,触发循环跑动。
调试定位死循环的方法,在循环脚本内添加SENDMSG输出提示,打印当前坐标和N1变量数值,观察M2窗口日志,查看每一轮循环输出信息,确认是坐标检测不通过,还是变量没有正常递增。注释掉MOVETO移动命令,只保留判定逻辑,单独测试条件判断是否正常,排除寻路带来的干扰。去掉所有延时,分步拆解脚本,先测试单次移动,确认坐标检测正常,再加入循环跳转。
多节点连续跑图任务,每一段点位都独立设置计数器和超时退出,不能把多个坐标点位写在同一个无限GOTO循环内。完成一个点位,重置计数变量,再进入下一段跑动逻辑,一个点位寻路失败,仅终止当前段落,不会卡死整个任务。使用变量标记任务状态,增加状态标识N2,N2=1正在前往A点,N2=2前往B点,依靠状态机切换,而不是单纯GOTO来回跳转,大幅降低死循环风险。
常见故障场景,角色跑到目标附近来回横跳,属于精准坐标CHECKPOS判定过于严格,更换CHECKPOSRANGE范围检测。角色原地不动反复触发移动指令,地图存在墙体阻挡,人物无法移动到目标XY,增加循环计数上限,超时退出。脚本偶尔正常,偶尔来回跑,地图刷新怪物挡住路径,增加怪物检测判断,点位周边怪物数量超标,暂停移动等待怪物清理。重载脚本之后循环依旧存在,检查全局变量残留,N1计数器没有重置,上次任务的变量数值保留,干扰新一轮任务判定。

