Lua 与引擎(C 层)之间靠虚拟栈交换数据:引擎把参数按顺序压栈再调用 Lua 函数,Lua 的返回值按返回顺序压回栈顶,引擎再按位取出。栈上槽位有正负两种索引:正数从栈底数、负数从栈顶数(-1 恒为栈顶)。由此有三条约定:一是参数按位置对齐,引擎期望 (actor, x, y) 而脚本写成 (actor, y, x) 就是灾难;二是返回值按位读取,中间的 nil 会让引擎在该位拿到空值;三是引擎按约定取前 N 个返回值,多余的被忽略。虚拟栈是槽位结构不是数组,不能随机改写历史位置。
返回值规范化包装。示例代码如下:
local function normalize(fn)
return function(actor, x, y)
local a, b, c = fn(actor, x, y)
return a or 0, b or 0, c or false
end
end
local function rawReturn(actor, x, y)
if x < 0 then
return nil, nil, nil
end
return x, y, true
end
local safeReturn = normalize(rawReturn)
print(safeReturn(nil, -5, 3))
调用侧约定示例。示例代码如下:
local function splitDamage(actor, rawDmg)
local base = math.floor(rawDmg * 0.7)
return base, rawDmg - base
end
local base, extra = splitDamage(actor, 1000)
sendmsg(actor, 1, "烈火剑法 基础 " .. base .. " 追加 " .. extra)
rawReturn 在 x 为负时返回三个 nil——直接交给按位读取的接口会三处全空;normalize 把空位补成 0 与 false,跨界契约始终成立。
引擎与 Lua 一次调用往返约 0.001 毫秒量级;参数个数线性影响成本(10 个参数比 3 个慢约 3 倍,绝对值仍是微秒级)。真正的热点是循环内反复跨界:逐个取 1000 名玩家的变量要 1000 次跨界,约 1 毫秒;改为批量取回再本地循环,降到约 0.1 毫秒——跨界次数才是成本大头,不是参数个数。
三个不适用场景:一是不与引擎交换数据的纯内部函数,无需关心栈约定;二是超多参数(10 个以上)的跨界接口应改为传一张表,按位置传参错一位就全错;三是需要边算边回写引擎状态的双向交互,逐次跨界成本高,改为批量读、本地算、批量写三段式。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏】 一、一行代码拆解:if price < WATCH[goods] then notify end —— 关注降价的…
【游戏】 一、业务场景:赛季结算发现一名玩家胜率 10% 却排在黄金段——历史计分只加不减,积分体系失效 3 个月;积分赛—…
【语法】 一、抛坑提问:3 对括号能组成多少种合法序列?答案是 5——卡塔兰数列:每一项等于前一项乘 2 倍的 2n 减 1…
【语法】 一、抛坑提问:不想用全局随机函数(怕多处共享种子互相干扰),可自实现一个独立随机序列——线性同余法三行核心:乘、加…
【游戏】 一、一行代码拆解:PENDING[outId] = {by = actor, at = now} —— 双人复核的…
【语法】 一、隐蔽陷阱:圆周率小数位背不出更多就不算理解随机模拟?用蒙地卡罗法随机撒点统计,10 万个点能把圆周率估到两位小…