资讯动态

调试器是怎么“连上“ Unity 的?

发布时间:2026/8/24 21:19:18 来源:尧图企业网站定制
接着上一篇。上面讲的是断点怎么工作这篇讲更前面的一步VS/Rider 点Attach to Unity那一下底层到底发生了什么。核心还是上一篇那个 agent。连上 Unity本质就是IDE 通过 socket 连到 Unity 进程里那个 debugger agent 线程。难点全在IDE 怎么知道该连哪个 IP、哪个端口——因为端口是动态的而且要支持连手机、连编辑器、连独立包三种目标。一、先看被调试端Unity 里的 agent 是怎么起来的和纯 Mono 命令行不同Unity 不需要你手写--debugger-agent...参数。Unity 运行时内建了调试支持启动时根据构建设置自动决定要不要拉起 agent。三种情况Editor编辑器本身Unity 编辑器进程里的 Mono 运行时默认就开着 agent一直在监听。所以你能随时 attach 到编辑器调试运行中的游戏。Development Build开发版包体勾了Development BuildScript Debugging的独立/移动端包启动时运行时才拉起 agent。没勾就没有 agent连不上——这是最常见的连不上原因。IL2CPP 的例外如果 scripting backend 是 IL2CPPC# 被 AOT 转成了 C没有 Mono 运行时、没有 soft debugger agent这套托管调试机制整个失效。IL2CPP 的调试是另一条完全不同的链路基于生成的 C能力也弱得多。这点上一篇末尾提过是很多人踩的坑。二、关键难题端口是动态的IDE 怎么找到它agent 监听的端口不是固定的。Unity 用了一个约定好的算法从进程 PID 推算端口让 IDE 不用扫全端口也能算出来。debugger 端口 56000 (PID % 1000)于是 attach 的信息发现流程是这样的IDE 想连某个 Unity 实例 │ ├─ 拿到目标进程的 PID │ └─ 端口 56000 PID % 1000 │ └─ 连 127.0.0.1:该端口编辑器还会额外用一个多年沿用的固定端口历史上是56000方便工具发现。但真正干活的端口走上面这个 PID 公式。所以 IDE 的Attach to Unity下拉列表里能列出一堆可连目标靠的就是发现进程 → 拿 PID → 算端口这套而不是玄学。三、IDE 是怎么发现有哪些可连目标的列表里那些UnityEditor (本机)、“某台手机上的 Player”是通过两种发现机制凑出来的1. 本机进程扫描IDE 扫本地进程找到 Unity 编辑器 / 独立播放器进程读它们的 PID套上面的端口公式。本机目标就这么出现的。2. UDP 组播发现连手机/远程设备的关键开发版的 Unity Player 启动后会周期性地往局域网广播 UDP 组播包内容大致是我是一个可调试的 Unity Player 我的名字叫 xxx 我的 IP 是 192.168.1.23 我监听在端口 yyyyIDE 在同一网段监听这些组播包收到就把这台设备加进可 attach 列表。这就是为什么手机和电脑必须在同一局域网、且不能被 AP 隔离/防火墙挡住组播——挡了就发现不了设备。手机上的 Development Player │ 周期性 UDP 组播 │ 可调试! IP192.168.1.23 portyyyy 名字... ▼ ~~~~ 局域网 ~~~~ ▲ │ IDE 监听组播 电脑上的 VS / Rider │ └─ 收到 → 列表里出现这台手机 → 你点它 → 按 IP:port 连过去四、连上之后握手IDE 拿到IP:port发起 TCP 连接到 agent。连上第一步不是马上发命令而是握手对版本IDE ──TCP connect── Agent │ ├─ 双方交换一个 handshake 魔数/协议版本串 │ 确认这确实是个 soft debugger agent │ 且 wire protocol 版本兼容 │ ├─ 版本不匹配 → 断开调试器版本不兼容就是这里报的 │ └─ 匹配 → 进入正常会话握手成功后IDE 就开始发上一篇讲的那些命令查已加载的程序集、注册断点、订阅事件……连接建立和断点机制在这里接上了连上并握手 │ ▼ IDE: 把已加载的 assembly / type 信息给我 IDE: 在 Foo.cs:42 注册断点 ──► agent 落到序列点见上一篇 IDE: 订阅断点命中、线程启动、异常抛出等事件 │ ▼ 程序跑到断点 → SIGSEGV → agent 发命中事件 → IDE 停下来给你看五、attach 模式的特点不接管生命周期这里有个和传统调试器如 GDB launch 一个进程很不一样的点Unity 调试基本都是attach 模式——程序先自己在跑调试器中途接入。这意味着agent 从进程启动就一直在监听没连的时候游戏正常全速运行几乎无开销触发页都是可读状态你可以随时连、随时断开游戏不受影响继续跑断开连接时agent 会把所有断点清掉、触发页恢复可读游戏回到全速这也解释了一个现象你 attach 之前设的断点不会生效因为断点是 attach 之后由 IDE 注册进 agent 的断开后断点也随之失效。六、整条连接链路串起来① 被调试端准备好 agent Editor: 默认开着 Player: 需 Development Build Script Debugging IL2CPP: 没有这套走不通 │ ▼ ② IDE 发现目标 本机: 扫进程拿 PID 远程设备: 监听局域网 UDP 组播 │ ▼ ③ 确定连接地址 端口 56000 PID % 1000本机 或组播包里自带的 IP:port远程 │ ▼ ④ TCP 连接 握手对协议版本 │ ▼ ⑤ 会话建立注册断点、订阅事件 │ ▼ ⑥ 命中断点回到上一篇的 SIGSEGV 机制一句话总结“连上 Unity就是 IDE 通过 socket 连到 Unity 进程内常驻的 soft debugger agent。麻烦的不是连接本身而是发现目标——本机靠扫进程 PID 推算端口”远程设备靠监听 UDP 组播广播连上后握手对版本然后才开始注册断点、进入上一篇讲的断点流程。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价