0からスタート!ゲーム開発ブログ

ゲーム開発に関する様々な記事を更新します

【Unityで始めるC#ゲーム開発】列挙型enum!ゲーム開発でどう使う?

enum とは?


 enum(列挙型)はC#の組込み型の一つで、固定された数の選択肢をプログラム内で表現するために使用されます。

 enum の読み方ですが、色々な読み方をされています。 「イニューム」「エニューム」「イナム」「イーナム」などです。 どれが正解ということもありませんので、enum の説明を行う際には、相手の方に伝わる読み方をしてください。



enum のイメージ


 enumのイメージは、箱に色々なアイテムを入れて管理するようなものです。

 例えば、あなたが冒険者で、ゲーム内で使う道具をで管理したいとします。 使う道具は「剣」、「盾」、「回復薬」だけだとします。

 この箱の役割が enum です。

 これらをenumで管理すれば、あなたが使う道具を間違えることはありません。 なぜなら、「剣」、「盾」、「回復薬」以外の道具は箱には存在しないからです。


 enumはこのように、事前に決まった複数の値の中から一つを選ぶときに便利な機能です。 プログラムを作る上で間違いを防ぎ、選択肢を明確にするのに役立ちます



enum の定義方法と列挙子


 enumを定義するときは、まずはenumというキーワードを使って、新しいenumの型を作成します。 その後に波括弧 { } の中に、カンマ , で区切って列挙子(enumの中の選択肢。れっきょし)を記述します。

 これが基本的なenumの定義方法です。




 では具体的なゲームの例を使ってみましょう。 先ほどの冒険者が「剣」、「盾」、「回復薬」の3つの道具を使うという状況を考えます。

 これをenumで表現すると以下のようになります。


public enum Tool
{
    Sword,   // 剣
    Shield,  // 盾
    Potion   // 回復薬
}


 ここではToolという新しいenumの型を作成し、「Sword」、「Shield」、「Potion」の3つの列挙子を定義しています。 enum の名称はクラスの名称と同じで、任意の名前を付けることが出来ます。管理したい情報の種類を考えて名前を付けるようにしましょう。

 なお enum の列挙子は、内部的には整数値によって管理されています。 そのため、列挙子はいわば見た目だけのものになりますので、定義には下記のように読みやすさを踏まえて日本語なども利用できます。


public enum Tool
{
    剣, 
    たて,
    ポーション 
}


 enum の定義は、クラスの定義と同じです。 そのため実際に利用するためには、変数の宣言を行い、列挙子を代入する必要があります。



enum 変数の作り方


 次に、このenumを使用して変数を作成します。

 変数の型としてenumの名前(この場合はTool)を使用し、=を使ってその変数に特定のenumの値を代入します。 代入する場合には、【enum の定義名.列挙子】の形で記述します。列挙子だけを書くとエラーになりますので気を付けてください。


Tool playerTool = Tool.Sword; // プレイヤーの道具に剣を設定


 このコードでは、プレイヤーが剣(Tool.Sword)を持っているという状況を表現しています。 enumを使用することで、プレイヤーが持つ道具の種類(情報)を明確にし、間違った道具が設定されることを防げます。

 これらの状態は互いに排他的で、playerTool 変数は一度に1つの状態だけを取ります。 つまり、重複して選択されることを防ぐことが出来ます。



enum の特徴



1.明示性


 enumは事前に決められた選択肢を一目でわかる形で示します。 これは、メニューに載っている料理を選ぶようなものです。

 例えば、レストランに行ったとき、オーダーする料理はメニューに載っているものから選びますよね。 これと同じで、enumを使うと、その中に登録されている列挙子からしか選択が出来ません。 そのため、選択肢が明確になり、間違えることなく正しい値を選ぶことができます。

 例えば先ほどの道具の例でいうと、剣、盾、回復薬の3つの道具が明示的に示されています。 プレイヤーが「弓(Bow)」を選ぼうとすると、その選択肢はenumの中にないため、コードはそれを受け入れません。


public enum Tool
{
    Sword,
    Shield,
    Potion
}

