【Doozy UI】UI ToggleとUI Toggle Groupの覚え書
概要
前回の記事に続き、ゲームエンジンUnityのUI構築の効率アップと管理に適したAssetであるDoozy UIを使ってみた事で発生したつまづきや気づきをまとめた記事です。同じ内容でつまづくことがあった際のご参考にどうぞ。
今回は、表題のとおりUI ToggleとUI Toggle Groupについてです。なお、当記事では以降Doozy UI上で"UI element"と呼ばれるものをUIパーツと呼称します。
なお、当記事で取り上げているDoozy UIはversion 4.3.1のものです。(3以前とは互換が無いとのことをご了承ください。)
UI Toggleとは
Doozy UIの提供するUIパーツのうち、ON/OFFの切り替え機能を持つUI Button、もしくはDoozy UIが提供する同名のコンポーネントです。UnityにおいてはuGUIの(RectTransformを持つ)GameObjectで、一般的なUI開発などにおけるチェックボックス(チェックボタン)と同等の役割をもつボタンと考えることが可能です。
また、UI ToggleにはUI Toggle Groupと呼ばれる兄弟UIパーツがあり、これと組み合わせて使用することで、一般的なUI開発におけるラジオボタンと同等の役割を持たせることも可能です。
UI ToggleのTips
本題です。順不同で気づきのあったものをテーマ別に列挙しています。
UI Toggle(UI Button)が判定しなくなった
UI Container系のコンポーネント(例:UI View)を持つGameObjectが親(祖先)に置いてみると解決しました。そういったGameObjectが存在しない場合、つまり単にUI ToggleをGameObjectにアタッチしても、Intaractableがチェックされているにも関わらずIntractableが不可となるケースが存在します。厳密にはInput Systemからの操作は受け付けなくなりInspectorやScriptからの操作は可能なのですが・・・。
UI Toogle GroupのControll Modeプロパティ
一見すると違いがわからなかったのでメモ。
- Passive : 配下のUIToggle全てが自由にON/OFFすることを許容(複数同時ON、全OFFも可能)
- One Toggle On : 配下のUIToggleは全てOFFもしくはどれかひとつだけON
- One Toggle On Enforced : 配下のUIToggleは必ずどれかひとつだけON(全OFF禁止)
- Any Toggle On Enforced : 配下のUIToggleは複数同時ONは許容するが、全OFF禁止
UI Toggle のisOnの挙動
isOnはクリックされたらチェックが入りON(=true)に、もう一度クリックするとチェックがハズレOFF(=false)になります。ただし、UI Toggle Groupでグループ化されているUI Toggle同士は取りまとめているUI Toogle GroupのControll Modeに設定されている値いかんによっては挙動が変化します。
例えば、UI Toogle GroupのControll ModeプロパティがOne Toggle On Enforcedとなっている場合は、OFFのUI Toggleをクリックすると今までONだった別のUI Toggleが強制的にOFFにかわります。
また、ここでいうクリックしたとは、Pointer Down → Pointer Upの一連の流れがGameObject上にPointerがある上で全て完了したことを指します。このためPointer Downをした後にマウスをドラッグしてGameObjectの範囲外に飛び出てPointer Upを行うとクリックした判定にはなりません。(UISelectable Color AnimatorのPressedには該当するのにSelectedには該当しないという罠があるので注意。)
UI Toggle GroupのisOnの挙動
UI Toggle GroupについているisOnの挙動は次のとおりです。
- 配下のToggleが1つでもONになればON
- 配下のToggleが全てOFFならOFF
- スクリプトやInspectorから強制ONしても配下のToggleはONにならない
- スクリプトやInspectorから強制OFFしても配下のToggleはOFFにならない
注意すべきは2の挙動で、UI Toggle GroupがOFFに変化する(OFFで上書きされる)のは配下のONになっている最後のToggleがOFFになった瞬間だけでなく、配下のToggleがOFF→OFFになる際であっても条件が発動することです。このため、UI Toggle Groupのcallbackに配下のUI ToggleをOFF(=isOnをfalse)にする処理を設定すると、UI Toggle GroupのisOnがfalse→callbackで配下のUI ToggleのisOnをfalse→上記2が発動→callbackで・・・という形で無限ループが発生し、StackOverFlowします。
UI ToggleをまとめてON/OFFにする
結論から先に話すと「機能としては存在しない」ため、スクリプトで制御する必要があります。
using UnityEngine;
using Doozy.Runtime.UIManager.Components;
public class UIToggleGroupExtentions : MonoBehaviour
{
private UIToggleGroup group;
void Start()
{
group = gameObject.GetComponent<UIToggleGroup>();
}
public void AllToggleOff()
{
if(group==null) return;
foreach( UIToggle toggle in group.toggles)
{
toggle.isOn = false;
}
}
public void AllToggleOn()
{
if(group==null) return;
foreach( UIToggle toggle in group.toggles)
{
toggle.isOn = true;
}
}
}
UI ToggleとUI Selectable Color Animator利用時のUI Selectable Color AnimatorのControllerプロパティにあるプルダウンの挙動
- on - Controller指定先のUI ToggleのisOnがonの際に状態変化に反応する
- off - Controller指定先のUI ToggleのisOnがoffの際に状態変化に反応する
- any - Controller指定先のUI ToggleのisOnがon/offどちらであっても状態変化に反応する
ここでいう状態変化とは、Normal/Highlight/Pressed/Selected/Disableのことです。なお、UI ToggleをアタッチしたGameObjectをクリックした(on→offもしくはoff→onへの変化)時は、上記設定がon,off,anyいずれであっても状態変化が発動しています。
UI ToggleがOnになっている時だけ状態を変える方法
例えば、ボタン色などをOnになっている時だけ別色に変更したい時などどのように設定すれば良いのでしょう?
答えは、UI Selectable ○○ Animatorのコンポーネントを2個アタッチし、それぞれのControllerプロパティをonとoffとで分け、2種類のAnimaton設定を行えば良いでしょう。
プリセットのToggleをHierarchyに設置して中身をのぞいてみるとそうなっていました。サンプルをよくみることは大事ですね!
UI Toggle GroupのfirstToggleを取得する
スクリプトなどからUI Toggle Groupの配下にあるUI Toggleのうち、"先頭"のUI Toggleを取得したいケースでは次のいずれかの方法で参照することが可能です。
- UI Toggle GroupのfirstToggleフィールド - UI Toggle GroupコンポーネントのfirstToggleプロパティに代入されているUI Toggleを参照する
- UI Toggle GroupのGetFirstToggle()メソッド - UI Toggle Groupのtogglesフィールドの0番目に該当するUI Toggleを参照する。
注意すべきは2番の挙動です。この0番目に該当するUI Toggleは、もしかするとあなたの想定している"先頭"でないケースがあります。(公式のドキュメント読んでも配下のUI Toggle達がどのようにリスト化されているかも見つからず、お手上げ。)
ということで、"先頭"のUI Toggleが確実に欲しいときは、UI Toggle GroupのfirstToggleフィールドにきちんと先頭対象のUI Toggleを代入した上で参照を行う1の方法をおすすめします。
終わりに
いや、つまづき多いな・・・。
まぁ、こんなアセットもあるよーという感じに思っていただければと存じます。
内容については、気が向いた時にいつの間にかアップデートするかもしれません。
Discussion