yu00’s blog

プログラミングに関する備忘録です

UdonSharpのイベント同期で複数の引数を渡す

はじめに

VRChat UdonSharpの同期手法であるSendCustomNetworkEvent
は関数に引数を渡すことができません。
そこで、変数同期を使い疑似的に、複数引数を持つ関数を
同期する手法について説明します。

コード

以下は関数SendMyEvent1, SendMyEvent2を同期する例です。

using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using UnityEngine.UI;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)]
public class EventMultiArgs : UdonSharpBehaviour
{
    public Text Text1;
    public Text Text2;

    [UdonSynced]
    public bool EventFlag1;
    [UdonSynced]
    public bool EventFlag2;
    [UdonSynced]
    public int Arg1;
    [UdonSynced]
    public int Arg2;
    [UdonSynced]
    public int Arg3;

    bool EventFlag1Sub;
    bool EventFlag2Sub;
    int Arg1Sub;
    int Arg2Sub;
    int Arg3Sub;

    bool PrevEventFlag1;
    bool PrevEventFlag2;

    int Cnt;
    int Cnt2;

    public void OnClick1()
    {
        if (!Networking.LocalPlayer.IsOwner(gameObject))
        {
            Networking.SetOwner(Networking.LocalPlayer, gameObject);
        }
        Cnt++;
        SendMyEvent1(Cnt, Cnt+1);
    }
    public void OnClick2()
    {
        if (!Networking.LocalPlayer.IsOwner(gameObject))
        {
            Networking.SetOwner(Networking.LocalPlayer, gameObject);
        }
        Cnt2++;
        SendMyEvent2(Cnt2);
    }

    public void SendMyEvent1(int arg1, int arg2)
    {
        Arg1Sub = arg1;
        Arg2Sub = arg2;
        EventFlag1Sub = !EventFlag1Sub;
        RequestSerialization();
    }
    public void SendMyEvent2(int arg3)
    {
        Arg3Sub = arg3;
        EventFlag2Sub = !EventFlag2Sub;
        RequestSerialization();
    }
    public override void OnPreSerialization()
    {
        EventFlag1 = EventFlag1Sub;
        EventFlag2 = EventFlag2Sub;
        Arg1 = Arg1Sub;
        Arg2 = Arg2Sub;
        Arg3 = Arg3Sub;
        UpdateText();
    }
    public override void OnDeserialization()
    {
        UpdateText();
    }
    private void UpdateText()
    {
        if (EventFlag1 != PrevEventFlag1)
        {
            Text1.text = $"Arg1:{Arg1}, Arg2:{Arg2}";
            PrevEventFlag1 = EventFlag1;
        }
        if (EventFlag2 != PrevEventFlag2)
        {
            Text2.text = $"Arg3:{Arg3}";
            PrevEventFlag2 = EventFlag2;
        }
    }
}

Unityプロジェクトは以下にあります。
https://github.com/hide00310/UdonSharp_EventMultiArgs

以下順番でコードが実行されます。

  1. ボタンを押すとOnClick1, OnClick2が呼ばれる
  2. ローカルでSendMyEvent1, SendMyEvent2が呼ばれる
  3. 関数の引数に対応する同期変数Arg1Sub\~Arg3Subを設定する
  4. イベント発火用の同期変数EventFlag1Sub, EventFlag2Subを設定する
  5. ローカルで同期時にOnPreSerializationが呼ばれる
  6. Arg1\~Arg3,EventFlag1, EventFlag2を設定し同期する
  7. ローカルで設定された引数をテキストに表示
  8. (ローカル以外の)ネットワークで同期時にOnDeserializationが呼ばれる
  9. ネットワークで設定された引数をテキストに表示

バージョン

Unity : 2019.4.31f1
VRChat SDK : 3.1.10
UdonSharp : 1.1.6