【Unityボタン完全攻略】ボタンの設計方法を解説!標準にない長押し判定のサンプルあり

ころもちゃん

ボタンを使っていろんな処理をしてみたいけど、どうやって作ったらいいんだろう?

本記事の内容

・ボタンの導入方法
・出来てしまうけど、やらない方がいい作り方を紹介
・ボタンを使う時のTIPS

この記事は初心者~中級者向けの簡易な解説記事です。大規模ゲーム開発現場で使える最適な設計というより、個人で作る小規模ゲームに適した設計で解説しています。(より深く知りたい人は、MVPパターン で検索してください)

目次

ボタンの導入方法

ボタンを作る時の流れ

ボタンを作って、ボタンを押した時に処理が実行されるようにするには、以下の手順を踏みます。

1.キャンバス配下にボタンを配置
2.ボタンを押した時の処理をボタンと紐付ける

キャンバス配下にボタンを配置する

ヒエラルキーウィンドウで右クリックし、ボタン-TextMeshProを選択します。
もしキャンバスが作られていない場合は、自動で作成されると思います。

デフォルトのボタンのImageは、本当に何もない簡素なボタンなので、お好みの画像にしましょう。素材の集め方は以下の記事で解説しています。

差し替えた画像に合わせてTransformも修正しましょう。デフォルトのボタンサイズはとても小さいので大きくしましょう。

Transformを150*150に設定

こんなボタンが出来ました。

ボタンを押した時の処理をボタンと紐付ける方法

次にこのボタンを押したときの処理を入れる方法です。こちらは2つの方法がありますが後者のやり方を紹介します。

  • 方法1:ボタンコンポーネントの「クリック時」に実行したい処理をアタッチする
  • 方法2:スクリプトからボタンとの紐づけを作成する(推奨!)

前者のやり方は、ボタンコンポーネントにある、「クリック時」にスクリプトをアタッチする方法です。初心者向けの解説でよく見る方法です。

ただ、このやり方はオススメしません。

エラーが起きた時に、普通はスクリプト(プログラム)を確認します。
しかし、この実装を行っていると、スクリプト+ボタンの設定を確認する必要があるため、バグを発見しずらくなり、メンテ性があまりよくありません。

なので、「スクリプトからボタンとの紐づけを作成する」方法を紹介します。

ボタンを押したら実行するスクリプトのサンプル

ではサンプルのスクリプトを作成してみます。今回もChatGPTに作成してもらいます。

ChatGPTへのプロンプト
unityのスクリプトを作成しています。 ボタンを押したら、指定したゲームオブジェクトをアクティブにするスクリプトを作成してください。 ボタンにはリスナーをつけてください。
クラス名はUIManagerとしてください。

using UnityEngine;
using UnityEngine.UI; // UIコンポーネントを使用するために必要

public class UIManager : MonoBehaviour
{
    public Button myButton; // エディタからアサインするボタンの参照
    public GameObject gameObjectToActivate; // アクティブにするゲームオブジェクトの参照

    void Start()
    {
        // ボタンのonClickイベントにリスナーを追加
        myButton.onClick.AddListener(ActivateObject);
    }

    // ゲームオブジェクトをアクティブにするメソッド
    void ActivateObject()
    {
        gameObjectToActivate.SetActive(true); // ゲームオブジェクトをアクティブにする
    }

    void OnDestroy()
    {
        // オブジェクトが破棄された時にリスナーを削除する(重要)
        myButton.onClick.RemoveListener(ActivateObject);
    }
}

この中の、myButton.onClick.AddListener(ActivateObject);の箇所が、ボタンコンポーネントにメソッドをアタッチするのと同じことをスクリプトで実行する処理です。Startに入れるのがよいでしょう。

そして出来上がったスクリプトを、空のGameObjectにアタッチします。ヒエラルキーウィンドウで空のオブジェクトを選択し、

コンポーネントをアタッチします。

今回のスクリプトは、ボタンを押したら、指定したGameObjectをActiveにするメソッドなので、「どのオブジェクトを対象とするか」をインスペクタウィンドウから追加します。対象のオブジェクトは適当に赤いパネルを作って割り当てています。

この状態でゲームを実行してみます。ボタンを押したら赤いパネルがActiveになりました!

このように、どこにどのボタンを配置するかを決め、ボタンにどんな処理を行わせるかは、プログラムで行うというのがボタン作成の流れになります。
また、ボタンを押した時の処理を、ChatGPTに手助けしてもらうというのが賢い使い方ではないでしょうか。

Unityのボタン機能を実装するときに気をつけること!

UnityでUIは比較的簡単に作れるように出来ています。しかし、初心者向け解説本などに書いている内容をそのまま使い続けると思わぬ困ったことが頻発します。

実際の開発現場だと、Unity標準のボタンを使わないことも多いそうです。ただゼロからボタン機能を作るのは結構大変なので、このサイトではUnityの標準ボタンを使う前提で、意識すべきことをまとめました。

その1:ボタンはPrefab化する!

絶対にやりましょう!どんなボタンでも基本的にPrefab化した方がよいです。
Prefabとは何か?という方はこちらの記事を参考にされてください。

ゲームを作っていくと、同じような種類のボタンが必要になることが多々あります。そういった時に、一つのデザインや機能を変えたらほかも同様に変える必要が出てくると大変です。

そこで、ボタンはPrefab化し、同じデザインのボタンは同じPrefabを使えるようにしましょう。例えば私の作っているゲームだと、下部の青いボタンをPrefab化して、デザインを統一しています。

その2:ボタンを押した時の処理はボタンにアタッチするスクリプトには入れない

少し分かりづらいかもですが、ボタンを押したときに行う処理は、ボタンのコンポーネントとして定義しないことをおすすめします。
基本的には、シーン内のボタンを参照する、UIManagerや、ButtonControllerなどの名前の別のクラスを作り、別のクラス側から処理を呼び出すという設計にするべきです。理由としては、2つあります。

1.ボタンを押した時の処理は、複数のボタンで共通化することが可能なことが多いから
2.メンテナンス性が上がるから

少し細かく解説。
ボタンを押した時の挙動としては、メニュー画面を開いたり、設定画面を開いたり、シーンを遷移したり、といった処理は同じコードにまとめることが可能だったりします。

では、ボタンにはスクリプトを一切入れてはいけないのか、というとそうではありません。

ボタンのコンポーネントにスクリプトを入れるケースとしては、ボタンそのものをアニメーションさせるなど、ボタンそのもののビジュアル的な挙動制御については、ボタンオブジェクトにアタッチするというケースはありです。

逆にボタンのビジュアル処理までを、Managerクラスに任せてしまうと、Managerクラスが肥大化して逆にメンテが難しくなることが考えられます。

より複雑なUIを作っていくには、MVPパターンという設計で作っていく必要があります。
M(データとロジック)、V(UIの表示)、P(MとVの仲介役)を、それぞれ別のクラスで保持する設計です。ただ、今回の説明は、M(データとロジック)とP(MとVの仲介役)を合体させて説明しています。
MVPで実装するには、イベントの購読などを理解する必要があり、少し難易度が上がりますので、ゲーム制作始めたての小さいゲームであれば、MとVが分かれていれば十分だと考えます。

ただ、MVPすべてを一つにまとめるのは、初心者でもやらないほうがいいです。

※予防線を張ると、プロジェクトの内容によって最適な設計は異なるので、あくまでそういうケースが多いということで認識していただけると助かります。

ボタン機能のTips

ボタンを押せないようにする


ボタンのinterractiveというチェックを外すと、ボタンが押せなくなります。スクリプトから操作することも可能なので、ゲーム中にボタンのアクティブ・非アクティブを切り替えることが出来ます。

カーソルを当てたらハイライトする

ボタンの状態に応じて、ボタンのイメージを変更することで、よりボタンが押されたことを演出することが出来ます。
やり方は、遷移のオプションを「スプライトスワップ」にして、それぞれの状態のボタンのスプライトを設定するだけです。

ボタンに長押し判定を追加する

Unity標準のボタンには長押し判定がありません。長押し判定を行うにはスクリプトを作成する必要があります。ということでスクリプトを作りました。

using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;

public class LongPressButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    [SerializeField] private float checkLongTapTime = 0.5f; // 長押しとみなす時間
    private bool isPointerDown = false; // ポインターが現在下がっているかどうかのフラグ

    public void OnPointerDown(PointerEventData eventData)
    {
        // ポインターがボタンに触れた時の処理
        isPointerDown = true;
        StartCoroutine(LongPressDetected());
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        // ポインターがボタンから離れた時の処理
        isPointerDown = false;
        // 長押しから手を離した時の処理をここに書く(以下サンプル)
        Debug.Log("Long press ended");
    }

    private IEnumerator LongPressDetected()
    {
        // 長押しを検出した時の処理
        yield return new WaitForSeconds(checkLongTapTime);
        while (isPointerDown) // ボタンが長押しされている間、このループを続ける
        {
            // 長押し中に行いたい処理をここに書く(以下サンプル)
            Debug.Log("Long press is happening");


            yield return null; // 次のフレームまで待機
        }
    }
}

新しいC#スクリプト(ファイル名はLongPressButton)を作成し、上記のスクリプトを貼り付けてください。そしてボタンオブジェクトにスクリプトをアタッチしてください。

checkLongTapTimを変更することで、何秒以上押していたら長押しとするかの判定を変更することが出来ます。少し分かりづらいですがボタンを押している間だけログが出力されていますね。

まとめ

ボタンは一見簡単そうで奥が深い機能です・・・。この記事が参考になれば幸いです。
それでは素敵なゲーム制作ライフを!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ゲーム制作の敷居を下げ、もっと多くの人にゲーム作りを楽しんでもらうために、ゲームをカンタンに作る方法を”網羅的に”解説しています。
よかったらブックマークお願いします。
Twitter(X)もよければフォローお願いします。

コメント

コメント一覧 (3件)

コメントする

目次