VRCStationに対して、「座っている」「座っていない」という状態を保持できる状態を作る話

概要

VRCSDK3のVRCStation に対して、今誰かが座っている、今誰かが座っていない、といった状態が欲しかったので、それらの仕組みをU#で作る上で、行ったアプローチの数々と最終的にどうしたか といったものが記述しています。正解かわかりませんが、こうすれば、一応作る事ができるといったものをまとめました。


対象

VRCStationを使用しているという状態が欲しくて渇望している人


開発環境

U#とSDKいずれも2020年5月くらいのタイミングで、実装されているものを使用。 なので、最新の場合だと変化している場合があるかもしれませんが、ちらっと見た感じはいけると思います。


事前知識

UdonGraphなどを、見てぼんやりこうかながわかる U#もしくはUnityでプログラムを書いた事がある SeiralizeFieldを使い方がわかる


作ろうと思ったきっかけ

きっかけは、座った状態の時に、OOが出来るといった。座っていないとできないものの制御を行うために VRCStationを調べてみたが、それっぽいのが、見つからなかったため。


作るもの

作るものとしては、「座っている」「座っていない」という状態を外部から判断が出来るもの。


目次

誤解回避のための事前共有

ここででてくる「VRCStation」は基本的には、VRC.SDKBaseの所にあるVRCStationです。 それらを継承したVRC.SDK3.ComponentsにあるVRCStationではありません。 以降VRCStationは、VRC.SDKBaseにあるVRCStationの事を指します。

また、VRCStationは、PrefabのVRCChair3というPrefabを使っています。 このPrefabについているVRCStationは、VRC.SDK3.Componentsの方ですが、VRCStationを継承されているため外部から取得する際は、VRCStationを取得しています。

成功したアプローチ

以下が最終的におちついた構成とそれぞれの処理。

まず、Hierachyの構成

f:id:herie270714:20201206135803p:plain
Hierachyの図

緑の部分がU#で作ったものをUdonBehaviorで使用したものです。

数字に書いているUdonSharpスクリプトのそれぞれのソースコードとしてはざっくり以下 (必要な処理だけ)

その1 VRCStationの状態を知りたいところ

[Serializefield]
private その3のクラス名;

public override Intaract()
{
     if(その3 のクラス名.IsSetting)
    {
        //座っていたらできるIntaract処理
    }
}

その2 VRCStationを降りるを行うもの

    [SerializeField]
    private その3のクラス名;

    void Start()
    {
        
    }

    public override void Interact()
    {
        if(null == sorting)
        {
            return;
        }
        その3のクラス名.OutExit();
    }

その3 VRCStationの状態を保持しているところ


    [SerializeField]
    private VRCStation station;

   public bool stationUsed;

   public override void Interact()
    {
        if(stationUsed)
        {
            return;
        }
        stationUsed = true;
        VRCPlayerApi api= Networking.LocalPlayer;

        station.UseStation(api);
        

    }

    /// <summary>
    /// 降りるためのもの
    /// </summary>
    public void OutExit()
    {
        stationUsed = false;


        VRCPlayerApi api = Networking.LocalPlayer;
        station.ExitStation(api);
    }

さらにVRCStationの設定で、Stationから外れる時は、かならず、その2のスクリプトが通るように以下の設定を行います。 DisableStationExit をtrue CanUseStationFromStation をfalse

で一応行えました。

失敗したアプローチ その1

VRCStationで提供されているstatic 関数の useStationDelegate 及び exitStationDelegateに対して、U#のUdonBehavior継承したクラスが欲しい処理を呼び出してもらうようにする。

結果:そもそもU#がdelegateを使用できないようで、うまくいかなかった。あとstaticなので、全体のVRCStationに絡んでくる可能性もあるので、早めに切り上げ。 UdonGraphでなら出来るかもしれないが、少なくともやりたくなかったので、今回は割愛。

失敗したアプローチ その2

VRCStationが提供されているboolで実装されている内容を見る。 提供されているboolは全部で3種類 - canUseStationFromStation (StationからStationへの移動が可能か) - disableStationExit (Stationを移動で降りる事が可能か?) - seated (座る状態に最適化するか?) の3種類があるが、いずれも、Stationを使用した時に対しての設定みたいなものだったため、今回の目的である、「座った」「座ってない」が外部からとれるものではなかった。

参考としては以下のURL

VRC_Station - VRChat Document 日本語訳 Wiki*

失敗したアプローチその3

アプローチとしては、VRC.SDKBase.VRCStationがabstractで継承されているので、それを継承して、オレオレVRCStationを作成して、それを欲しいところで使用する。

オレオレVRCStationはU#側がそもそも認識されないという状態(恐らくあくまでも、U#自体は、UdonBehaviorを継承していないクラスは、基本的には、VRCSDKクラスのみをサポートしているであろうため。) (もしかしたら、Githubに書いているかもしれない。)のため、U#上で使用できなかったため。

失敗したアプローチその4

Intaractを実装したUdonBehaviorを継承したクラスにSerializeFieldでVRCStationの参照だけ持ってきてあげてUseStationなどを使用して、行う。

ほぼほぼ正解に近かったものではあるのだが、単純に、Intaractを実装したゲームオブジェクトに対して、Coliderが存在しなかったため。(これは単純なミス)