世界日志

从 Unity Console 盯着一个正在跑的世界,以及一个出错的 behaviour 长什么样。

更新于 2026-09-08

世界一离开 Editor,Unity 的 Console 就什么都看不见了。Play 模式是日志最后一处好读的地方,可世界并不在 Play 模式里坏掉——它坏在有八个人的时候,在别人的网络上,在你一小时前上传的那个版本里。

Udonite → Open Window → Settings → Logging 会在你身处世界之中时读客户端的日志,把你的行放回 Console。

三个设置,其实是一个

选择 转发什么
关闭 什么都不
Udonite 日志 只有用 Log 写的行
全部日志 连客户端自己写的也算,那是相当大的一堆

默认是 Udonite 日志。监听只读不写,而且只要世界没在跑、没在写日志,它就什么都不转发。

全部日志 在一次读取里到 200 行就停下,并告诉你丢了多少。热闹的世界一次就能甩回来几千行,而 Console 远在拒绝它们之前就已经慢得像在爬。

如果没在 VRChat 自己的设置里打开完整日志,这里什么都不会来。Console 一片空白,最常见的原因就是这个。

转发过来的行,就是你写的那一行

[combat] [Scoreboard.Award:14] hit for 3

Play 模式里看到的是它,真实世界里看到的也是它。路上什么都不加:没有时间,没有级别词,没有颜色,没有过滤。

这是有意为之,不是没做完。一行字要是因为跑在哪里而有两种读法,它就没法和自己比对,而比对正是转发它的全部理由。时间也没丢——客户端在自己的文件里给每一行都盖了时间,Console 也盖自己的。

不止一个客户端

要测试联机,就得在同一台机器上、用同一个账号开两个客户端。两边的显示名一样,世界也无法告诉你某一行来自哪个窗口。

客户端自己把这件事解决了:每个客户端都写自己的日志文件。所以从第二个客户端开口的那一刻起,Console 就开始编号。

[client 1] [Scoreboard.Award:14] hit for 3
[client 2] [Scoreboard.Award:14] hit for 5

只有一个客户端在说话时,什么都不会被编号。 一个永远只写着 client 1 的前缀谁也告诉不了,却要占掉每一行那么宽。

编号按谁先写日志排,而不是按谁先启动:一个启动后停在加入界面的客户端,对看着 Console 的人来说不是 client 1。

已经在 Console 里的行不会因为第二个客户端出现而重新标注。重新标注做不到,事后猜测比让它们保持原样更糟。

当一个 behaviour 出错

这是 Udon 世界里最糟也最安静的一件事。VM 抛出异常,客户端接住,写一行,然后把那个 behaviour 在这一整局里禁用掉。此外什么都不会发生。门就是不动了,世界照旧在它周围转。

Console 会把这件事报出来:

An Udon behaviour faulted and is disabled for the rest of the session.
System.NullReferenceException: Object reference not set to an instance of an object (program counter 812)

程序计数器是编译后程序里的地址,不是你源码的行号。 要把它换算过来,需要一张从地址到源码的对照表,而 Udonite 目前不生成这张表。所以它不去猜,原样把客户端写的传过来。光是这条消息点到的东西,通常已经够你找到调用的地方了;再配上你自己撒在周围的那些 Log,就能看出这个 behaviour 走到了哪一步。

客户端随后写的几百行栈转储和堆转储,就留在它们该待的地方——那个文件里。

出了点问题 重新加载