39传奇素材网 发表于 6 天前

传奇游戏脚本优化时,如何选择合适的命令

在传奇游戏脚本优化中,命令的选择直接影响执行效率(CPU / 内存占用)和稳定性。不同命令的底层实现逻辑差异很大(如内存操作 vs 磁盘 IO、单步处理 vs 批量处理),需结合场景(如高频触发、数据量级、交互频率)选择最优命令。以下从效率优先级、场景适配、引擎特性三个维度,提供具体的命令选择策略:
一、按 “执行效率” 优先级选择命令
传奇脚本命令的效率核心取决于:是否涉及磁盘 IO(读写文件 / 数据库)、是否需要复杂计算(字符串解析、跨地图查询)、是否为批量操作。优先级从高到低排序如下:
1. 优先选择 “内存级轻量命令”(无 IO、无复杂计算)
这类命令仅操作内存数据(如临时变量、基础运算),执行耗时通常在微秒级,适合高频触发场景(如玩家移动、怪物攻击)。

命令类型        典型命令(GEE/GOM 通用)        适用场景
临时变量操作        MOV P0 1、INC I5 1、DEC M3 2        临时计数、状态标记(如副本内步数)
基础数值运算        ADD G1 10、MUL P2 2、MOD I0 10        简单数学计算(如冷却时间倒计时)
条件判断(基础)        #IF EQUAL P0 1、#IF LARGE U1 100        变量值对比(非跨地图 / 跨玩家)

示例:玩家每走一步计数(高频触发),应使用M变量(地图内临时变量,内存操作)而非U变量(数据库存储):

ini
; 高效:M变量(内存操作,切换地图自动清空)
@MOVE
#ACT
INC M0 1 ; 记录当前地图内移动步数

; 低效:U变量(每次修改写入数据库,IO成本高)
@MOVE
#ACT
INC U100 1 ; 不推荐!高频IO会卡顿
2. 谨慎使用 “磁盘级持久化命令”(有 IO 操作)
这类命令涉及读写磁盘文件(如G/A变量存于GlobalVal.ini)或数据库(如U/T变量存于Mir.db),执行耗时是内存命令的 10-100 倍,需避免高频调用。

命令类型        典型命令        注意事项
持久变量操作        MOV G1 3600、SET U2 1000        低频同步(如每 10 分钟更新一次全服数据)
数据库查询        CHECKUSER 玩家A(查询其他玩家数据)        禁止在循环或高频事件中使用
文件读写        WRITEFILE Log.txt 内容        仅用于低频日志(如每日统计),避免实时写入

优化策略:用内存变量缓存,批量同步到持久化存储。例如,全服金币总量统计:

ini
; 高效:先缓存到I变量,每100次同步到G变量(减少磁盘IO)
#ACT
INC I0 1000 ; 玩家获得1000金币,先加临时变量
#IF
MOD I0 100000 = 0 ; 累计10万金币同步一次
#ACT
ADD G0 100000 ; 同步到持久化G变量(磁盘操作)
MOV I0 0

; 低效:每次操作直接修改G变量(高频IO)
#ACT
ADD G0 1000 ; 不推荐!每次都写磁盘
3. 避免使用 “高消耗复杂命令”(复杂计算 / 跨资源查询)
这类命令需要解析字符串、跨地图统计或遍历数据,执行耗时高(毫秒级),在高频场景中会直接导致服务器卡顿。

高消耗命令(需谨慎)        底层逻辑        替代方案
MAPMONCOUNT 3 1001        遍历指定地图(3 号)的 1001 号怪物数量        用G变量定时同步(如每 30 秒统计一次)
GETSTRVALUE(A1, 键)        解析A变量中的键值对字符串(如 “玩家 A=100”)        初始化时拆分到G变量(如G1=玩家A的值)
GETONLINECOUNT        遍历所有在线玩家计数        用I0变量在玩家登录 / 下线时INC/DEC维护
CHECKITEMEX 物品名        遍历背包所有物品检测是否存在        用U变量记录物品状态(如U5=1表示拥有该物品)

示例:检测全服在线人数(避免直接调用GETONLINECOUNT):

ini
; 高效:用I0维护在线人数(登录时+1,下线时-1)
; Login.txt(玩家登录)
#ACT
INC I0 1

; Logout.txt(玩家下线)
#ACT
DEC I0 1

; 需要时直接读取I0(内存操作)
#IF
LARGE I0 1000
#SAY
当前在线人数:<$I0>(1000+,爆满)

; 低效:每次需要时调用GETONLINECOUNT(遍历所有玩家)
#SAY
当前在线人数:<$GETONLINECOUNT>(不推荐!高频调用卡顿)
二、按 “场景特性” 选择命令
不同场景(如物品操作、事件触发、字符串处理)对命令的需求不同,需结合场景的 “触发频率” 和 “数据量级” 选择:
1. 物品 / 金币操作:优先 “批量命令”
涉及大量物品(如给予 100 瓶药水)或金币时,单步命令(GIVE/TAKE)需要循环执行,效率极低。应使用引擎提供的批量命令(不同引擎支持不同):

