【Unity】UIボタンで学ぶシンプルなポリモーフィズムの実現

2024年6月2日

UnityでUIボタンを使ってシンプルなポリモーフィズムを実現するコードの例を示します。この例では、異なる動物のクラスを作り、それぞれがボタンを押すと異なるメッセージを表示するようにします。

サンプル

まず、動物の基底クラスとその派生クラスを定義します。

クラス図

オブジェクト指向のクラスとその関係を示します。

概要: このクラス図は、オブジェクト指向プログラミングの基本的な継承関係を示しています。Animalは抽象クラスであり、MakeSoundという抽象メソッドを持っています。DogCatAnimalを継承し、それぞれのクラスでMakeSoundメソッドを実装しています。これは、共通のインターフェースを持ちながら、異なる具体的な動作を実現するためのポリモーフィズムを示しています。さらに、AnimalButtonControllerクラスはUIボタンを管理し、クリックイベントに応じて対応する動物オブジェクトを生成し、その動物が特定の動作を実行する役割を担っています。この構造により、コードの再利用性と保守性が向上し、新しい動物クラスを簡単に追加することが可能になります。

このクラス図は以下のような構成になっています:

  • Animalは抽象クラスであり、MakeSoundという抽象メソッドを持っています。
  • DogCatAnimalを継承し、それぞれMakeSoundメソッドを具体的に実装しています。
  • AnimalButtonControllerクラスは、dogButtoncatButtonのフィールド、およびボタンがクリックされたときに動物の音を鳴らすメソッドを持っています。

このクラス図を使って、ポリモーフィズムの概念を視覚的に説明することができます。

Step 1: 動物クラスの定義

// Animal.cs
public abstract class Animal
{
    public abstract void MakeSound();
}
// Dog.cs
public class Dog : Animal
{
    public override void MakeSound()
    {
        Debug.Log("わん!");
    }
}
// Cat.cs
public class Cat : Animal
{
    public override void MakeSound()
    {
        Debug.Log("ミャー!");
    }
}

Step 2: ボタンの設定とスクリプト

次に、UIボタンを設定し、ボタンを押したときに動物の音を鳴らすスクリプトを作成します。

// AnimalButtonController.cs
using UnityEngine;
using UnityEngine.UI;

public class AnimalButtonController : MonoBehaviour
{
    public Button dogButton;
    public Button catButton;

    private void Start()
    {
        dogButton.onClick.AddListener(() => OnButtonClick(new Dog()));
        catButton.onClick.AddListener(() => OnButtonClick(new Cat()));
    }

    private void OnButtonClick(Animal animal)
    {
        animal.MakeSound();
    }
}

クラスの構造と役割

  1. フィールド:
    • dogButton: UIのDogボタンを参照するためのフィールドです。
    • catButton: UIのCatボタンを参照するためのフィールドです。
  2. Startメソッド:
    • Unityのライフサイクルメソッドの一つで、ゲームが開始されたときに呼び出されます。
    • このメソッド内で、dogButtoncatButtonにクリックリスナーを追加します。リスナーは、ボタンがクリックされたときに特定の動作を実行するためのものです。
  3. OnButtonClickメソッド:
    • 引数としてAnimal型のオブジェクトを受け取り、そのオブジェクトのMakeSoundメソッドを呼び出します。
    • Animalは抽象クラスで、DogCatクラスはそのサブクラスとして実装されます。これにより、ポリモーフィズムを利用して異なる動物がそれぞれ異なる動作を実行できます。

ポリモーフィズムの利用

AnimalButtonControllerクラスでは、ポリモーフィズムを利用しています。ポリモーフィズムとは、同じインターフェースや基底クラスを通じて異なるクラスのオブジェクトを同様に扱うことができる機能です。この例では、DogCatクラスがAnimalクラスを継承しており、それぞれがMakeSoundメソッドを実装しています。

クラスの全体的な流れ

  1. ゲームが開始されると、Startメソッドが呼び出されます。
  2. Startメソッド内で、dogButtoncatButtonにクリックイベントリスナーを追加します。
  3. ユーザーがDogボタンをクリックすると、OnButtonClickメソッドが呼び出され、新しいDogオブジェクトが作成されます。
  4. DogオブジェクトのMakeSoundメソッドが呼び出され、"Woof!"というメッセージが出力されます。
  5. 同様に、ユーザーがCatボタンをクリックすると、新しいCatオブジェクトが作成され、"Meow!"というメッセージが出力されます。

