9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Unity初心者必見】Toggle(Group)のOnValueChangedでハマった話

Posted at

初めに

ToggleのOn/Offの切り替え時にメソッドを呼び出したいとき、OnValueChangedにメソッドをAddListenerすることが多いと思う。
これと同じように、複数のToggleをToggleGroupで管理してOn/Offの切り替え時にメソッドを呼び出そうとした時、微妙な挙動の違いでメソッドが複数回呼び出されてハマったのでメモしておく。

環境

Unity:2019.1.5f1

起こったこと

設定は以下のスクショの通り。
Toggle3つ(A,B,C)をToggleGroupで管理し、どれか一つのみにチェックが入るようになっている。
スクリーンショット 2021-01-10 22.43.38.png

ToggleGroupには以下のコードをアタッチ

ToggleController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;

public class ToggleController : MonoBehaviour
{
    public void Change()
    {
        Toggle activeToggle = this.gameObject.GetComponent<ToggleGroup>().ActiveToggles().First();
        Debug.Log(activeToggle.name);
    }
}

各ToggleのOnValueChangedにChangeメソッドをインスペクタからアタッチする。
すると、次のような挙動をする。
画面収録-2021-01-10-23.05.17.gif
メソッドが2回呼び出されているようだ。
これは、例えばB→AとToggleを切り替える時
BがOffになる時のOnValueChangedとAがOnになる時のOnValueChangedが両方動いてしまうことが原因である。
つまりOnValueChangedはチェックマーク(isOn)がついた時ではなくToggleの状態が変わった時に発火するようだ。

対処法

コードを次のように修正した。
なお、特に大差はないがスクリプトからメソッドをAddListenerした。

ToggleController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;

public class ToggleController : MonoBehaviour
{
    public ToggleGroup toggleGroup;

    private void Start()
    {
        var toggles = toggleGroup.gameObject.GetComponentsInChildren<Transform>();
        foreach (var toggle in toggles)
        {
            if (toggle.GetComponent<Toggle>() != null)
            {
                toggle.GetComponent<Toggle>().onValueChanged.AddListener(Change);
            }
        }
    }

    public void Change(bool state)
    {
        if (state)
        {
            Toggle activeToggle = this.gameObject.GetComponent<ToggleGroup>().ActiveToggles().First();
            Debug.Log(activeToggle.name);
        }
    }
}

変更点はChangeメソッドに引数を持たせたことである。
実際はこのメソッドは2回呼び出されているのだが、引数のstateでToggleにチェックが入っているかどうかを判断しているため、中の処理が行われるのは1回になる。

すると次のような挙動になる。
画面収録-2021-01-10-22.54.51.gif

まとめ

  • ToggleGroupのToggleのOnValueChangedを使うときは、処理が重複しないよう注意が必要
  • やりたい処理に応じて2つの挙動を使い分けることが大事
  • Toggleにはあまり複雑な処理を持たせない方が良い気もする
  • 頑張ればButtonでもできる

最後に

ここまで読んでいただきありがとうございました。
投稿者はまだまだUnity初心者のため、アドバイスやコメント等あればお待ちしております。
この記事が何かのお役に立てれば幸いです。

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?