你的第一个世界

一个任何人都能按的按钮和一个所有玩家都看到相同数字的计数器,从空项目到上传完成,大约十五分钟。

更新于 2026-09-13

你将做一个计数器:一个任何人都能按的方块,一个显示它被按了多少次的标签,并且每个玩家屏幕上的数字都相同,包括一小时后才进来的玩家。它会用到编译器、网络包和一个普通的 UI 标签,这已经是一个真实世界所做事情的大部分,只需要大约二十行 C#。

1. 安装

  1. 在 VRChat Creator Companion 中打开 Settings → Packages → Add Repository,粘贴 https://udonite.github.io/vpm/index.json,点击 Add
  2. 创建或打开一个世界项目。需要 Unity 2022.3 和 Worlds SDK 3.10 或更新版本。
  3. 在项目的包列表中添加 UdoniteUdonite Net

从这里开始,Udonite 会自动把你的 C# 编译成 Udon;Net 包提供计数器需要的同步值。

2. 搭建场景

  1. GameObject → 3D Object → Cube,命名为 Counter,放在玩家能碰到的位置。方块上的碰撞体就是它能被按的原因。
  2. GameObject → UI → Canvas,把 Render Mode 设为 World Space,缩小到可读的尺寸(缩放 0.005 是个合理的起点),放在方块上方。
  3. 在画布内 UI → Legacy → Text,命名为 Label,文本填 0。这里用旧版组件就够了,不需要导入任何东西。

3. 编写行为脚本

创建 Assets/Counter.cs

using Udonite;
using Udonite.Net;
using UnityEngine;
using UnityEngine.UI;

public class Counter : UdoniteBehaviour
{
    public Text label;

    private Synced<int> count = new Synced<int>();

    public override void Start()
    {
        InteractionText = "Press";
        count.Subscribe(OnCountChanged);
        label.text = count.Value.ToString();
    }

    public override void Interact()
    {
        Ownership.Claim(gameObject);
        count.Value = count.Value + 1;
    }

    private void OnCountChanged(int value)
    {
        label.text = value.ToString();
    }
}

撑起整个世界的是三件事:

  • Interact 在玩家按下物体时运行。它是 UdoniteBehaviour 的普通成员,所以名字拼错会是编译错误,而不是悄无声息地什么都不发生。
  • Synced<int> 是每个客户端都持有的计数。写入 .Value 会保存它并请求 VRChat 复制;后来加入的玩家无需任何人重发就能收到当前值。只有物体的所有者可以写入,这就是 Ownership.Claim 的用处:谁按下就成为所有者,然后写入。
  • Subscribe 在值到达时于每个客户端运行处理程序,包括写入它的那个客户端,因此标签只在一个地方更新。Start 里那行 label.text 覆盖第一次变化之前的时刻。

这里没有任何 Udon 专有语法。没有需要与同步模式配对的 sync 属性,没有需要记得调用的序列化方法,也没有需要避开的关键字清单。

4. 挂载并编译

  1. Counter.cs 拖到 Counter 方块上。
  2. Label 物体拖进检视面板的 Label 字段。
  3. 保存场景。

保存即编译。Udonite 会在 C# 组件旁挂上一个 Udon 程序;编译成功什么都不打印,Udon 无法运行的内容会在控制台被逐项点名,附带 UDN 代码和改写建议。Udonite → Open Window → Compile 会手动编译所有内容并打印一行摘要,在刚把脚本拖到物体上之后很有用。

5. 试一试

按下 Play。ClientSim 给你一个本地玩家;走到方块前按下它。标签会往上数,而 Udon 程序运行时 C# 组件是禁用的,所以你测试的就是将要发布的东西。

ClientSim 不运行序列化,因此在编辑器里计数是本地的。要看它穿过网络,在 SDK 控制面板用 Build & Test 开两个客户端:在一个里按下,另一个的标签会跟上。

6. 上传

像任何世界一样,从 VRChat SDK 控制面板构建并上传。发布出去的是 Udonite 挂载的 Udon 程序,C# 留在你的项目里等待下一次编辑。

接下来

  • 让计数在所有人离开又回来后仍然保留:Persistence
  • 计数超过一百时通知一个 Discord 频道:Net 包的消息,以及控制台里的托管中继。
  • 看看什么能编译:语言支持是那份清单,比你预想的长。
  • 当某些东西被拒绝时:诊断解释每一个代码。
出了点问题 重新加载