Lua接口/函数不存在
来自天龙知识库
跳到导航跳到搜索
函数调用报 nil 时,先判断报错的是函数名称,还是函数执行后得到的结果。下面的服务端示例使用当前回调提供的 sceneId、selfId。
先区分三种情况
| 现象 | 含义与排查方向 |
|---|---|
attempt to call ... (a nil value)
|
执行到调用位置时,该名称的值是 nil;检查拼写、运行环境、脚本加载和同名变量。参数顺序错误通常不是这条报错的直接原因。 |
attempt to index ... (a nil value)
|
点号或下标前的对象是 nil;先检查访问的 table 或上一步返回值。把 table 不存在误判为原生函数未注册,会查错方向。 |
调用完成,接收变量为 nil
|
可能是接口无返回值、失败分支少返回几项,或者脚本封装漏写 return;此时函数本身可以存在。 |
错误文本可能随 Lua 运行环境不同而变化,以实际错误行和被指出的变量为准。
检查调用名称是否是函数
local entryType = type(GetLevel)
if entryType ~= "function" then
-- 查看 entryType,并检查当前作用域和运行环境
return
end
local level = GetLevel(sceneId, selfId)
if type(level) == "number" and level >= 0 then
-- 已取得等级
end
这里只检查名称能否调用,不保证玩家对象、场景或业务条件有效。type 是 Lua 基础函数,不属于服务端注册接口。
按顺序排查
- 在 服务端函数索引 中查完整名称,核对大小写和 LuaFn 前缀。GetLevel 与 LuaFnGetLevel 都有注册,但不能把这个规则套给其他函数。
- 核对实际运行的是服务端脚本还是客户端界面脚本。复制 .lua 文件不会把另一端的 C++ 注册函数一并复制过去,见 调用范围。
- 检查同名变量。例如声明 local GetLevel 后,该局部变量会遮住全局函数;给 GetLevel 赋数值、字符串或 nil 也会改变之后的调用行为。业务变量宜命名为 level、playerLevel。
- 若调整过脚本环境表,检查该环境是否能访问注册函数。普通全局环境下可比较 type(GetLevel) 与 type(_G.GetLevel),不要直接修改 _G 来掩盖加载问题。
- 区分 C++ 注册接口和脚本自定义入口。前者由运行程序注册,后者需要对应脚本加载成功;检查脚本编号、入口名称和之前的语法错误。CallScriptFunction 的参数另有约定,不能代替两端之间的通信。
- 若当前源码有注册而运行时仍为 nil,核对实际启动的程序和脚本部署是否与源码一致;热加载能力、加载时机和具体重载流程需要实测。
有函数但没有返回值
local result = EndEvent()
-- EndEvent 已注册,但无返回值,因此 result 为 nil
if result == nil then
-- 这不能证明 EndEvent 不存在或执行失败
end
EndEvent 不会自动把对话显示给玩家。AddText 和 AddItemListToHuman 也不能通过接收结果判断业务成功。返回数量与返回数字的区别见 返回值判断。
记录问题时保留什么
保留函数完整名称、错误文本和行号、报错前后的短代码、运行端、回调名称,以及每个实参的值和 type 结果。优先检查最早出现的加载错误,后续 nil 可能只是连带结果。
相关问题
示例依据当前服务端注册名称和参数读取顺序核对;sceneId、selfId 等上下文及业务编号由实际回调提供。Lua 语法检查不能代替游戏内实测。