「unity]自分で UI/Button を作る

上がカスタムボタン、下が UI/Button

UI/Button はテストや、ビジネスパッケージなどに向いている反面、ゲームのパーツとしては少々味気ない面があります。
とはいえ、UI/Button を拡張し、望みのボタンを作るのは結構大変です。

実は Image や TextMeshProUGUI を組み合わせ、独自のボタンを作ることはそれほど難しくありません。
簡単なプロジェクトを通して説明します。

サンプルプロジェクト

仕組み

ボタンの反応を司る5つのイベント

Canvas 下にある Monobehaviour に、5つのイベントを付け足すことで、マウスやタップの動きを拾うことが可能になります。

IPointerClickHandler .. ボタンが押され、その後ドラッグ操作が入ることなくボタンが離される
IPointerDownHandler .. ボタンが押される
IPointerUpHandler .. ボタンが離される
IPointerEnterHandler .. ボタンの範囲にマウスカーソルが入る
IPointerExitHandler .. ボタンの範囲からマウスカーソルが出る

なお、EventSystem が動作していなかったり、その GameObject より上のレイヤーにクリックを拾う GameObject があった場合は反応しなくなってしまうので、注意してください。

おかしいな? と思ったら何も入っていないプロジェクトにボタンだけ持っていき、反応するかどうかテストをしてみましょう。

ソースコードの書き方

特に難しい部分はありません。
なお、不要なイベントはカットしてください。例では IPointerEnterHandler、IPointerExitHandler をカットしています。

using UnityEngine;
using UnityEngine.EventSystems;

public class NewBehaviourScript : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler
{
    void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
    {
        // ボタンが押される
    }

    void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
    {
        // ボタンが離される
    }

    void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
    {
        // ボタンが押され、その後ドラッグ操作が入ることなくボタンが離される
    }
}

後はこのイベントに合わせて、表示したい Image やテキストを変更するだけです。
サンプルプロジェクトの GameButton を参考にしてください。

クリック(タップ)判定の、暗黙のルール

ここでは初心者の頃、私が疑問に思ったボタンの暗黙ルールについて、説明します。
私が「こうだろう」と思っている部分もあるので、間違いもあるかもしれません。

IPointerDownHandler と IPointerClickHandler は一緒でいいのでは?

試しに UI/Button を押した後、押したままマウスを動かしてから離すと、ボタンを押したイベントは発生しません。
これは、ボタンが「押された」のではなく「ドラッグされた」と判定するためです。

IPointerDownHandler の段階では、「押された」「ドラッグされた」のどちらかわからないに関わらず、イベントが発生してしまいます。
一方、IPointerClickHandler は「押された」場合のみ反応し、「ドラッグされた」場合は反応しません。

今回のようなボタンでは IPointerClickHandler を使うのがセオリーですが、音ゲーのようなシビアな入力タイミングを判定するには、ボタンが離された瞬間イベントが起こる IPointerClickHandler ではなく、 IPointerDownHandler を使った方がいい場合もあります。

この2つの違いは微妙ですが、使い分けを間違えると「なんかおかしいな…?」「反応悪いな」とユーザーに思わせてしまう重要な部分なので、気をつけて使い分けましょう。

マウスのポイントと、キーボードのフォーカスを一緒にしない方がいい

フォーカスとは「今カーソルがどこにあるか?」という表現です。
たとえば Windows のエクスプローラーでは、このように表示されます。

濃い部分が「選択箇所(キーボードで移動できる)」、薄い部分が「マウスカーソルがポイントしているが、選択していない箇所」になっています。

この濃い部分と薄い部分は、作り手としては一本化してしまいたくなるのですが、「マウスが間違えて移動して、おかしなものを選択してしまう」という誤操作の要因となるので、一本化しないほうが安全です。

と、いってもボタンの演出など作っていると混乱する事が多いので、私は今回のボタンのようにマウス操作の演出は分けるようにしています。

ボタンが連打されないように設計する

個人で制作していると結構見落とすのですが、例えばボタンを押すと次の画面に移動する…といった場合に、そのボタンが連打できてしまう、といったプログラムになることがよくあります。

デバッグチェックでは基本となる操作チェックです。
もっとも、最近は基本チェックをサボるデバッグチェック会社も多いです…苦笑

これはベテランであってもしばしば起こしてしまう落とし穴で、連打している間画面が切り替わらなかったり、多重シーンロードによって落ちたりすることもある厄介な問題です。

ボタンが押された瞬間から、そのボタンの判定はなくすといった個別対策や、シーン切り替え時などは全ての入力をカットするよう共通UIになんらかの規制を一つ入れておく、といった方法を考える必要があります。

初期の段階で設計しておくと、かなり未然のバグを防げるんですが…難しいですよね💦

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA