UnityのuGUIでButtonクリック時のスクリプト呼び出しを共通化しよう!

Unityでゲーム開発をしているほとんどの人がお世話になっているであろうuGUI。

そのuGUIの中でも使用率が高いButtonですが、何も考えずにクリック時の処理を作成していくとスクリプトが細麺スパゲッティの大盛りになってしまいます。

1Buttonに対して1スクリプトを作った場合、画面にボタンが10個あったらスクリプトも10個になってしまいます。
モジュール数を増やすのは管理が大変になるので避けたいです。

Buttonクリック時の処理を1個のスクリプトに記述した場合、スクリプトは1個で済みますが呼び出したい関数をUnityの画面で選択するのが大変です。
UnityはGUIでいろいろできるのが利点ですが、選択する要素が多すぎるとGUIの操作もストレスに感じます。

できることならButtonクリック時の処理は1個のスクリプトの1個の関数にしてしまいたい。
そんなわがままをできる限りかなえる方法をご紹介いたします。

スポンサーリンク

共通化しなかった場合の問題点

まずは共通化しなかった場合の問題点について整理しましょう。

・1Buttonに1スクリプトの場合
uGUIButtonCommon01
Buttonの数だけスクリプトが必要になるので管理が大変。

・1スクリプトに複数関数の場合
uGUIButtonCommon02
uGUIButtonCommon03
選択するものが増えて操作にストレスを感じる。

数が少なければ別にそこまで気にはならないことですが、やはり管理しやすく実装しやすい状態こそが開発者として望ましいかと思います。

スクリプト呼び出しの共通化

それでは早速スクリプト呼び出しの共通化を行いましょう。
※この記事はUnity 5.3.4p3 (64-bit)を使用して作成しています。

共通化するためにクラスの継承を使用します。
オブジェクト指向プログラミングというやつです。
クラスの継承についてはこの記事では説明しませんが、気になる方は調べてみてください。

まずは親クラスとなるスクリプト(ここでは「BaseButtonController.cs」とします)を作成します。
作成した親クラスのスクリプトは以下のように実装します。

using UnityEngine;
using System.Collections;

public class BaseButtonController : MonoBehaviour {

    public BaseButtonController button;

    public void OnClick()
    {
        if (button == null)
        {
            throw new System.Exception("Button instance is null!!");
        }
        // 自身のオブジェクト名を渡す
        button.OnClick(this.gameObject.name);
    }

    protected virtual void OnClick(string objectName)
    {
        // 呼ばれることはない
        Debug.Log("Base Button");
    }
}

次に、子クラスとなるスクリプト(ここでは「SampleButtonController.cs」とします)を作成します。
作成した子クラスのスクリプトは以下のように実装します。

using UnityEngine;
using System.Collections;

public class SampleButtonController : BaseButtonController
{
    protected override void OnClick(string objectName)
    {
        // 渡されたオブジェクト名で処理を分岐
        //(オブジェクト名はどこかで一括管理した方がいいかも)
        if ("Button1".Equals(objectName))
        {
            // Button1がクリックされたとき
            this.Button1Click();
        } 
        else if ("Button2".Equals(objectName))
        {
            // Button2がクリックされたとき
            this.Button2Click();
        }
        else
        {
            throw new System.Exception("Not implemented!!");
        }
    }

    private void Button1Click()
    {
        Debug.Log("Button1 Click");
    }

    private void Button2Click()
    {
        Debug.Log("Button2 Click");
    }
}

Unityから「Create」→「C# Script」でスクリプトを作成した場合、デフォルトでMonoBehaviourを継承した状態になっていますが、子クラスではそれを先ほど作成した親クラス(BaseButtonController)に変更しています。

次にヒエラルキーに空のGameObject(名前を「SampleButtonController」に変更しました)を作成し、作成した子クラスのスクリプトをコンポーネントとして追加します。
uGUIButtonCommon04
publicフィールド”Button”には何も設定する必要ありません。

今度はuGUIのButtonに作成した親クラスのスクリプトをコンポーネントとして追加し、publicフィールド”Button”に先ほど作成した「SampleButtonController」オブジェクトを割り当てます。
uGUIButtonCommon05

最後にButton1オブジェクトのOn Click()に親クラスのスクリプトのOnClick関数を割り当てて完了です。
uGUIButtonCommon06

Button2についても同様の手順で親クラスのスクリプトを適用してください。

さて、この状態でゲーム画面を起動してボタンをクリックしてみましょう。
uGUIButtonCommon07

Button1をクリックしたらコンソールに以下のように出力されたと思います。
uGUIButtonCommon08

Button2をクリックしたらコンソールに以下のように出力されたと思います。
uGUIButtonCommon09

同じスクリプトの同じ関数の呼び出しでButton毎の処理を分けるできました。
これでスクリプト呼び出しの共通化については完了です。

画面単位で子クラス(XXXButtonController.cs)を作成すればスクリプトの管理もやりやすいと思います。
※10画面あったら計11個(親クラス含む)のボタン操作用スクリプトが必要となりますが、画面とスクリプトが紐付けられるので管理しやすくなります

以上、uGUIのButtonクリック時のスクリプト呼び出しを共通化でした。

オブジェクト指向プログラミングやクラスの継承については以下の書籍で詳しく解説されています。


Unity5.xの勉強なら以下の書籍がおすすめです。