Tool playerTool = Tool.Bow; // エラー! "Bow"は定義されていない



2.型安全性


 enumはある種の「型」を作り出します。 これにより、列挙子に定義されていない値が設定されるとエラーになりますので、互換性のない、間違った種類の値の代入を防ぐことができます。

 道具の例で言うと、道具として「10」を設定しようとしても、コードはそれを受け入れません。 なぜなら、「10」は「剣」、「盾」、「回復薬」のいずれでもないからです。


Tool playerTool = 10; // エラー! "10"は int 型であって、Tool型の値ではない



3.自動割り当て


 enumの各要素(列挙子)は、特に指定しない限り、0から始まる連番の整数が割り当てられます。 これは、道具を棚に並べてそれぞれに番号を付けるようなものです。今回の Tool であれば、剣は0、盾は1、回復薬は2となります。


public enum Tool
{
    Sword,   // 剣は0
    Shield,  // 盾は1
    Potion   // 回復薬は2
}


 この自動割り当てのおかげで、剣を選ぶ場合にはTool.Swordと指定するだけで、その裏で自動的に0という整数値が割り当てられています。 そのため、ゲーム内の各道具に一意の番号を持たせることが簡単にできます。



enum のサンプルコード


 それではサンプルコードを使って、enum の挙動を確認してみましょう。

 enum は型の宣言時に SerializeField属性か public 修飾子を設定することで、インスペクターから確認することが出来ます。



 そして選択すると、プルダウンメニューが表示され、定義してある列挙子のみが表示されます。



 ゲームの設定値として、とても見やすく、かつ、ゲームの情報を作っている実感が沸きますね! 早速作ってみましょう。




 enum には大きく2つの書き方があります。

 1つはクラスの中に enum を定義する入れ子の方法、もう1つはクラスと同じように enum だけのファイルを作成する方法の2つです。 enumを定義する場所によって、その使用方法と範囲が異なります。

 ここでは、enum入れ子(クラス内)で定義する場合のみ説明します。




   C#では、クラスの中に直接enumを定義することができます。これを入れ子(nested)のenumといいます。

 以下に、Characterクラスの中にキャラクターの状態を表す CharacterStateというenumを定義する例を示します。


using UnityEngine;

public class Character : MonoBehaviour
{
    public enum CharacterState
    {
        Standing,
        Walking,
        Running,
        Jumping
    }

    public CharacterState characterState = CharacterState.Standing;
}


 このようにすると、CharacterState という enum は Character クラスの一部としてまとめられます。 このenumを参照するには【クラス名.enum】(今回なら Character.CharacterState ) という形式を使用します。

 この方式の場合、作成するファイルは1つだけになります。



 サンプルコードが完成したら、Character ファイルを任意のゲームオブジェクトにアタッチしてみましょう。 先ほど提示したように enum がインスペクターに表示されて、プルダウンメニューから自由に設定できるようになります。



まとめ


 enumはゲーム開発においても有用で、特に有限的な選択肢や状態を表すのに適しています。 たとえば、キャラクターの状態(待機、移動、攻撃など)やゲームのシーンを表すのにenumを使うと、その状態やシーンが明示的に表現され、コードが読みやすくなります。

 また打ち間違いを防ぐ側面もあります。"Running"とタイプするつもりが"Rnning"と間違えてしまうと、プログラムは期待通りに動作しません。 enum を使用すれば、プログラムは特定の選択肢のみを許可するため、このようなミスを防ぐことができます。

 加えて、互いに排他的な状態を表すのに最適です。 ゲームのキャラクターが「歩いている」か「走っている」かを表すとき、キャラクターは両方の状態を同時に取ることはできません。 このような状況では、enum を使用すると、プログラムがどの状態にあるのかを一目でわかり、また、不適切な状態の組み合わせを防ぐことができます。



 ただし、enum無限的な選択肢や可変的な状態を表すのには不適切であるため、適切な場面で使用することが大切です。

 実際に自分のプロジェクトに導入しながら、どういったケースに向いているかを検証してみましょう!