ハツェの真時代傾向璋

興味を持ったことを書いていく鱗片的な場所から先の未来の場

誰でも操作できる同期uGUI - ボタン・トグル編

こんばんは。ハツェです。
この間は入門記事を投稿しまして。
たくさんの人に読んでもらったみたいで大変驚いています。
今回は、誰でも入力できるuGUIはいつか必要となる日が来ると思うので、サンプルを公開していきます。
全4つからなるシリーズで投稿していきたいと思いますので、よろしくお願いします。

  1. ボタン・トグル編
  2. スライダー編
  3. ドロップダウン編
  4. テキスト入力編

今回の動作環境は、Unity : 2018.4.20f1、VRCSDK : 2020.04.09.16.59、U# : v0.15.5です。

目次


追記

当記事は少し古めの物になります。
使用する際は、ContinuousSyncの手法にてお試しいただけますと正常に動作するかと思います。
予めご了承ください。

完成図

今回は下図(三人称視点)のボタンとトグルの部分を紹介します。
他のUIも別の記事で紹介しています。

f:id:hatuxes:20200416133821g:plain

オーナーはどの部分で渡せばいいのか

変数同期をする際に一度は考える部分だと思います。
現状の環境だと、

  • Syncをつけた変数は、そのUdonBehaviorのオーナーにしか変更できない
  • (現状)オーナーを渡すのと変数を書き換える動きが同フレームで出来ない

という状態なので、どこかしらでオーナーを渡すフレームと変数に代入するフレームを分ける必要があります。
そこで使うのが、Event Triggerになります。

Event Trigger

EventTriggerはUnityのコンポーネントの一つで、主にuGUIでの使用を想定したトリガーです。
スクロールした時やクリックした時といった瞬間に任意の関数を実行出来たりするものです。
所謂On Clickなどの拡張版みたいな感じだと思っていただければ大丈夫です。
EventTriggerの使い方等は以下の記事が参考になるかと思います。
tech.pjin.jp

スクリプト

実装に使ったスクリプトはこちらになります。

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

public class Button_Anyone : UdonSharpBehaviour
{
    Button _button;
    [SerializeField] Text _displayText;

    [UdonSynced] bool _result;

    void Start()
    {
        _button = this.gameObject.GetComponent<Button>();
    }

    void Update()
    {
        _displayText.text = _result.ToString();
    }

    public void Pressed()
    {
        _result = !_result;
    }

    public void ChangeOwner()
    {
        if (!Networking.IsOwner(Networking.LocalPlayer, this.gameObject)) Networking.SetOwner(Networking.LocalPlayer, this.gameObject);
    }
}


部分解説

ちょっと説明が無いので、解説をいくつかしていきます。
今回は、_resultがboolの同期変数です。

ChangeOwner

ChangeOwner()はEventTriggerのPointerDownで呼んでいます。

f:id:hatuxes:20200416135608p:plain

PointerDownはUIを押した瞬間に呼ばれるイベントです。
そのため、押し始めにその人がこのスクリプトのオーナーじゃなかったらオーナーにしてあげるようになっています。
また、EventTriggerでオーナーを移すことで、オーナー移動時と変数代入時でフレームを分けることが可能となります。
なので、少しゆっくりボタンを押してもらえばPointerDownOn Clickでフレームがずれるので、初動から結果を反映することが出来ます。(瞬間的にクリックすると初動が反映されませんけどね)

Pressed

Pressed()はButtonのOn Clickで呼んでいます。

f:id:hatuxes:20200417180706p:plain

そのため、ボタンを押した時にPressed()が呼ばれることになります。
Pressed()の中身は

_result = !_result;

だけなので、クリックしたらboolを反転し、それを同期変数_resultに代入するといった処理のみになります。

あとがき

結局どこでオーナーを移すかというだけの話でした。
EventTriggerがVRChatで使えたのは少し意外だったので、記事にしてみました。
ちなみにトグルの方も実装方法はほとんど一緒です。
困った場合には、Githubにトグルのコードも載せているのでそこを確認してもらえばと思います。

今回を含む同期uGUIのサンプルはまとめてGithubに置いてあります。
ライセンスを確認したうえで、お使いください。
github.com

次回

次回はSliderの同期についてお話しします。
hatuxes.hatenablog.jp