引擎        批量给予物品        批量删除物品        批量金币操作
GEE 引擎        GIVEBATCH 药水 100        TAKEBATCH 药水 50        GIVEGOLD 100000(一次给 10 万)
GOM 引擎        GIVE 药水 100(支持数量参数)        TAKE 药水 50(支持数量参数)        ADDGOLD 100000

示例:玩家完成任务获得 100 瓶太阳水:

ini
; 高效:批量命令(1次调用)
#ACT
GIVEBATCH 太阳水 100 ; GEE引擎

; 低效:循环单步命令(100次调用)
LOOP 100
#ACT
GIVE 太阳水 1
#ENDLOOP
2. 事件触发:优先 “被动触发命令”,替代 “主动轮询”
检测状态变化(如 BOSS 死亡、玩家上线)时,主动轮询(如每秒用@TIMER检测)会持续占用资源,应使用引擎的被动触发命令(事件驱动):

需求场景        低效方案(主动轮询)        高效方案(被动触发)
检测 BOSS 死亡        @TIMER 1 + MAPMONCOUNT        在MonDie.txt中检测MONID=BOSSID
检测玩家上线        @TIMER 5 + CHECKONLINE 玩家A        在Login.txt中检测USERNAME=玩家A
检测物品使用        @TIMER 1 + CHECKITEM 特药        在UseItem.txt中检测ITEMID=特药ID

示例:BOSS 死亡后发送全服公告:

ini
; 高效:被动触发(BOSS死亡时执行一次)
; MonDie.txt(怪物死亡事件脚本)
#IF
MONID = 1001 ; BOSS的怪物ID
#ACT
SENDMSG 6 全服公告:世界BOSS已被击杀!

; 低效:主动轮询(每秒检测一次,持续消耗资源)
@TIMER 1
#IF
MAPMONCOUNT 3 1001 = 0 ; 3号地图的1001号BOSS数量为0
#ACT
SENDMSG 6 全服公告:世界BOSS已被击杀!
3. 字符串处理:减少 “动态解析”,优先 “静态拆分”
A/T变量存储字符串(如键值对 “玩家 A=500# 玩家 B=300”)时,频繁用GETSTRVALUE解析会消耗 CPU,应在初始化时拆分到数值变量:

示例:处理玩家贡献榜数据:

ini
; 高效:初始化时拆分到G变量(一次解析,多次使用)
#ACT
; A1存储原始数据:"玩家A=500#玩家B=300"
MOV G1 <$GETSTRVALUE(A1, 玩家A)> ; G1=500(玩家A的贡献)
MOV G2 <$GETSTRVALUE(A1, 玩家B)> ; G2=300(玩家B的贡献)

; 后续直接用G1/G2(内存操作)
#SAY
玩家A贡献:<$G1><br>
玩家B贡献:<$G2>

; 低效:每次使用时动态解析(多次计算)
#SAY
玩家A贡献:<$GETSTRVALUE(A1, 玩家A)><br>
玩家B贡献:<$GETSTRVALUE(A1, 玩家B)> ; 每次都要解析字符串
三、结合 “引擎特性” 选择命令
不同引擎(GEE、GOM、996 等)对命令的支持和优化不同,需避免使用 “引擎不擅长” 的命令:

引擎        高效命令(推荐)        低效命令(避免)        备注
GEE 引擎        GIVEBATCH、TAKEBATCH(批量操作)        GETSTRVALUE(高频解析)        对批量命令优化较好
GOM 引擎        ADDGOLD、SUBGOLD(金币批量操作)        MAPMONCOUNT(跨地图统计)        对数据库操作优化较弱
996 引擎        Synzvar(跨服变量同步)        WRITEFILE(文件操作)        跨服场景下优先用内置服变量

示例:GOM 引擎中避免频繁查询其他玩家数据:

ini
; GOM引擎低效:CHECKUSER会频繁访问数据库
#IF
CHECKUSER 玩家A ; 检测玩家A是否存在
#ACT
...

; 替代方案:用G变量维护玩家列表(登录时记录,下线时删除)
; Login.txt
#ACT
MOV A1 "<$A1>#<$USERNAME>" ; A1存储所有在线玩家:"玩家A#玩家B#..."

; 检测时用字符串包含判断(内存操作)
#IF
STRSTR A1 玩家A ; 检查A1中是否包含"玩家A"
#ACT
...
四、命令选择的核心原则总结
高频场景用内存命令:玩家移动、怪物攻击等每秒触发多次的场景,只使用I/P/M等临时变量和基础运算命令。
低频场景用持久命令:全服活动开关、每日统计等几分钟一次的场景,可使用G/U等持久变量。
批量操作替代循环:物品、金币数量≥10 时,优先用批量命令(GIVEBATCH等),避免LOOP循环单步操作。
事件驱动替代轮询:状态检测(如 BOSS 死亡、物品使用)优先用引擎事件(MonDie.txt/UseItem.txt),而非@TIMER轮询。

页: [1]
查看完整版本: 传奇游戏脚本优化时,如何选择合适的命令