Tsuの雑記¯\_(ツ)_/¯

主に製作メモ・備忘録として使用。製作したアプリのリンクもあります。

【Unity】表示・非表示を SetActive で行うか enabled で行うか切り替える【拡張メソッド】

オブジェクトの表示・非表示を操作する時,SetActive() を実行するか enabled を書き換えるかで悩む事はないでしょうか。

今回は,どちらの方法で操作するかを簡単に切り替えられる拡張メソッドを作りました。

本稿では,UI.Canvas を使って御説明いたします。

(Unity 2018.3.0f2)

はじめに

オブジェクトの表示・非表示にSetActive()enabledのどちらを採るか,悩ましい問題だと思います。

SetActive()は,GameObjectそのもののアクティブ状態を切り替える関数です。

docs.unity3d.com

対してenabledは,GameObjectに含まれるコンポーネントの有効・無効を司る変数です。

docs.unity3d.com

オブジェクトの表示・非表示を操作するたびに,両方を試すのは大変ですよね。

そこで今回,これらを簡単に切り替える方法を考えました。

スクリプトの用意

まずは,拡張メソッド用のスクリプトを用意します。

unity3d.com

SetActiveOrEnable.cs

using UnityEngine;

/// <summary>
/// SetActive() 実行と enabled 代入を Inspector 上で切り替える
/// </summary>
public static class ShowHide
{
    // 表示・非表示方法の列挙
    public enum ShowHideMethod { SetActive, Enabled };
    // 表示・非表示方法の切り替え
    public static ShowHideMethod extensionShowHideMethod = ShowHideMethod.SetActive;

    /// <summary>
    /// オブジェクト表示・非表示
    /// </summary>
    /// <param name="behaviour">オブジェクトのコンポーネント</param>
    /// <param name="visibility">現すか隠すか</param>
    public static void SetActiveOrEnabled(this Behaviour behaviour, bool visibility)
    {
        // ShowHideMethod で分岐
        switch (extensionShowHideMethod)
        {
            // SetActive の場合
            case ShowHideMethod.SetActive:
                // SetActive の切り替え
                behaviour.gameObject.SetActive(visibility);
                break;
            // Enabled の場合
            case ShowHideMethod.Enabled:
                // enabled の切り替え
                behaviour.enabled = visibility;
                break;
        }
    }
}

これで,Unity 独自クラスであるBehaviourSetActiveOrEnabled()というメソッドを追加できました。

次に,この拡張メソッドの使用例を挙げます。

NewBehaviourScript.cs

// List<T> を使用するため
using System.Collections.Generic;
// LINQ を使用するため
using System.Linq;
using UnityEngine;
// UI を使用するため
using UnityEngine.UI;
// 拡張メソッドを使用するため
using static ShowHide;

public class NewBehaviourScript : MonoBehaviour
{
    // 表示・非表示方法の切り替え
    [SerializeField] ShowHideMethod showHideMethod = extensionShowHideMethod;
    // 表示・非表示方法を切り替えるオブジェクトリスト
    [SerializeField] List<Behaviour> behaviours = null;
    // タイトルキャンバス
    [SerializeField] Behaviour titleCanvasBehaviour = null;
    // 設定キャンバス
    [SerializeField] Behaviour settingsCanvasBehaviour = null;
    // 設定ボタン
    [SerializeField] Button settingsButton = null;
    // タイトルボタン
    [SerializeField] Button titleButton = null;

    void OnValidate()
    {
        // 表示・非表示方法の切り替えを反映
        extensionShowHideMethod = showHideMethod;
    }

    void Start()
    {
        // 初めに表示したいオブジェクト
        var startBehaviour = titleCanvasBehaviour;

        switch (showHideMethod)
        {
            case ShowHideMethod.SetActive:
                // リスト内のオブジェクトを全て enabled = true に
                behaviours.Select((Behaviour behaviour) => (behaviour.enabled = true)).ToList();
                // リスト内のオブジェクトを全て SetActive(false) に
                behaviours.ForEach((Behaviour behaviour) => behaviour.gameObject.SetActive(false));
                // 初めに表示したいオブジェクトのみ SetActive(true) に
                startBehaviour.gameObject.SetActive(true);
                break;
            case ShowHideMethod.Enabled:
                // リスト内のオブジェクトを全て SetActive(true) に
                behaviours.ForEach((Behaviour behaviour) => behaviour.gameObject.SetActive(true));
                // リスト内のオブジェクトを全て enabled = false に
                behaviours.Select((Behaviour behaviour) => (behaviour.enabled = false)).ToList();
                // 初めに表示したいオブジェクトのみ enabled = true に
                startBehaviour.enabled = true;
                break;
        }
    }

    /// <summary>
    /// Button に対応した挙動
    /// </summary>
    /// <param name="button">ボタン</param>
    public void OnClick (Button button)
    {
        if (button == settingsButton)
        {
            // タイトルキャンバスを非表示
            titleCanvasBehaviour.SetActiveOrEnabled(false);
            // 設定キャンバスを表示
            settingsCanvasBehaviour.SetActiveOrEnabled(true);
        }
        else if (button == titleButton)
        {
            // 設定キャンバスを非表示
            settingsCanvasBehaviour.SetActiveOrEnabled(false);
            // タイトルキャンバスを表示
            titleCanvasBehaviour.SetActiveOrEnabled(true);
        }
    }
}

解説

まずは拡張メソッドクラスであるShowHideを,using staticディレクティブで指定します。

docs.microsoft.com

これはShowHideを拡張クラスとするうえで,静的(static)にする必要があったためです。

/// <summary>
/// SetActive() 実行と enabled 代入を Inspector 上で切り替える
/// </summary>
public static class ShowHide

次に表示・非表示方法を Inspector 上で切り替えるため,showHideMethodを宣言します。

// 表示・非表示方法の切り替え
[SerializeField] ShowHideMethod showHideMethod = extensionShowHideMethod;

そして Inspector 上の操作をExtensionクラスのSetActiveOrEnabled()関数に反映させるため,Onvalidate()関数を使用します。

docs.unity3d.com

private void OnValidate()
{
    // 表示・非表示方法の切り替えを反映
    extensionShowHideMethod = showHideMethod;
}

これで,UI.Button による表示・非表示切り替えが可能となりました。

Inspector 上の showHideMethod 列挙型が SetActive の状態で表示・非表示を切り替えている画像
表示・非表示切り替えを SetActive() 関数で行っている例

リスト内オブジェクトの変数操作には,LINQSelect()関数を使用しました。

docs.microsoft.com

// リスト内のオブジェクトを全て enabled = true に
behaviours.Select((Behaviour behaviour) => (behaviour.enabled = true)).ToList();

リスト内オブジェクトの関数実行には,System.Collections.Generic のForEach()関数を使用しました。

docs.microsoft.com

// リスト内のオブジェクトを全て SetActive(false) に
behaviours.ForEach((Behaviour behaviour) => behaviour.gameObject.SetActive(false));

おわりに

この拡張メソッドは,飽くまで製作中の補助機能として考えました。

SetActive()enableのどちらが適切か分かった部分から,それぞれの命令に書き換えるべきかと思います。

以上,表示・非表示をSetActive()で行うかenabledで行うか切り替える拡張メソッドの御紹介でした。

Unity における似た処理を切り替える拡張メソッドは,他にも提案しております。

tsu-games.hatenablog.com

tsu-games.hatenablog.com