ネットワーク
同期フィールド、カスタムイベント、型付きネットワークイベント、そして NetworkTransform コンポーネント。
Udonite は内部で VRChat 自身のネットワーク機能を使います。規則は通常の Udon ビヘイビアと同じです。GameObject の同期状態を書き換えられるのはそのオーナーだけで、ネットワーク越しに呼べるのは public メソッドだけです。
同期フィールド
フィールドに [UdonSynced] を付け、ビヘイビアの同期モードを設定します。
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は、受信側で数値フィールドを補間します。OnPreSerialization、OnPostSerialization、OnDeserializationが転送の前後に呼ばれます。
変更に反応する
[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 はそのオブジェクトのオーナーにだけ送ります。SendCustomEventDelayedSeconds と SendCustomEventDelayedFrames は、ローカルでの呼び出しを後回しにします。
型付きネットワークイベント
構造のあるペイロードを送りたいときは、Serialize/Deserialize の対を持つイベントクラスを定義し、受信側のビヘイビアにハンドラを置きます。
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 は、位置・回転・スケールを補間とテレポート検出つきで同期する、そのまま使えるビヘイビアです。オブジェクトに追加してコンパイルし、動かすだけです。同じオブジェクトに VRC_Pickup があれば、持ち上げるとオーナーシップを取得し、放すと静止した姿勢を送ります。送信レート、チャンネルごとのしきい値、テレポート判定距離はインスペクタのフィールドです。
オーナーシップ
OnOwnershipRequest を override して false を返せば、移譲を拒否できます。OnOwnershipTransferred はオーナーが変わったときに全クライアントで呼ばれます。ClientSim はオーナーシップの要求を発火しないため、その確認はアップロードしたワールドで行ってください。