VSCode + EmmyLua 调试 Unity Lua(最简接入 + 不阻塞运行版)
本文给出一套最小可用 、同时不影响正常运行 的接入方案:
即使 VSCode 没开启调试,Unity 也不会报错或中断;当你需要调试时再连接。
适用:
text
Unity + ToLua / XLua / SLua / 自研 Lua
一、最终效果
text
不开 VSCode 调试 → Unity 正常运行(不会报错)
开 VSCode 调试 → Lua 命中断点
二、原理(非常关键)
EmmyLua 的模式是:
text
Lua 主动连接 VSCode(tcpConnect)
因此:
text
VSCode 没开 → 连接会被拒绝(connection refused)
解决思路就是:
text
把连接过程用 pcall 包起来 → 失败也不影响运行
三、目录结构(标准)
假设你的 Unity 项目:
text
D:/Users/Administrator/Documents/goods-triple-tile/
结构如下:
text
goods-triple-tile/
├── .vscode/
│ └── launch.json
│
├── Assets/
│ ├── Tools/
│ │ └── EmmyLua/
│ │ └── x64/
│ │ └── emmy_core.dll
│ │
│ └── Game/
│ └── Lua/
│ └── App/
│ └── Controller/
│ └── Main/
│ └── MainViewBehaviour.lua
四、复制 EmmyLua DLL
从 VSCode 插件目录复制:
text
C:\Users\你的用户名\.vscode\extensions\tangzx.emmylua-xxx\debugger\emmy\windows\x64
复制到:
text
Assets/Tools/EmmyLua/x64/
确认文件存在:
text
emmy_core.dll
五、VSCode 配置(launch.json)
路径:
text
项目根目录/.vscode/launch.json
完整内容:
json
{
"version": "0.2.0",
"configurations": [
{
"type": "emmylua_new",
"request": "launch",
"name": "EmmyLua Unity Debug",
"host": "localhost",
"port": 9966,
"ext": [
".lua",
".lua.txt",
".lua.bytes"
],
"ideConnectDebugger": false
}
]
}
六、Lua 最简接入代码(核心)
这是你当前方案的正确版本(修正过):
lua
local function StartEmmyLuaDebugger()
print("package.cpath before = " .. tostring(package.cpath))
-- ⚠️ 必须用 /?.dll,不能写死 emmy_core.dll
-- ⚠️ 必须用 .. 追加,不能用 = 覆盖
package.cpath = package.cpath ..
";d:/Users/Administrator/Documents/goods-triple-tile/Assets/Tools/EmmyLua/x64/?.dll"
-- 1. 安全加载
local requireOk, dbgOrErr = pcall(require, "emmy_core")
if not requireOk then
print("EmmyLua调试器加载失败:" .. tostring(dbgOrErr))
return
end
local dbg = dbgOrErr
-- 2. 安全连接(关键点)
local connectOk, connectErr = pcall(function()
dbg.tcpConnect("localhost", 9966)
end)
if not connectOk then
print("EmmyLua未连接(VSCode未启动调试),游戏继续运行:" .. tostring(connectErr))
return
end
print("EmmyLua调试器连接成功")
-- ⚠️ 不建议默认开启,否则 VSCode 没开会卡住
-- dbg.waitIDE()
end
-- 最外层保护(防止极端异常)
local ok, err = pcall(StartEmmyLuaDebugger)
if not ok then
print("EmmyLua调试器启动异常,游戏继续运行:" .. tostring(err))
end
七、为什么你原来的写法会出问题
你写的是:
lua
package.cpath = "xxx/emmy_core.dll"
问题有两个:
❌ 问题1:require 找不到
Lua 的规则是:
lua
require("emmy_core")
会去找:
text
路径/?.dll → emmy_core.dll
所以必须写:
lua
";路径/?.dll"
❌ 问题2:覆盖了 package.cpath
lua
package.cpath = "xxx"
会把原来的所有 C 模块路径清空。
正确写法:
lua
package.cpath = package.cpath .. ";xxx/?.dll"
八、为什么会出现 connection refused
报错:
text
[Emmy]connection refused
原因:
text
VSCode 没按 F5 → 没有监听 9966 端口
Lua 调用:
lua
dbg.tcpConnect("localhost", 9966)
就会失败。
✅ 正确处理方式
必须这样写:
lua
pcall(function()
dbg.tcpConnect(...)
end)
这样:
text
连接失败 → 打印日志 → 不影响 Unity 运行
九、启动顺序(必须)
text
1. VSCode 打开项目根目录
2. 按 F5(启动调试)
3. Unity 点击 Play
4. Lua 执行 tcpConnect
5. 连接成功
如果反过来:
text
Unity 先 Play → 必然 connection refused
十、如何查看调用来源(Call Stack)
断点命中后,在 VSCode 左侧:
text
CALL STACK
示例:
text
MainViewBehaviour.lua : 429
MainGameConfig.lua : 29
正确理解
text
下面调用上面
也就是:
text
MainGameConfig → MainViewBehaviour
记住:
text
Call Stack 下面的是调用者
十一、调试神器:打印调用链
lua
print(debug.traceback())
输出:
text
stack traceback:
MainViewBehaviour.lua:429
MainGameConfig.lua:29
十二、是否使用 waitIDE()
lua
dbg.waitIDE()
作用:
text
等待 VSCode 连接后再继续执行
问题:
text
VSCode 没开 → Unity 卡住
建议:
text
默认关闭,只在需要时打开
十三、最终结论
这套最简方案的核心:
text
1. require 用 pcall
2. tcpConnect 用 pcall(关键)
3. package.cpath 用追加 + /?.dll
4. VSCode 不开时也能运行
十四、一句话总结
text
让调试"可选",而不是"强依赖"
如果你下一步要做更高级的:
text
只在 Debug 模式自动连接
一键开关调试
自动识别 VSCode 是否启动