Lua Addin
1. 插件简介
Lua Addin 是面向 Unity Lua 项目的 VS Code 语言服务与调试插件,仅支持使用 ToLua 的工程。
主要功能:
- Lua 语法高亮、代码片段、代码补全、参数提示和悬浮提示。
- 定义跳转、查找引用、重命名、CodeLens 引用计数和语义高亮。
- 局部变量、全局变量、函数、Table、类型注解及跨文件
require 语义分析。
- 未定义全局变量、无效成员、参数数量和未使用局部变量等诊断。
- C# Wrap 类型、方法、字段、属性、枚举及继承关系索引。
- PB 配置表、协议头文件和项目特定类型传播规则支持。
- SQLite 工作区索引、增量扫描和冷启动恢复。
- Unity Lua 断点、单步、调用栈、变量查看和表达式求值。
插件配置统一写在工作区的 .vscode/settings.json。路径配置应使用相对工作区的路径,不能使用绝对路径。
2. 支持的版本
| 项目 |
支持范围 |
| 操作系统 |
Windows x64 |
| VS Code |
1.106.0 及以上兼容版本 |
| Lua |
Lua 5.3 |
| Unity Lua 方案 |
ToLua |
| 调试方式 |
Unity 编辑器内 TCP Attach |
插件发布包及 SQLite 原生模块均面向 Windows x64。当前 Unity 调试桥接默认适配提供 LuaInterface、LitJson 和 LuaScriptManager.GetMainState() 的 tolua 工程;其他 ToLua 工程可通过 .luaaddin/runtime-config.json 配置运行时获取入口,无需修改桥接代码。
3. 配置字段说明
3.1 扫描与工程目录
| 配置字段 |
类型 |
默认值 |
说明 |
luaaddin.sourceRoots |
string[] |
["Assets/Lua", "Lua"] |
Lua 源码根目录,也用于自动生成调试路径映射。 |
luaaddin.libraries |
string[] |
[] |
参与补全、跳转和诊断的第三方 Lua 库目录。 |
luaaddin.scanDirectories |
string[] |
[] |
额外的 Lua 扫描目录。 |
luaaddin.ignoreDirectories |
string[] |
[] |
忽略的目录或单个 .lua、.cs 文件。 |
luaaddin.unityProject |
string |
"." |
Unity 工程根目录。 |
luaaddin.wrapScanPaths |
string[] |
["Assets\\Code\\ToLua\\Source\\Generate"] |
ToLua 生成代码或注册代码目录。 |
luaaddin.csharpSourcePaths |
string[] |
[] |
C# 源码目录,用于匹配 Wrap 重载的参数名和源码注释。 |
luaaddin.pbDirectories |
string[] |
[] |
PB 描述符目录。 |
luaaddin.protocolDirectories |
string[] |
[] |
协议 .h 文件目录;可使用 ../ 指向工作区同级目录。 |
3.2 类型、诊断与分析
| 配置字段 |
类型 |
默认值 |
说明 |
luaaddin.wrapTypeConversions |
string[] |
[] |
Wrap 回调参数类型、组合类型和字段类型映射;序号从 arg0 开始。 |
luaaddin.typeGuards |
object[] |
[] |
自定义类型守卫规则。 |
luaaddin.globals |
string[] |
[] |
项目全局变量白名单。 |
luaaddin.diagnostics.undefinedGlobal |
boolean |
true |
是否报告未定义全局变量。 |
luaaddin.analysis.largeFileLines |
number |
5000 |
大文件行数阈值。 |
luaaddin.analysis.largeFileExpressions |
number |
20000 |
大文件表达式数量阈值。 |
luaaddin.analysis.maxUnionMembers |
number |
8 |
联合类型最大成员数。 |
luaaddin.analysis.maxRelationExpansion |
number |
256 |
类型及实例关系最大展开数量。 |
配置示例:
{
"luaaddin.wrapTypeConversions": [
"LuaCallCS.TryAsyncOpenUIScene:arg3 => function(LuaUIBaseExecutor:UIScene)",
".transform => UnityEngine.Transform"
],
"luaaddin.typeGuards": [
{
"function": "Object.IsPlayer",
"parameterIndex": 0,
"trueType": "Player",
"excludeOnFalse": true
}
]
}
3.3 显示、引用与调试体验
| 配置字段 |
类型 |
默认值 |
说明 |
luaaddin.highlightDecorations.enabled |
boolean |
false |
是否启用插件自定义字色装饰。 |
luaaddin.highlightColors |
object |
见设置界面 |
自定义各类语义元素的颜色。 |
luaaddin.references.enabled |
boolean |
true |
是否启用查找引用。 |
luaaddin.references.codeLens.enabled |
boolean |
true |
是否在方法和字段定义上方显示引用计数。 |
luaaddin.debug.inlineValues.enabled |
boolean |
true |
调试暂停时是否显示内联变量值。 |
luaaddin.trace.server |
boolean |
false |
是否在“Lua Addin”输出面板记录详细日志。 |
3.4 索引与内存
| 配置字段 |
类型 |
默认值 |
说明 |
luaaddin.index.cachePath |
string |
".luaaddin/cache/index.sqlite" |
SQLite 索引文件路径,必须是工作区相对路径。 |
luaaddin.index.mode |
string |
"sqlite" |
索引模式:sqlite 或 memory。 |
luaaddin.memory.maxResidentFiles |
number |
128 |
内存中保留完整语义详情的最大文件数。 |
luaaddin.memory.maxResidentMb |
number |
256 |
语义详情的目标内存上限,单位为 MB。 |
工作区配置示例:
{
"luaaddin.sourceRoots": ["Assets/Code_Lua"],
"luaaddin.libraries": ["Assets/LuaLib"],
"luaaddin.ignoreDirectories": ["Assets/Code_Lua/Generated"],
"luaaddin.unityProject": ".",
"luaaddin.wrapScanPaths": ["Assets/Code/ToLua/Source/Generate"],
"luaaddin.csharpSourcePaths": ["Assets/Scripts"],
"luaaddin.pbDirectories": ["Assets/StreamingAssets/BinData/pb"],
"luaaddin.protocolDirectories": ["../tools/NetProtor/msg"],
"luaaddin.globals": ["Game", "Manager"]
}
3.5 忽略路径通配符
luaaddin.ignoreDirectories 支持通配符,路径相对工作区根目录:
{
"luaaddin.ignoreDirectories": [
"Assets/Code_Lua/**/.*",
"Assets/Code_Lua/**/generated_*.lua",
"**/*Wrap.cs"
]
}
| 写法 |
含义 |
* |
匹配单层路径中的任意字符,不跨目录。 |
? |
匹配单个非路径分隔符字符。 |
** |
作为独立路径段,匹配零层或多层目录。 |
例如,Assets/Code_Lua/**/.* 忽略该源码目录下任意层级的点号目录及其内容,**/*Wrap.cs 忽略任意目录下以 Wrap.cs 结尾的文件。支持正斜杠和反斜杠,JSON 中的反斜杠需要转义;不支持否定、花括号或字符集语法。
以 .lua 或 .cs 结尾的规则匹配文件,其余规则匹配目录及其内容。目录规则用于 Lua 扫描,.cs 文件规则用于 Wrap 和 C# 源码扫描。内置 Lua 库仍参与扫描。修改配置后重启插件,已有索引通过增量扫描更新,无需全量重建。
3.6 Wrap 类型直接转换
在 luaaddin.wrapTypeConversions 中使用单个等号,将来源 Wrap 类型转换为目标 Wrap 类型:
{
"luaaddin.wrapTypeConversions": [
"UnityEngine.Transform = UnityEngine.RectTransform"
]
}
转换后,成员补全、悬浮提示、诊断和定义跳转使用目标类型及其继承成员。类型名区分大小写,必须使用已加载的完整 Wrap 类型名;允许等号两侧及字符串末尾有空白。字段映射和回调映射仍使用 =>。
支持链式转换。同一来源配置多条规则时,首条生效;循环映射或目标类型不存在时不转换。
4. VS Code 命令
在命令面板中输入 Lua Addin 可以使用以下命令:
| 命令 |
说明 |
Lua Addin: 打开状态菜单 |
打开插件常用操作菜单。 |
Lua Addin: 停止插件 |
停止语言服务、扫描和调试支持。 |
Lua Addin: 重启插件 |
重新加载配置并重建索引服务。 |
Lua Addin: 全量扫描 |
清除索引后扫描全部文件;大型工作区耗时较长。 |
Lua Addin: 增量扫描 |
只处理新增、修改或删除的文件。 |
Lua Addin: 重启插件并刷新索引 |
重启插件并刷新索引。 |
Lua Addin: 打开索引数据库位置 |
在文件管理器中定位 SQLite 索引。 |
Lua Addin: 查看 Wrap 扫描结果 |
在输出面板显示 C# Wrap 类型摘要。 |
Lua Addin: 显示方法引用 |
显示方法或字段的引用位置,通常由 CodeLens 调用。 |
Lua Addin: 安装 Unity 调试运行时 |
安装 Unity C# 调试桥接并补充 Attach 配置。 |
状态栏中的 Lua Addin 项也可以打开常用操作菜单。扫描进度、配置错误和运行信息会显示在状态栏、通知消息或“Lua Addin”输出面板中。
5. 扩展 API
其他 VS Code 插件可以通过扩展 ID zhangjunyu.luaaddin 激活 Lua Addin,并查询指定脚本的诊断。该 API 只返回传入脚本的 luaaddin 诊断;目标脚本不需要在编辑器中打开。
import * as vscode from 'vscode';
import type { LuaAddinExtensionApi } from 'luaaddin';
const extension = vscode.extensions.getExtension<LuaAddinExtensionApi>('zhangjunyu.luaaddin');
if (!extension) {
throw new Error('未安装 Lua Addin');
}
const api = extension.isActive ? extension.exports : await extension.activate();
const diagnostics = await api.getDiagnostics(
vscode.Uri.file('G:\\Work\\Project\\Assets\\Code_Lua\\Manager.lua')
);
getDiagnostics 接受 vscode.Uri、绝对文件路径或 file: URI 字符串,返回 Promise<readonly LuaAddinDiagnostic[]>。每条结果包含目标 URI、零基行列范围、消息、VS Code 诊断级别和固定来源 luaaddin。
调用约束:
- 仅支持本地
.lua 文件。
- 文件必须属于
sourceRoots、libraries 或 scanDirectories 配置的扫描范围,且不能命中忽略规则。
- 已打开文件使用编辑器当前文本;未打开文件读取磁盘内容。
- 磁盘文件尚未入库或内容已经变化时,只增量更新该目标文件,不触发全工作区重建,也不传播依赖。
- API 会等待当前工作区索引恢复或扫描完成,避免读取过渡状态。
- 无效参数、文件不存在、插件停止或目标超出扫描范围时会拒绝 Promise。
公共 TypeScript 类型声明位于扩展包根目录的 api.d.ts,API 版本可通过 api.apiVersion 检查;当前版本为 5。
5.1 安装 Codex 配套插件
LuaAddin Diagnostics 让 Codex 查询 Lua Addin 提供的诊断、成员、引用和定义来源。使用前需要安装 Codex 桌面应用或 CLI、Node.js,以及 Lua Addin VS Code 插件。
- 安装 Lua Addin VSIX,使用 VS Code 打开并信任本地工作区,激活 Lua Addin。
- 在工作区的
.luaaddin/codex-plugins 目录中双击 install.cmd,按提示完成配套插件安装。
- 在 Codex 中新建任务,以加载配套工具。
- 查询时保持该工作区的 VS Code 和 Lua Addin 正常运行,目标 Lua 脚本无需在编辑器中打开。
扩展激活、工作区变化或授予信任时,会自动同步配套目录中的变化文件。更新 Lua Addin 后,重新运行 install.cmd 并新建 Codex 任务。请保留该目录,本地插件市场会引用它;需要卸载配套插件时运行其中的 uninstall.cmd。安装脚本只安装 LuaAddin Diagnostics,Codex 应用和 Node.js 需提前安装。
5.2 Codex 连接与源码查询
| 工具 |
用途 |
check_luaaddin_connection(workspace) |
检查与指定 VS Code 工作区的连接。 |
get_lua_diagnostics(file) |
查询指定 Lua 脚本的诊断。 |
get_lua_members_at(file, line, character) |
查询源码位置对应实例的直接成员。 |
get_lua_references_at(file, line, character) |
查询字段、方法或函数的引用位置,不包含定义。 |
get_lua_definitions_at(file, line, character) |
查询源码位置对应实例的全部定义来源。 |
workspace 和 file 必须使用绝对路径。源码查询的输入行列及返回位置从 1 开始,范围结束位置不包含在范围内。成员和引用查询遇到定位失败或歧义时返回空数组;引用结果不保证完整,需结合实际代码分析。
定义查询返回 definitions: [{ uri, range: { start, end } }],首项与编辑器优先定位顺序一致。C# 成员优先返回关联的业务源码,源码缺失时回退到 Wrap;方法返回全部已绑定重载,按实参数量差排序。同一位置去重,多来源全局变量返回全部声明,规范首处在前。没有实例绑定时返回空数组。对应扩展 API 为 getDefinitionsAt。
查询示例:
查询 G:\Work\Project\Assets\Code_Lua\ui\Example.lua 的 LuaAddin 诊断
桥接信息保存在工作区的 .luaaddin/runtime/diagnostics-bridge.json,由 Lua Addin 自动管理。连接失败时,先确认工作区路径正确且插件正在运行,再调用连接检查工具查看原因。也可为 MCP 进程设置 LUAADDIN_WORKSPACE,作为无法从脚本路径发现桥接信息时的备用工作区根目录。
5.3 Codex 外部结构查询
使用 get_external_members_by_name(workspace, kind, name),按名称查询已加载的配置表、协议或 Wrap 类型。workspace 为 VS Code 工作区绝对路径。
kind |
name 的写法 |
返回内容 |
config |
带 Data 的配置表全局名。 |
配置表行字段;重复字段的类型附加 []。 |
protocol |
精确的协议结构名。 |
带 m_ 前缀的直接字段及协议声明类型。 |
wrap |
注册的 Wrap 类型名,推荐完整名,支持 CS. 前缀。 |
包含继承成员,方法类型显示已扫描的签名。 |
返回格式为 members: [{ name, type }]。结构不存在时返回空数组,无法确定的字段类型为 unknown。该工具只查询已加载的外部结构;普通 Lua Table 请使用源码位置查询工具 get_lua_members_at。
6. 调试说明及配置
6.1 安装调试运行时
- 使用 VS Code 打开 Unity 工程工作区。插件首次激活时自动安装调试运行时,并补充
.vscode/launch.json 的 Attach 配置。
- 调试桥接安装到
Assets/Plugins/LuaAddin/LuaAddinDebugger.cs;升级插件后,下次激活自动同步新版桥接。
- 目标文件内容相同则不写入,避免重复启动触发 Unity 编译。自定义调试配置保留;旧版完整标准模板的
9966/9967 自动迁移为动态端口 0。
- 多工作区分别安装到各自识别出的 Unity 工程;打开工程子目录时向父目录定位,也可通过
luaaddin.unityProject 指定工作区相对工程路径。普通目录和未信任工作区跳过自动安装。
- 可将
luaaddin.debug.autoInstallRuntime 设为 false 关闭自动安装。仍可执行 Lua Addin: 安装 Unity 调试运行时 手动安装或重试;安装失败会显示原因,语言服务继续启动。
桥接代码仅在 Unity 编辑器中生效。进入 Play 模式前,它会取得主 LuaState 并启动内嵌调试运行时,业务 Lua 入口不需要手工调用启动、更新或关闭函数。
6.1.1 配置 Unity 的 Lua 运行时入口
在 Unity 工程根目录新建 .luaaddin/runtime-config.json(UTF-8 无 BOM,标准 JSON)。未创建此文件时,继续使用旧入口 LuaScriptManager.GetMainState()。
无实例的静态方法,直接配置完整类型名与无参方法:
{
"type": "Game.LuaManager",
"memberPath": "GetMainState()"
}
如果通过单例获取,memberPath 可以改为 Instance.LuaState 或 Instance.GetLuaState(),也支持 GetInstance().LuaState。路径第一段访问静态成员,后续访问返回对象的实例成员;支持公开字段、可读属性和有返回值的非泛型无参方法,不支持参数、索引器或表达式。类型名包含命名空间,成员名区分大小写。
入口返回 null 时调试桥继续等待,不主动创建或启动业务 LuaState;最终返回值必须是当前桥支持的 ToLua LuaState。显式配置无效会输出具体错误,不回退到旧入口。配置在每个调试对象首次成功解析后缓存,修改后请退出并重新进入 Play;自动安装或更新不会覆盖此文件。获取方法应轻量且无副作用,等待期间约每 250 毫秒调用一次。
6.2 配置 Attach
在 Unity 工程的 .vscode/launch.json 中加入:
{
"version": "0.2.0",
"configurations": [
{
"type": "luaaddin",
"request": "attach",
"name": "Attach Unity Lua",
"host": "127.0.0.1",
"port": 0,
"autoReconnect": true
}
]
}
| 字段 |
类型 |
默认值 |
说明 |
type |
string |
"luaaddin" |
调试器类型,固定为 luaaddin。 |
request |
string |
"attach" |
Unity 调试推荐使用 Attach。 |
name |
string |
— |
调试配置显示名称。 |
host |
string |
"127.0.0.1" |
Unity Lua 调试服务地址。 |
port |
number |
0 |
0 或省略时使用动态端口;操作系统为各 Unity 实例分配空闲端口。显式正整数仍使用固定端口。 |
unityProjectRoot |
string |
自动定位 |
Unity 工程目录;默认从调试配置所属工作区向父目录定位,也可指定工作区相对路径。 |
unityProcessId |
number |
自动选择 |
同一工程有多个运行实例时可指定进程 ID;启动附加时也可选择实例。 |
autoReconnect |
boolean |
true |
Unity 尚未启动或停止 Play 时保持等待,并在运行时可用后自动附加。 |
pathMappings |
object[] |
自动生成 |
源码路径映射,每项包含 localRoot 和 runtimeRoot。 |
动态模式只监听本机 127.0.0.1。Unity 在工程的 .luaaddin/runtime/unity-debug-<进程ID>-<会话标识>.json 发布实际端口,文件以 UTF-8 无 BOM 原子写入,包含协议版本、进程 ID、端口和随机会话标识,不写入数据库。插件只读取所选工程的记录,并在发送断点前校验会话标识;不同目录下同名工程也相互隔离。停止 Play、脚本重载或退出时清理本实例记录,新会话启动时清理同进程旧记录。实例发现同时检查进程存活、端口是否监听及所属 PID,使用只读系统监听表,不占用调试连接;握手继续校验会话标识,防止端口复用后误连。
Unity 停止 Play 或重启后,自动重连会重新发现端口。同工程多个实例不会任意选择;已指定 unityProcessId 的会话只附加该进程,整个 Unity 进程退出后需重新选择。远程调试继续使用显式固定端口。
升级插件后,在各工程激活插件即自动更新 C# 桥,并将旧版完整标准模板的 9966/9967 迁移为 0。自定义端口或增加了手工字段的旧配置保持原样;此类配置切换动态模式时将 port 设为 0 即可,后续无需按工程维护端口。
省略 pathMappings 时,插件会根据工作区和 luaaddin.sourceRoots 自动生成映射。需要手动映射时,可在调试配置中加入:
"pathMappings": [
{
"localRoot": "Assets/Code_Lua",
"runtimeRoot": "Assets/Code_Lua"
}
]
6.3 开始调试
- 可以先在 VS Code 启动调试;Unity 尚未运行或未进入 Play 时,调试会话会保持等待连接。
- 启动 Unity 并进入 Play 模式,确认 Unity 控制台出现“Lua Addin 调试服务已启动”,调试器会自动附加。
- 在 Lua 文件中设置断点。
- 在 VS Code 的“运行和调试”视图选择
Attach Unity Lua 并开始调试。
当前支持断点暂停、继续、基础单步、调用栈、局部变量、upvalue、全局变量、Watch 求值和内联值。暂不支持向 Unity 进程注入式附加。
6.4 展开 C# 数组和集合
调试暂停时,可在悬浮提示和变量面板中展开 C# 数组及集合:
| 类型 |
展示方式 |
| 数组 |
按真实下标展示,例如 Vector3[] 的 [0]、[1];元素可继续展开 x、y、z。支持空数组、交错数组和带非零下界的多维数组。 |
| 列表 |
List<T>、ArrayList 和只读列表按下标展示元素。 |
| 字典 |
Dictionary、Hashtable、排序字典和只读字典按条目展示,每条可展开 Key 和 Value。支持对象键、空值和嵌套集合。 |
| 其他可枚举集合 |
Queue、Stack、HashSet、LinkedList 等按枚举顺序展示,不执行出队、出栈或删除操作。 |
每页最多显示 100 项,其余通过“更多元素”展开。单次暂停最多缓存 4096 个顺序集合元素;达到上限或枚举期间集合变化时会显示提示。分页不消耗对象展开深度,原有深度限制仍生效。展开自定义 IEnumerable 时会执行其枚举代码。
此功能依赖 Unity 调试桥。更新插件后,在工程中重新激活 Lua Addin,等待调试桥同步和 Unity 编译完成,再进入 Play 模式并连接调试器。
本配置用于适配不同项目的管理器入口,Lua 桥接框架仅支持 ToLua。
编辑器原生模块兼容
Windows x64 安装包固定包含 ABI 136、140、143、146、148,覆盖已核实的 VS Code 1.106.x 起的相应 Electron 运行时,并保留既有 ABI 143 支持。Cursor 3.21.18 在本机使用 ABI 146;不承诺所有历史 Cursor 或未来编辑器版本。最低 VS Code 要求仍为 1.106.0。
构建使用 npm run package,仅检查运行时使用 npm run verify:native;精确版本及依据见 scripts/native-compatibility.json。打包前和最终 VSIX 解压后均执行原生数据库验证,结果见 dist/native-compatibility-report.json。本机编辑器出现清单外 ABI 时构建失败,需要先更新兼容清单。独立 Node.js 版本、非 Windows x64 和真实项目行为不属于本项兼容声明。