网络

同步字段、自定义事件、类型化网络事件,以及 NetworkTransform 组件。

更新于 2026-09-03

Udonite 底层直接使用 VRChat 自己的网络机制,规则和任何 Udon behaviour 完全一样:只有 GameObject 的所有者才能写入它的同步状态,而且只有 public 方法才能跨网络调用。

同步字段

给字段加上 [UdonSynced],并设置 behaviour 的同步模式:

using Udonite.Package.Runtime;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon.Common;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class Counter : UdoniteBehaviour
{
    [UdonSynced] public int count;

    public override void Interact()
    {
        if (!Networking.IsOwner(gameObject))
            Networking.SetOwner(Networking.LocalPlayer, gameObject);

        count = count + 1;
        this.RequestSerialization();
    }

    public override void OnDeserialization(DeserializationResult result)
    {
        Debug.Log("count is now " + count);
    }
}
  • BehaviourSyncMode.Manual 只在你调用 this.RequestSerialization() 时发送。Continuous 会自动发送,None 则完全不同步。
  • [UdonSynced(UdonSyncMode.Linear)]Smooth 会在接收端对数值字段做插值。
  • OnPreSerializationOnPostSerializationOnDeserialization 会在每次传输前后触发。

响应变化

[FieldChangeCallback] 指定一个属性,每当该字段的同步值到达时,就会执行这个属性的 setter:

[UdonSynced, FieldChangeCallback(nameof(Lit))]
private bool lit;

public bool Lit
{
    get => lit;
    set
    {
        lit = value;
        lamp.SetActive(value);
    }
}

属性的类型必须与字段的类型完全一致。

自定义事件

任何 public 方法都可以按名称发送给其他客户端:

this.SendCustomNetworkEvent(NetworkEventTarget.All, nameof(Ring));

public void Ring()
{
    bell.Play();
}

NetworkEventTarget.Owner 只发送给该对象的所有者。SendCustomEventDelayedSecondsSendCustomEventDelayedFrames 会把一次本地调用推迟到之后执行。

类型化网络事件

如果负载需要结构,可以定义一个带 SerializeDeserialize 的事件类,并在接收方的 behaviour 上放一个处理方法:

using Udonite.Package.Runtime;
using UnityEngine;

public class ScoreEvent : NetworkEvent
{
    public int player;
    public int score;

    public void Serialize(ByteWriter writer)
    {
        writer.WriteInt32(player);
        writer.WriteInt32(score);
    }

    public void Deserialize(ByteReader reader)
    {
        player = reader.ReadInt32();
        score = reader.ReadInt32();
    }
}

public class Scoreboard : UdoniteBehaviour
{
    public void Award(int player, int score)
    {
        ScoreEvent evt = new ScoreEvent();
        evt.player = player;
        evt.score = score;
        Udonite.Network.Send(evt, this);
    }

    [NetworkEventHandler]
    public void OnScore(ScoreEvent evt)
    {
        Debug.Log("player " + evt.player + " scored " + evt.score);
    }
}

Udonite.Network.Send(evt, receiver) 会把事件序列化,并在每个客户端上投递给 receiver 上那个以该事件类型为参数的 [NetworkEventHandler] 方法。请写完整的限定名:在有 using UnityEngine; 的作用域里,单独的 Network 会和 Unity 已废弃的 UnityEngine.Network 冲突。它依靠同步字段传输,因此只有当 receiver 所在 GameObject 的所有者调用时,才会到达其他客户端。

NetworkTransform

NetworkTransform 是一个开箱即用的 behaviour,用于同步位置、旋转和缩放,并带有插值与瞬移检测。把它加到物体上,编译,然后移动物体即可。如果同一物体上还有 VRC_Pickup,那么拾起时会取得所有权,放下时会发送静止时的姿态。发送频率、各通道的阈值以及瞬移判定距离都是 Inspector 上的字段。

所有权

重写 OnOwnershipRequest 并返回 false 即可拒绝所有权转移。OnOwnershipTransferred 会在所有者变化时于每个客户端触发。ClientSim 不会触发所有权请求,这部分请在已上传的世界里测试。

Something went wrong. Reload