このように、AnimalButtonControllerクラスは、ボタン操作に応じて異なる動物オブジェクトを生成し、それぞれの動物が特定の動作を実行するようにする役割を担っています。

Step 3: Unityエディターでの設定

  1. Unityエディターで、キャンバスを作成し、その中に2つのボタン(Dog Button、Cat Button)を配置します。
  2. ボタンに対応するテキスト(Dog、Cat)を設定します。
  3. AnimalButtonControllerスクリプトをアタッチするオブジェクトを作成し、スクリプトをアタッチします。
  4. AnimalButtonControllerスクリプトのdogButtonフィールドにDogボタンを、catButtonフィールドにCatボタンをドラッグして割り当てます。

この設定を行うと、ボタンを押すとそれぞれの動物の音がコンソールに表示されます。これがポリモーフィズムのシンプルな実例です。同じインターフェース(ここではMakeSoundメソッド)を使って、異なるクラス(Dog、Cat)が異なる動作を実行します。

オブジェクト図

特定の時点でのシステムの状態を示します。

概要: このオブジェクト図は、Unityアプリケーション内でボタンとそれに関連するオブジェクトの状態と関係を示しています。Canvasオブジェクトは、DogButtonCatButtonを含んでいます。DogButtonオブジェクトは「Dog」というテキストを持ち、クリックイベントを処理します。同様に、CatButtonオブジェクトは「Cat」というテキストを持ち、クリックイベントを処理します。AnimalButtonControllerオブジェクトは、dogButtoncatButtonを操作し、それぞれのボタンがクリックされたときに対応する動物のMakeSoundメソッドを呼び出します。この図は、オブジェクト間の関係とその相互作用を視覚的に示しています。

このオブジェクト図は以下の要素を含んでいます:

  1. Canvasオブジェクト: dogButtoncatButtonを含んでいます。
  2. DogButtonオブジェクト: テキストが「Dog」であり、onClick()メソッドがあります。
  3. CatButtonオブジェクト: テキストが「Cat」であり、onClick()メソッドがあります。
  4. AnimalButtonControllerオブジェクト: dogButtoncatButtonを使用し、OnButtonClick(animal: Animal)メソッドを持っています。

この図をもとに、実際のUnityの構成を視覚化できます。特に、AnimalButtonControllerDogButtonCatButtonを操作する関係を示しています。

その他のUML図

シーケンス図

オブジェクト間の相互作用を時系列で示します。

概要: このシーケンス図は、ユーザーがDogButtonをクリックしたときの一連の操作を時系列で示しています。ユーザーがボタンをクリックすると、DogButtonAnimalButtonControllerOnButtonClickメソッドを呼び出し、新しいDogオブジェクトを作成します。その後、DogオブジェクトがMakeSoundメソッドを実行し、"Woof!"という音を出します。

ユースケース図

システムの機能と外部との相互作用を示します。

概要: このユースケース図は、システムの機能とそれを利用するアクター(User)との相互作用を示しています。ユーザーはボタンをクリックすることで、「Make a sound」というユースケースが実行されます。具体的には、ユーザーがシステムのUIボタン(DogボタンまたはCatボタン)をクリックすると、システムは対応する動物のオブジェクトを作成し、その動物が音を出すという動作を行います。この図は、システムが提供する機能とユーザーの関係を視覚的に示しています。

コンポーネント図

システムの物理的な部分やコンポーネントの構造を示します。

概要: このコンポーネント図は、システムを構成する各コンポーネントとその相互関係を示しています。AnimalButtonControllerは、DogButtonおよびCatButtonと連携して動作します。各ボタンはUI要素として存在し、それぞれがクリックイベントを持ちます。AnimalButtonControllerは、これらのボタンからのクリックイベントを受け取り、対応する動物オブジェクト(DogまたはCat)を生成し、その動物のMakeSoundメソッドを呼び出します。この図は、システムの各コンポーネントがどのように連携して動作するかを視覚的に示しています。

ステート図

オブジェクトの状態遷移を示します。

概要: このステート図は、ユーザーがボタンをクリックした後のアプリケーションの状態変化を示しています。ユーザーがボタンをクリックすると、システムはIdle状態からDogButtonClickedまたはCatButtonClicked状態に遷移します。DogButtonClicked状態では、新しいDogオブジェクトが作成され、"わん"という音を出します。一方、CatButtonClicked状態では、新しいCatオブジェクトが作成され、"ミャー"という音を出します。それぞれのアクションが完了すると、システムは再びIdle状態に戻ります。この図は、システムがどのように異なる状態間を遷移するかを視覚的に示しています。

