UdonSharpでクラス間のデータ引き渡し


これは、UdonSharp_v0.15.4 での情報です。

VRChatが2018になった!

VRChatのバージョンアップにより、VRCSDK3が使えるようになりました。
目玉はなんと言ってもUdonというビジュアルプログラミングでしょう。
しかし、グラフをつないでいくのは便利なのかもしれませんが、
新しいことを覚えるのが苦手なおっさん族にはスクリプトください…という気分です。

そこででてきた、C#風に書けるUdonSharp!
思った以上にC#の知識が活かせてこれはいい

クラス単体で完結する系はかなり便利です。

クラス単体で完結するとは、他のUdonSharpのクラスと連携しないという意味です。
できないわけではないんですが…その説明をしていきます。

UDONSharp間でのデータ引き渡し

例えば、AのCubeをクリックすると、
Bのキューブに回るように指示する場合、こんな感じで書きます。
(このサンプルはUdonSharpの中にあります)

[SpinningCubes_5_Master]
UdonBehaviour udonRotateTarget;
private void Start()
{
    udonRotateTarget = (UdonBehaviour) cubeToRotate.GetComponent(typeof(UdonBehaviour));
}

private void Interact() //もともとはOnMouseDownだけど、VRC似合わせて書き換え
{
    udonRotateTarget.SendCustomEvent("DoRotate");
}

[SpinningCubes_5_Dependent]
public void DoRotate()
{
    isRotating = !isRotating;
}

private void Update()
{
    if (isRotating)
        transform.Rotate(Vector3.up, 60f * Time.deltaTime);
}

要は、BのUdonBehaviourを取り、SendCustomEventを呼び出します。
SendCustomEventは文字列を引数に取ることから、リフレクションで呼び出していて、
引数を与えることが出来ません。

素直にこう書けないの?という感じがしますが出来ません

private void Interact()
{
    // SpinningCubes_5_Dependent udonRotateTarget;
    udonRotateTarget.DoRotate();
}

現在、UdonSharpで使えるクラスや関数はホワイトリスト形式であり、
自分の作ったクラスは確実にホワイトリストにないので、
キャストや宣言することが出来ません。
そのうちできるようになるらしいですが…。

メンバー変数のアクセス方法はこんな感じです。

var data = (int) udon.GetProgramVariable("intdata");
udon.SetProgramVariable("intdata", 10);

しかし、これも注意で構造体は代入できません。
具体的にはVector3、Quaternionが代入できないので、
floatの配列を渡すという感じでいきましょう。

なお、SendCustomEventで呼び出す関数はpublicである必要がありますが、
GetProgramVariable/SetProgramVariable はprivateでも出来ます。
(ただ、いつ修正されてもいいように、publicにしておきましょう)

Instantiateの注意点

Instantiateを使う場合、VRCInstantiateを代わりに使います。
VRCInstantiateは生成したGameObjectが返ってきます。
ここで、すぐにtransformやgameObjectにアクセスするのは問題ありません。

しかし、UdonBehaviour にはアクセスしてはいけません。
UdonBehaviourの初期化は、Unityのイベントループを一周した後に行われます。
ですから、VRCInstantiateの後にUdonBehaviourにデータを渡したり
関数を呼び出したりする場合は次のフレーム以降に行う必要があります。