ハツェの真時代傾向璋

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

誰でも操作できる同期uGUI - ドロップダウン編

こんばんは。ハツェです。
今回も同期uGUIについて書いていきます。
他の記事でも紹介していますが、この記事は全4つからなるシリーズです。

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

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

目次


追記

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

前回

前回はスライダーの同期について書きました。
hatuxes.hatenablog.jp

完成図

今回は下図(三人称視点)のドロップダウン部分を紹介します。
他のUIも別の記事で紹介しています。
上のテキストにvalueを、下のテキストにcaptionを表示しています。

f:id:hatuxes:20200416152638g:plain

スクリプト

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

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

public class Dropdown_Anyone : UdonSharpBehaviour
{
    Dropdown _dropdown;
    [SerializeField] Text _numText;
    [SerializeField] Text _contentText;

    [UdonSynced] int _value;

    void Start()
    {
        _dropdown = this.gameObject.GetComponent<Dropdown>();
    }

    void Update()
    {
        _dropdown.value = _value;
        _numText.text = _value.ToString();
        _contentText.text = _dropdown.captionText.text;
    }

    public void SetValue()
    {
        _value = _dropdown.value;
    }

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


部分解説

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

ChangeOwner

ChangeOwner()はEventTriggerのPointerDownで呼んでいます。
「EventTriggerって何?」と思った方は、ボタン・トグル編をご覧ください。

f:id:hatuxes:20200417170754p:plain

ボタンの時と実装は同じく、押し始めにその人がこのスクリプトのオーナーじゃなかったらオーナーにしてあげるようになっています。
また、EventTriggerでオーナーを移しているのは、少しでもオーナー移動時と変数代入時のフレームを分けるためです。

SetValue

SetValue()はDropdownのOn Value Changedで呼んでいます。

f:id:hatuxes:20200417170911p:plain

そのため、別の選択肢を選んだ時にSetValue()が呼ばれることになります。
SetValue()の中身は

_value = _dropdown.value;

だけなので、別の選択肢をクリックしたら、その要素番号を同期変数_valueに代入するといった処理のみになります。

選択肢の内容を取得する

_contentText.text = _dropdown.captionText.text;

Dropdownで選択している内容を表示させるにはリストからの取得とラベルからの取得があります。
現状、UdonではListを含むGenericには対応していないため前者の方法では取得できません。
そのため、ラベルからDropdownの内容を取得する方法を採用しています。

あとがき

ドロップダウン自体がVRChatでなじみが無いので、どういう風に使われるかに期待ですね。
ドロップダウンを使うのか、もしくはトグルグループが使われるのか見たいなところありそうですし...

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

次回

次回はInputFieldの同期についてお話ししますが、内容はほとんど同じです。
hatuxes.hatenablog.jp

誰でも操作できる同期uGUI - スライダー編

こんばんは。ハツェです。
今回もuGUIについての記事です。
他の記事でも紹介していますが、この記事は全4つからなるシリーズです。

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

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

目次


追記

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

前回

前回はuGUIを同期する方法とボタンによる同期の紹介をしました。
hatuxes.hatenablog.jp

完成図

今回は下図(三人称視点)のスライダー部分を紹介します。
他のUIも別の記事で紹介しています。

f:id:hatuxes:20200417174939g:plain

スクリプト

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

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

public class Slider_Anyone : UdonSharpBehaviour
{
    Slider _slider;
    [SerializeField] Text _text;

    [UdonSynced(UdonSyncMode.Linear)] float _value;

    void Start()
    {
        _slider = this.gameObject.GetComponent<Slider>();
    }

    void LateUpdate()
    {
        _slider.value = _value;
        _text.text = _value.ToString("F2");
    }

    public void SetValue()
    {
        _value = _slider.value;
    }

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


部分解説

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

ChangeOwner

ChangeOwner()はEventTriggerのBeginDragで呼んでいます。
「EventTriggerって何?」と思った方は、ボタン・トグル編をご覧ください。

f:id:hatuxes:20200417172133p:plain

スライダーに関してはPointerDownよりもBeginDragの方が都合がいいんですよね。
クリックした時だと、クリックしただけで動かさないなんて場合にもオーナーの移動が発生しちゃうので好ましくありません。
また、EventTriggerでオーナーを移しているのは、少しでもオーナー移動時と変数代入時のフレームを分けるためです。

SetValue

SetValue()はSliderのOn Value Changedで呼んでいます。

f:id:hatuxes:20200417172403p:plain

そのため、ハンドルを動かし始めた時にSetValue()が呼ばれることになります。
SetValue()の中身は

_value = _slider.value;

だけなので、ハンドルを動かし始めたら、その値を同期変数_valueに代入するといった処理のみになります。

LateUpdateである理由

今回紹介しているシリーズの中で唯一、SliderだけはこのLateUpdateを使っています。
どうしてかというと、SliderはuGUIの中で最もオブジェクトに触れ始める瞬間と値を更新し始める瞬間との間隔が短く、その間隔が一定でないUIだからです。
そのためUpdateで呼ぶと、On Value Changedと近いフレームで呼ばれてしまうため、オーナーが移る前にスライダーの値を更新してしまい、スライダーの値が初回時だけ反映されないという状況が発生してしまいます。
これを改善するためにUpdateの後に呼ばれるLateUpdateを使っています。

参考として、Unityの各イベントがどの順番で呼ばれているかについては、公式マニュアルをご覧ください。
docs.unity3d.com

あとがき

まとめると、オーナーの移す場所とLateUpdateを使うのがポイントということでした。
スライダーが同期すると出来ることが広がりそうですよね。
ちなみに完成図で上げているGif、SyncModeをLinearにしているので、同期の仕方が多少滑らかになっています。
(Linearで補間時にガクガクしちゃうのは、VRChatが悪い)

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

次回

次回はDropdownの同期についてお話ししますが、内容はほとんど同じです。
hatuxes.hatenablog.jp