アクティビティ図

ワークフローやアクティビティの順序を示します。

概要: このアクティビティ図は、ユーザーがボタンをクリックした後のプロセスを示しています。ユーザーがボタンをクリックすると、プロセスはDog button clickedまたはCat button clickedというイベントに分岐します。Dog buttonがクリックされた場合、新しいDogオブジェクトが作成され、"Woof"という音を出します。同様に、Cat buttonがクリックされた場合、新しいCatオブジェクトが作成され、"Meow"という音を出します。この図は、イベントに応じた分岐処理を視覚的に示しています。

参考(直接ボタンに表示イベントをそれぞれアタッチする方法と、コントローラークラスを使用してイベントを管理する方法の違い)

直接ボタンに表示イベントをそれぞれアタッチする方法と、コントローラークラスを使用してイベントを管理する方法の違いについて説明します。

直接ボタンにイベントをアタッチする方法

直接ボタンにイベントをアタッチする方法では、各ボタンのクリックイベントに対して直接的に処理を定義します。例えば、Unityエディターのインスペクターでボタンに対してイベントをアタッチすることができます。

using UnityEngine;
using UnityEngine.UI;

public class DirectButtonHandler : MonoBehaviour
{
    public Button dogButton;
    public Button catButton;

    private void Start()
    {
        dogButton.onClick.AddListener(OnDogButtonClick);
        catButton.onClick.AddListener(OnCatButtonClick);
    }

    private void OnDogButtonClick()
    {
        Dog dog = new Dog();
        dog.MakeSound();  // "わん!"
    }

    private void OnCatButtonClick()
    {
        Cat cat = new Cat();
        cat.MakeSound();  // "ミャー!"
    }
}

コントローラークラスを使用する方法

コントローラークラスを使用してイベントを管理する方法では、イベント処理のロジックを一つのクラスにまとめ、より組織的に管理します。この方法はコードの再利用性や保守性を向上させます。

using UnityEngine;
using UnityEngine.UI;

public class AnimalButtonController : MonoBehaviour
{
    public Button dogButton;
    public Button catButton;

    private void Start()
    {
        dogButton.onClick.AddListener(() => OnButtonClick(new Dog()));
        catButton.onClick.AddListener(() => OnButtonClick(new Cat()));
    }

    private void OnButtonClick(Animal animal)
    {
        animal.MakeSound();
    }
}

違いの比較

  1. コードの可読性と保守性:
    • 直接アタッチ: 各ボタンに対して個別にイベント処理を記述するため、コードが散在しやすく、メンテナンスが難しくなる可能性があります。ボタンの数が増えると、コードが冗長になりがちです。
    • コントローラー使用: イベント処理のロジックを一つのクラスにまとめることで、コードの見通しが良くなり、保守性が向上します。新しいボタンを追加する場合も、コントローラークラスに対して追加するだけで済みます。
  2. 再利用性:
    • 直接アタッチ: 各ボタンに対して固有の処理が必要な場合、コードの再利用が難しくなります。
    • コントローラー使用: 抽象クラスやインターフェースを使って共通の処理を定義することで、コードの再利用が容易になります。例えば、OnButtonClickメソッドはどの動物クラスにも対応できます。
  3. 拡張性:
    • 直接アタッチ: 新しい種類のボタンを追加するたびに、新しいイベントリスナーを定義する必要があります。
    • コントローラー使用: 新しい動物クラスを追加する場合、コントローラークラスに新しいボタンを簡単に追加できます。既存のロジックを使い回すことができるため、拡張が容易です。
  4. 依存関係の管理:
    • 直接アタッチ: 各ボタンが個別の処理を持つため、依存関係が増えると複雑になります。
    • コントローラー使用: 依存関係を一つのクラスにまとめることで、管理が容易になります。依存関係の変更があった場合でも、コントローラークラスのみを修正すれば済みます。

まとめ

コントローラークラスを使用する方法は、コードの可読性、保守性、再利用性、拡張性、依存関係の管理の面で優れています。特に大規模なプロジェクトや将来的に機能拡張が見込まれる場合には、コントローラークラスを使用する方法が推奨されます。

Unity

Posted by hidepon