Puerts Unity VSCode 断点调试完整指南:JsEnv 调试端口、等待调试器与 launch.json 配置
Puerts Unity VSCode 断点调试完整指南JsEnv 调试端口、等待调试器与 launch.json 配置【免费下载链接】puertsPUER(普洱) Typescript. Lets write your game in UE or Unity with TypeScript.项目地址: https://gitcode.com/GitHub_Trending/pu/puerts本文基于当前仓库 doc/unity/zhcn/knowjs/debugging.md英文版见 doc/unity/en/knowjs/debugging.md整理而成并结合 JsEnv.cs 等源码对底层机制做了进一步解读。读者将掌握如何在 Unity 中通过JsEnv构造参数开启调试端口、用“等待调试器连接”能力让最早期脚本也能命中断点、以及如何在 VSCode 中配置自动附加或手写launch.json完成断点、单步、变量查看等操作。Puerts 在 Unity 中的脚本以 V8 为 JS 引擎因此天然复用 V8 Inspector 协议调试器通过 WebSocket 连接到一个本地 TCP 端口即可像调试 Node.js 一样调试运行在游戏内的 TypeScript/JavaScript 代码。本指南介绍官方推荐的 VSCode 调试链路从 C# 侧开启端口开始一直讲到 VSCode 侧的附加配置与 Unity 侧的配套设置。如果目标平台是手机等移动设备端口转发与真机调试方式可参考开发博客原文档建议阅读对应开发 blog仓库内不包含该内容此处不再展开。一、调试前置为 JsEnv 开启调试端口并驱动 TickVSCode 调试的第一步是在创建JsEnv时传入调试端口。端口号会通过ScriptEnv一路传递到后端最终由 V8 后端启动一个本地 Inspector 服务见下文“底层原理”一节。以Start为例最简单的开启方式如下// 8080 是连接的端口和 vscode 工程目录下的 .vscode\launch.json 保持一致 void Start() { jsEnv new JsEnv(new TSLoader(), 8080); // 推荐使用 TSLoader就不需要你手动指定 JS 输出目录 jsEnv new JsEnv(new DefaultLoader(F:/puerts/unity/TsProj/output/), 8080); // 使用 DefaultLoader 时需要手动指定你的 JS 输出目录 } void Update() { jsEnv.Tick(); }两个关键点端口必须与 VSCode 的launch.json一致。8080只是示例换成任意空闲端口均可但两侧必须保持相同。Tick()不可省略。JsEnv.Tick()在Update中每帧被调用它负责驱动调试器的消息循环。从源码看JsEnv.cs 的Tick()转发到ScriptEnv.Tick()而后者在debugPort ! -1时会调用backend.DebuggerTick()处理 Inspector 收发见 ScriptEnv.cs。换言之端口开启后若不做Tick调试器将无法正常工作。关于 Loader 的选择原文档给出的建议同样适用TSLoader推荐使用自动处理 TS 编译与输出目录无需手工指定 JS 输出位置DefaultLoader需要手动传入 JS 输出目录如F:/puerts/unity/TsProj/output/适合你已经自行完成编译、仅需加载产物的场景。提示new JsEnv()的第二个参数默认值为-1见 JsEnv.cs此时不开启调试端口只有传入有效端口号才会启动调试服务。二、等待调试器连接让早期脚本也能断点连接耗时与断点盲区调试器通过 WebSocket 与 V8 建立连接期间包含TCP 握手、WebSocket 握手以及建立连接后调试器与 V8 之间交换协议信息整个过程大约几百毫秒。在这几百毫秒内执行的脚本无法被断点命中——因为调试协议尚未就绪。如果你的模块入口如QuickStart.mjs在启动瞬间就会执行大量代码而这些代码恰好落在“盲区”里断点就会失效。解决方案就是 Puerts 提供的“等待调试器连接”功能让JsEnv阻塞等待直到 V8 Inspector 与调试器完成握手后再执行业务脚本。选择依据原文档说明C# 版本高于 7.2支持 async时推荐异步等待否则使用同步阻塞等待。异步等待推荐C# 7.2async void RunScript() { jsEnv new JsEnv(new DefaultLoader(E:/puerts_unity_demo/TsProj/output/), 8080); await jsEnv.WaitDebuggerAsync(); jsEnv.ExecuteModule(QuickStart.mjs); } void Start() { RunScript(); } void Update() { jsEnv.Tick(); }同步阻塞等待void Start() { jsEnv new JsEnv(new DefaultLoader(E:/puerts_unity_demo/TsProj/output/), 8080); jsEnv.WaitDebugger(); jsEnv.ExecuteModule(QuickStart.mjs); } void Update() { jsEnv.Tick(); }底层实现Task 驱动与轮询两个 API 在 JsEnv.cs 中都有封装具体逻辑位于 ScriptEnv.csWaitDebugger()同步版本内部while (!backend.DebuggerTick()) { }空转轮询直到 V8 Inspector 检测到调试器已连接才返回WaitDebuggerAsync()异步版本构造一个TaskCompletionSourcebool返回Task后续Tick()中一旦DebuggerTick()为真就通过waitDebugerTaskSource.SetResult(true)唤醒等待方——因此异步等待同样依赖每帧调用Tick()。注意WaitDebuggerAsync()在debugPort -1时会直接返回null见 ScriptEnv.cs所以只有开启调试端口的JsEnv才适用这两个等待 API。仓库自带的 Unity 测试工程也演示了这一用法HelloWorlder.cs 中创建JsEnv(new DefaultLoader(), 8080)后立即调用env.WaitDebugger()可作为最小可运行参考。调试器连接流程的源码印证从实现看调试链路是这样的Unity V8 后端与 Unreal 共享同一份 Inspector 实现即 V8InspectorImpl.cppC# 侧new JsEnv(loader, 8080)最终触发BackendV8.OpenRemoteDebugger(8080)→ 原生CreateInspectorBackendV8.cs原生层使用websocketpp::serverconfig::asio在指定端口上listen、start_accept并注册 HTTP/Open/Message/Close/Fail 事件处理器V8InspectorImpl.cppV8 Inspector 通过v8_inspector::V8Inspector::create创建并注册当前上下文V8InspectorImpl.cpp该服务还实现了GET /json列表接口返回webSocketDebuggerUrl等信息V8InspectorImpl.cpp这正是调试器用于发现与连接目标的信息来源。这也解释了“几百毫秒”的构成TCP 握手 WebSocket 握手 协议信息交换全部发生在连接建立阶段。三、VSCode 端配置自动附加或手写 launch.json连接方式二选一方式 A开启 Auto Attach简单快捷在 VSCode 中打开设置Ctrl,搜索auto attach将Debug Node: Auto Attach设置为on。此后 VSCode 会自动发现并附加到上述端口上的调试会话。原文档特别说明高版本 VSCode 可能没有该选项此时可以跳过此项设置直接用手写launch.json的方式。方式 B手动创建 launch.json推荐更可控在 VSCode 工程目录下创建或打开.vscode/launch.json新增一个Node.js Attach类型的调试配置并把port改为你在JsEnv构造函数里传入的端口号。要点调试类型选择node.js attachNode.js 附加模式而不是 launch/启动模式port必须与new JsEnv(loader, 8080)的端口完全一致配置完成后在调试面板启动该 Attach 会话VSCode 即开始尝试连接 Unity 内运行的 V8 Inspector。launch.json的最小示意如下端口以你实际使用的为准{ version: 0.2.0, configurations: [ { type: node, request: attach, name: Attach to Puerts, port: 8080, restart: true, localRoot: ${workspaceFolder}, remoteRoot: ${workspaceFolder} } ] }原文档同时给出了“选择 node.js attach”的界面示意图见英文版 doc/unity/en/knowjs/debugging.md仓库内该图为外部托管图片。实际操作中只要能建立对127.0.0.1:8080的 WebSocket 附加即可获得断点、单步、调用栈、变量监视等能力。断点盲区的完整规避方案把等待调试器与启动顺序组合起来就是最稳妥的启动模板先await WaitDebuggerAsync()或同步WaitDebugger()确保 Inspector 已就绪再ExecuteModule(QuickStart.mjs)执行入口模块从而保证入口代码的所有断点都能命中。四、Unity 侧配套设置勾选 Run In Background最后一步是让游戏在失焦后台时继续运行否则一旦切到 VSCode 调试Unity 主循环暂停、Tick()不再执行调试自然中断。操作路径打开Project Settings / Player页面把Run In Background勾选上。图中高亮的正是该选项它位于 Player 设置的 Resolution and Presentation 区域勾选后游戏窗口失去焦点时仍保持运行Update/Tick持续被调用调试器消息循环才不会停摆。五、常见问题与调试实践建议结合原文档要点与源码行为整理如下实战清单断点不生效先查端口确认launch.json的port与new JsEnv(loader, port)完全一致早期代码断不到启动瞬间执行的代码落在“握手盲区”改用WaitDebuggerAsync()/WaitDebugger()等调试器连接后再执行入口模块Tick()必须持续调用调试器的消息收发依赖Update()中的jsEnv.Tick()任何一帧的阻塞都会让调试响应变慢甚至超时务必勾选 Run In Background否则切换到 VSCode 时 Unity 进入后台主循环被暂停Loader 差异TSLoader免去手动指定输出目录DefaultLoader需要传入 JS 产物目录且两者均可搭配调试端口使用仅 V8 后端开启调试从 Backend.cs 的虚方法可以看出OpenRemoteDebugger/DebuggerTick是后端级能力V8 与 NodeJS 后端均有对应实现BackendV8.cs、BackendNodeJS.cs使用这些后端才能获得完整的断点调试支持。六、相关阅读模块加载与入口执行ExecuteModule的用法见 JsEnv.cs调试时配合等待 API 使用可确保入口代码可断点TypeScript 调试辅助TypeScript 指引模块系统见 模块文档理解ExecuteModule(QuickStart.mjs)的模块解析规则调试链路底层的 Inspector 实现见 V8InspectorImpl.cpp可深入阅读 WebSocket 服务与协议分发细节。【免费下载链接】puertsPUER(普洱) Typescript. Lets write your game in UE or Unity with TypeScript.项目地址: https://gitcode.com/GitHub_Trending/pu/puerts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →