news 2026/9/17 12:22:01

Puerts Unity VSCode 断点调试完整指南:JsEnv 调试端口、等待调试器与 launch.json 配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Puerts Unity VSCode 断点调试完整指南:JsEnv 调试端口、等待调试器与 launch.json 配置

Puerts Unity VSCode 断点调试完整指南:JsEnv 调试端口、等待调试器与 launch.json 配置

【免费下载链接】puertsPUER(普洱) Typescript. Let's 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 开启调试端口并驱动 Tick

VSCode 调试的第一步,是在创建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(); }

两个关键点:

  1. 端口必须与 VSCode 的launch.json一致8080只是示例,换成任意空闲端口均可,但两侧必须保持相同。
  2. 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.2+)

async 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.cs:

  • WaitDebugger():同步版本,内部while (!backend.DebuggerTick()) { }空转轮询,直到 V8 Inspector 检测到调试器已连接才返回;
  • WaitDebuggerAsync():异步版本,构造一个TaskCompletionSource<bool>返回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.cpp):

  1. C# 侧new JsEnv(loader, 8080)最终触发BackendV8.OpenRemoteDebugger(8080)→ 原生CreateInspector(BackendV8.cs);
  2. 原生层使用websocketpp::server<config::asio>在指定端口上listenstart_accept,并注册 HTTP/Open/Message/Close/Fail 事件处理器(V8InspectorImpl.cpp);
  3. V8 Inspector 通过v8_inspector::V8Inspector::create创建并注册当前上下文(V8InspectorImpl.cpp);
  4. 该服务还实现了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 attach(Node.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持续被调用,调试器消息循环才不会停摆。

五、常见问题与调试实践建议

结合原文档要点与源码行为,整理如下实战清单:

  1. 断点不生效,先查端口:确认launch.jsonportnew JsEnv(loader, port)完全一致;
  2. 早期代码断不到:启动瞬间执行的代码落在“握手盲区”,改用WaitDebuggerAsync()/WaitDebugger()等调试器连接后再执行入口模块;
  3. Tick()必须持续调用:调试器的消息收发依赖Update()中的jsEnv.Tick(),任何一帧的阻塞都会让调试响应变慢甚至超时;
  4. 务必勾选 Run In Background:否则切换到 VSCode 时 Unity 进入后台,主循环被暂停;
  5. Loader 差异TSLoader免去手动指定输出目录,DefaultLoader需要传入 JS 产物目录,且两者均可搭配调试端口使用;
  6. 仅 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. Let's write your game in UE or Unity with TypeScript.项目地址: https://gitcode.com/GitHub_Trending/pu/puerts

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 12:21:36

擦亮眼睛!不是随便一个 AI 就能搞定毕业论文,2026 导师认可工具全览

每年毕业季&#xff0c;无数同学深陷论文难题&#xff1a;开题毫无思路、搭建框架耗费数日、初稿逻辑松散、查重标红泛滥、AI检测超标、格式反复被导师驳回。现如今市面上通用型AI工具遍地开花&#xff0c;但绝大多数通用大模型存在编造虚假参考文献、学术语句口语化、AI生成痕…

作者头像 李华
网站建设 2026/9/17 12:20:46

3 步装好音源插件:MusicFree 免费无广告音乐播放器新手上手指南

3 步装好音源插件&#xff1a;MusicFree 免费无广告音乐播放器新手上手指南 【免费下载链接】MusicFree 插件化、定制化、无广告的免费音乐播放器 项目地址: https://gitcode.com/GitHub_Trending/mu/MusicFree 想听一首歌&#xff0c;却总被广告和会员弹窗拦在门外&…

作者头像 李华
网站建设 2026/9/17 12:18:26

从零掌握SNMP Trap:网络设备主动告警的接收配置与故障排查

1. 为什么网络管理离不开trap报文&#xff1a;轮询之外的“主动上报”做网络运维的人应该都有过这样的经历&#xff1a;明明监控平台显示一切正常&#xff0c;但业务部门已经炸锅了。交换机CPU飙到99%、链路down了又恢复、光模块收发异常&#xff0c;这些突发状况如果全靠监控平…

作者头像 李华
网站建设 2026/9/17 12:12:17

AI改完代码后如何自我验证:Open Agents验证循环完整指南

AI改完代码后如何自我验证&#xff1a;Open Agents验证循环完整指南 【免费下载链接】open-agents An open source template for building cloud agents. 项目地址: https://gitcode.com/GitHub_Trending/op/open-agents Open Agents 是一个用于构建**云端 AI 编程智能体…

作者头像 李华
网站建设 2026/9/17 12:12:04

AI辅助STM32开发:从CubeMX配置到跑马灯实战

1. 动手前的准备&#xff1a;为什么你把AI当成搜索引擎用&#xff0c;却写不好STM32工程先聊点实际的。很多人一说AI编程&#xff0c;第一反应是打开对话框&#xff0c;把需求打过去&#xff0c;复制代码&#xff0c;粘贴进Keil&#xff0c;然后编译报错&#xff0c;再复制报错…

作者头像 李华