[Unity] シンプルにボタンを作ってみる 完成



Nプログラマです。

前々回の記事:シンプルにボタンを作ってみる前回の記事:シンプルにボタンを作ってみる 続きで、シンプルなボタンを作ってきました。

残った課題を解決して、ボタンを完成をさせたいと思います。

概要

目標 (前回の課題解決)

  • ボタンの種類判定にEnumを使う
  • 押されたボタンに付属してくる引数をGameObjectへ変更する

環境

  • Unity: 2018.3.6f1
  • プロジェクトのテンプレート: 2D

実装

ボタン判別用クラス (ButtonEventArg.cs)

前回はItemクラスにボタンを判別する用の名前をもたせていました。
今回は、ボタン判別用の専用クラスを作ることにします。

ButtonEventArg.cs コードを開く
ButtonEventArg.cs

using UnityEngine;

public enum ButtonEvent
{
    Use,
    Info,
    Close,
}

public class ButtonEventArg : MonoBehaviour
{
    public ButtonEvent _buttonEvent;
    public ButtonEvent ButtonEvent
    {
        get { return _buttonEvent; }
    }

    public GameObject argGameObject;
}

説明

ボタンにアタッチするためのスクリプトです。

Enumは同じコード内に宣言しておきます。
分けてもいいのですが、ボタンが増えてくるとEnumだけのクラスが増えてくるため自分はこのようにしています。

アタッチするとインスペクタでボタンの種類を設定するすることができます。
これを使ってMenuクラスのOnClickメソッド内で押されたボタンの種類を判別します。

注意点

インスペクタにプルダウンで設定したあとにEnumの末尾以外に定数を新しく追加した場合、インスペクタの項目がずれます。
これはどうにもならないので、新しい定数は末尾に追加していくことにします。

押されたボタンを判別して処理を行う(Menu.cs)

ボタンが押されたら呼び出すメソッドを定義します。

Menu.cs コードを開く
Menu.cs

using UnityEngine;
using UnityEngine.UI;

public class Menu : MonoBehaviour
{
    public void OnClick(ButtonEventArg arg)
    {
        switch (arg.ButtonEvent)
        {
            case ButtonEvent.Use:
                Debug.Log("use button");
                var itemName = arg.argGameObject.GetComponent<Text>();
                Debug.Log(itemName.text);
                break;
            case ButtonEvent.Info:
                Debug.Log("info button");
                var info = arg.argGameObject.GetComponent<ItemInfo>();
                info.Show();
                break;
            case ButtonEvent.Close:
                Debug.Log("close button");
                break;
        }
    }
}

説明

前回と比べると、メソッドがOnClick一つになってButtonのインスペクタでの設定も楽になっていると思います。

押されたボタンの判定について

Enumによる条件分岐をしているので、IDEによる補完が表示されます。
文字列を打ち込まない分、タイプミスも減るでしょう。

押されたボタンからコンポーネントを取得する

押されたボタンからはGameObjectが取得できるので、ここで処理によってGetComponentを使って欲しいコンポーネントを取得しています。

Useが押されたらTextコンポーネントを取得して、そのテキストを表示しています。
Infoが押されたらItemInfoコンポーネントを取得して、Showメソッドを呼び出しています。
Closeが押されたら何もせず、出力を行います。

余談

Itemクラスを間に挟んだらいいじゃない?

まぁ、、、そのとおりです。

Itemクラスを作って、それにTextとItemInfoの参照をもたせればわざわざこんな風に実装しなくてもいいです。

自分も基本的にはItemクラスを作るほうを使っています。

Itemクラス以外の別コンポーネントが必要になり取得したいというケースに役に立つかもしれないということでメモしています。。。

ケースバイケースで使っていきます。

分岐処理の肥大化

このクラスはボタンの数が多くなると、分岐処理が大きくなってきます。

自分が作ったもので言うと、ページング用のボタンを押すと現在のページ番号の管理する処理が必要になってくるので、すぐに肥大化してきます。
また、ページングのアイコンの表示処理も追加するともっと多くなります。

分岐処理が大きくなってきたらクラスやメソッドに切り出すと処理がスッキリしていいかもしれません。

Infoボタンが押された時に使うクラス(ItemInfo.cs)

Infoボタンが押された時に使うクラスです。 さきほどのMenu.csでコンポーネントを取得後、メソッドを呼び出しています。

ItemInfo.cs コードを開く
ItemInfo.cs

using UnityEngine;

public class ItemInfo : MonoBehaviour
{
    public void Show()
    {
        Debug.Log("item info method show");
    }
}

シーンの準備

先程作ったスクリプトをシーン内にアタッチするための説明用画像です。

ヒエラルキー

/img/article/2019/03/06/01.png
Hierarchy インスペクタ

ItemNameButton インスペクタ

/img/article/2019/03/06/02.png
ItemNameButton インスペクタ

Buttonの設定

ButtonのOnClickにはMenuの参照、呼び出すメソッドはMenu.OnClickを指定、引数は同一コンポーネントのButtonEventArgにします。

ButtonEventArgの設定

ButtonEventはUseを選択、ArgGameObjectには子のTextコンポーネントを指定します。

ItemInfoButton インスペクタ

子のItemInfoオブジェクトにItemInfo.csをアタッチするのを忘れないようにしましょう。

/img/article/2019/03/06/03.png
ItemInfoButton インスペクタ

Buttonの設定

ItemNameButtonと同じです。

ButtonEventArgの設定

ButtonEventはInfoを選択、ArgGameObjectには子のItemInfoコンポーネントを指定します。

CloseButton インスペクタ

Buttonの設定

ItemNameButtonと同じです。

/img/article/2019/03/06/04.png
CloseButton インスペクタ

ButtonEventArgの設定

ButtonEventはCloseを選択、ArgGameObjectにはなにも設定しません。 (Menu.csのSwitch内で未使用のため)

準備完了

実行してみて、ボタンを押してみましょう。

Consoleの出力が、ボタン毎に変わっていると思います。
Nullなどが出る場合は、インスペクタのアタッチ漏れがないかを確認してみてください。

おわりに

今回は、押されたボタンの種類の判定をEnumに変更、コンポーネントの取得をGameObject経由にするという内容でした。

ひとまずボタン作成はここまでにします。 ちょっとインスペクタでの作業が多めですが、ボタンを作るのが楽になった気がします。

それでは、このへんで。
バイナリー!



関連した記事