开始使用

在客户端之间共享一个值、在它变化时收到通知,并发送一条所有人都处理一次的消息。

更新于 2026-09-10

安装

首先,通过 VCC(VRChat Creator Companion)把联网包添加到你的 Unity 项目。打开你项目的 vccproject.json 并添加包,或者使用 VCC 界面直接安装。

安装后,包在你的项目中可用,你就可以开始使用下面的联网 API 了。

共享一个值

public class Scoreboard : UdoniteBehaviour
{
    private Synced<int> score = new Synced<int>();

    public override void Interact()
    {
        score.Value = score.Value + 1;
    }
}

Synced<T> 是 behaviour 上的一个字段。写 .Value 就会存下并请求复制,不用记得调用序列化,也不用配一个同步模式的特性。

只有物体的所有者能写。 在不拥有该物体的客户端上赋值只会留在本地。如果谁都可以改,先取得所有权:

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

在它变化时收到通知

public override void Start()
{
    score.Subscribe(OnScoreChanged);
}

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

处理器会在每个客户端上跑,包括写入的那一个,所以显示只用写一处而不是两处。它在整批更新到达之后才跑,这在你有两个同步值时就有分别:处理器里读另一个同步值,读到的是同一批更新里进来的值,而不是之前的旧值。

处理器可以是 private。它是从你自己的 behaviour 里调用的,外面不需要能叫出它的名字。

发送一条消息

消息就是一个带着你要发送的字段的类:

public class Scored : NetworkEvent
{
    public int playerId;
    public int points;

    public override void Serialize(ByteWriter writer)
    {
        writer.WriteInt32(playerId);
        writer.WriteInt32(points);
    }

    public override void Deserialize(ByteReader reader)
    {
        playerId = reader.ReadInt32();
        points = reader.ReadInt32();
    }
}

发送它,并接收它:

public override void Start()
{
    Room.Subscribe<Scored>(OnScored);
}

public override void Interact()
{
    Room.Send(new Scored { playerId = 1, points = 10 });
}

private void OnScored(Scored message)
{
    Debug.Log(message.points + " to player " + message.playerId);
}

Room.Send 发给整个房间。 它是 static 的,所以在 behaviour 里和在普通类里都能调用。关于某一个物体的消息则在那个物体上流动,写成就是该物体的那个 behaviour 上的 this.Send,而那个需要拥有该物体。两者都在消息

谁都能发。 和同步值不同,不需要是所有者。所以消息适合“某人做了某事”,而变量适合“现在是什么状态”。

每个客户端按发送顺序各收到一次,包括发送的那个客户端。之后进来的人不会收到自己错过的部分,这正是你对事件的期待,也和你对值的期待相反。

谁发的

需要时多接一个参数:

private void OnScored(VRCPlayerApi sender, Scored message)
{
    Debug.Log(sender.displayName + " scored");
}

同一个消息类型可以用两种形式订阅,两种都会跑。多数处理器并不关心是谁发的,所以发送者没有出现在每个签名里。

接下来读什么

Synced<T> 的全部内容,包括数组和编译器唯一看不见的那种情况,在同步值。寻址、物体自己的通道,以及实际的流量开销,在消息

出了点问题 重新加载