
キャラクターの向き、ゲームの状態、今いる町、攻撃の属性・・・。ゲームには「決まった選択肢の中から1つ」を持っておきたい場面がたくさんあります。これを0や"north"のような数字や文字で持っていると、打ちまちがいや「0ってどっちだっけ?」が起きがちです。今回は、選択肢そのものに名前を付けられるenum(イーナム、列挙型)と、enumとセットで使うswitch文を、ゲームでよくある場面と一緒にご紹介します!
この記事で学べること
- enumとは何か(数字や文字で持つときの困りごと)
- enumの作り方と、Inspectorのドロップダウンで選ぶ方法
- switch文で、選択肢ごとに処理を分ける方法
- ゲームでよく使う例:東西南北の向き・ゲームの状態・町の順番・属性の相性
- enumの中身は数字であることと、途中に足すときの注意
前提知識
enumってどんなもの?
たとえば、キャラクターが東西南北のどちらを向いているかを持っておきたいとします。数字や文字で持つと、次のようになります。
int facing = 0; // 0=北、1=東、2=南、3=西・・・のつもり
string facingName = "north";
- 数字:
0が北なのか南なのか、コメントを見ないと分からない。7のような、ありえない数も入ってしまう - 文字:
"nroth"のように打ちまちがえても、エラーにならない。動かしてみるまで気づけない
enumを使うと、選択肢そのものに名前を付けて、その中からしか選べないようにできます。
public enum Direction
{
North, // 北
East, // 東
South, // 南
West // 西
}
Direction facing = Direction.North;
Direction.Nrothと打ちまちがえると、その場でエラーになるので、すぐに気づける- 入れられるのは、North・East・South・Westの4つだけ
- VS Codeで
Direction.まで打つと、候補の一覧が出る
enumを作ってみよう
enumは、クラスの外(または中)に書きます。いろいろなスクリプトから使いたいときは、クラスの外に書いておくのがオススメです。
- Projectウインドで右クリック>Create>MonoBehaviour Script で「Walker」を作り、中身を次のように書き換える
using UnityEngine;
// 東西南北の向き
public enum Direction
{
North, // 北
East, // 東
South, // 南
West // 西
}
// 向いている方向を Inspector で選べるようにする
public class Walker : MonoBehaviour
{
[SerializeField] private Direction facing = Direction.North;
private void Start()
{
Debug.Log($"今の向き:{facing}");
}
}
- public enum Direction { … }
enum 名前 { 選択肢, 選択肢, … }の形で書く。選択肢は,で区切る- 名前は、クラスと同じく大文字で始めるのが決まりです
- [SerializeField] private Direction facing
- enumの変数をInspectorに出すと、ドロップダウンで選べるようになる
- {facing}
- enumを文字にすると、選択肢の名前(
North)になる
- enumを文字にすると、選択肢の名前(
空のGameObjectにWalkerを付けて、Inspectorを見てみましょう。

Facingをクリックすると、North・East・South・Westの4つがドロップダウンで出てきます。InspectorではNorthが「North」、PortTownのような2語の名前は「Port Town」と、見やすく表示されます。
switch文で選択肢ごとに分けよう
enumとセットでよく使うのがswitch文です。「この値ならこれ、あの値ならあれ」と、選択肢ごとに処理を分けられます。
向きに合わせて、進む方向(Vector2)を返すメソッドを作ってみましょう。Walkerに足します。
// 向きから、1マス進む方向を返す
private Vector2 ToVector(Direction direction)
{
switch (direction)
{
case Direction.North:
return Vector2.up;
case Direction.East:
return Vector2.right;
case Direction.South:
return Vector2.down;
case Direction.West:
return Vector2.left;
default:
return Vector2.zero;
}
}
- switch (direction)
()の中の値を見て、同じ値のcaseへ飛ぶ
- case Direction.North:
- 「値が北のとき」。その下に処理を書く
- return / break
- caseの処理の最後には、
return(メソッドを抜ける)かbreak(switchを抜ける)が必要。書き忘れるとエラーになります
- caseの処理の最後には、
- default:
- どのcaseにも当てはまらなかったとき。enumの選択肢を全部書いていても、念のため入れておくと安心です
同じことはif文でも書けますが、選択肢が多いときはswitch文のほうが「全部の選択肢を書いたか」がひと目で分かります。
VS Codeでは、switchの中にcaseの足りない選択肢があると、電球マーク(クイックフィックス)から「足りないcaseを追加」できることがあります。選択肢の書き忘れを防げるので、出てきたら使ってみてください。
ゲームでよく使う例
ここからは、ゲームでよくある場面ごとに、enumの使い方を見ていきましょう。「決まった選択肢から1つ」が出てきたら、enumの出番です。
例1:東西南北の向きと「右を向く」
ダンジョンを歩くゲームで、「右を向く」ボタンを押すと向きが変わるようにします。
enumの中身は、実は書いた順に0・1・2・3の数字になっています(North=0、East=1、South=2、West=3)。これを使うと、「次の向き」を計算で出せます。
// 右を向く(北→東→南→西→北…)
private Direction TurnRight(Direction direction)
{
int next = ((int)direction + 1) % 4;
return (Direction)next;
}
- (int)direction
- enumを数字にする。Eastなら1
- % 4
- 4で割ったあまり。West(3)の次は4ではなく0(North)に戻る
- (Direction)next
- 数字をenumに戻す
この計算は、enumを「北・東・南・西」の時計回りの順に書いているから成り立ちます。順番を入れかえると、右を向いたつもりが反対を向いたりします。順番に意味があるenumには、コメントで「時計回りの順」と書いておきましょう。
例2:ゲームの状態
タイトル・プレイ中・一時停止・ゲームオーバーのように、「今ゲームがどの場面か」もenumの定番です。
using UnityEngine;
// ゲームの場面
public enum GameState
{
Title, // タイトル
Playing, // プレイ中
Paused, // 一時停止
GameOver // ゲームオーバー
}
// 場面ごとに、毎フレームの処理を分ける
public class GameFlow : MonoBehaviour
{
[SerializeField] private GameState state = GameState.Title;
private void Update()
{
switch (state)
{
case GameState.Title:
// スタートボタンを待つ
break;
case GameState.Playing:
// プレイヤーを動かす・敵を出す
break;
case GameState.Paused:
// 何もしない(止めておく)
break;
case GameState.GameOver:
// リトライを待つ
break;
}
}
public void ChangeState(GameState next)
{
Debug.Log($"場面が変わった:{state} → {next}");
state = next;
}
}
「プレイ中なのに、タイトルのボタンが反応する」のような事故は、boolをいくつも並べて場面を持っているときによく起きます。enumなら今の場面はいつも1つだけなので、そういう事故が起きにくくなります。
例3:町の順番と「もう行ける?」
RPGで、はじまりの村から王都まで、町を順番に進んでいくとします。
// 町(旅の順番に並べる)
public enum Town
{
StartVillage, // はじまりの村
ForestTown, // 森の町
PortTown, // 港町
Capital // 王都
}
enumは数字なので、<や>=で比べられます。「港町より先に進んでいたら、船に乗れる」のような判定が1行で書けます。
[SerializeField] private Town currentTown = Town.StartVillage;
private bool CanTakeShip()
{
return currentTown >= Town.PortTown;
}
// 次の町に進む(王都より先は無い)
private void GoToNextTown()
{
if (currentTown == Town.Capital)
{
Debug.Log("もう王都に着いています");
return;
}
currentTown = currentTown + 1;
Debug.Log($"{TownName(currentTown)}に着いた!");
}
- currentTown >= Town.PortTown
- 港町(2)か王都(3)なら true
- currentTown + 1
- enumに1を足すと、次の選択肢になる
画面に出す日本語の名前は、switch文で別に用意しておきます。
// 画面に出す町の名前
private string TownName(Town town)
{
switch (town)
{
case Town.StartVillage:
return "はじまりの村";
case Town.ForestTown:
return "森の町";
case Town.PortTown:
return "港町";
case Town.Capital:
return "王都";
default:
return "?";
}
}
例4:属性の相性
炎・水・草の3すくみのような属性の相性も、enumとswitch文で書けます。
// 属性
public enum Element
{
Fire, // 炎
Water, // 水
Grass // 草
}
// 攻撃の属性と、相手の属性から、ダメージの倍率を返す
private float DamageRate(Element attack, Element target)
{
switch (attack)
{
case Element.Fire:
return target == Element.Grass ? 2f : (target == Element.Water ? 0.5f : 1f);
case Element.Water:
return target == Element.Fire ? 2f : (target == Element.Grass ? 0.5f : 1f);
case Element.Grass:
return target == Element.Water ? 2f : (target == Element.Fire ? 0.5f : 1f);
default:
return 1f;
}
}
- 条件 ? A : B
- 「条件がtrueならA、falseならB」を1行で書く書き方(三項演算子)
- 炎で草を攻撃したら2倍、水を攻撃したら0.5倍、それ以外は1倍
ほかにも、ゲームではこんなところでenumがよく使われます。
| 場面 | enumの例 |
|---|---|
| アイテムの種類 | 回復・武器・防具・だいじなもの |
| 装備する場所 | 頭・体・右手・左手・足 |
| 難易度 | かんたん・ふつう・むずかしい |
| 敵のAIの状態 | うろうろ・追いかける・攻撃・逃げる |
| カードの種類 | 攻撃・防御・回復・特殊 |
スライムアイテムの種類を"kaifuku"みたいな文字で持っていたの、全部enumにしたくなってきました・・・



打ちまちがいがエラーで分かるようになるから、直す価値はあるよ!まずは新しく作るところから使ってみてね
動かして確認してみよう!
ここまでのメソッドをまとめて、Walkerで試してみましょう。例1〜例4を入れたWalkerの全体は次のとおりです(GameFlowは別のスクリプトなので、ここには入れていません)。
using UnityEngine;
// 東西南北の向き(時計回りの順)
public enum Direction
{
North, // 北
East, // 東
South, // 南
West // 西
}
// 町(旅の順番に並べる)
public enum Town
{
StartVillage, // はじまりの村
ForestTown, // 森の町
PortTown, // 港町
Capital // 王都
}
// 属性
public enum Element
{
Fire, // 炎
Water, // 水
Grass // 草
}
// enum と switch 文の使い方を、Console で確かめる
public class Walker : MonoBehaviour
{
[SerializeField] private Direction facing = Direction.North;
[SerializeField] private Town currentTown = Town.StartVillage;
private void Start()
{
// 例1:右を4回向くと、ぐるっと1周して北に戻る
for (int i = 0; i < 4; i++)
{
Direction next = TurnRight(facing);
Debug.Log($"右を向いた:{DirectionName(facing)} → {DirectionName(next)}(進む向き {ToVector(next)})");
facing = next;
}
// 例3:王都まで町を進む(船に乗れるようになった瞬間だけ知らせる)
for (int i = 0; i < 4; i++)
{
bool couldTakeShip = CanTakeShip();
GoToNextTown();
if (!couldTakeShip && CanTakeShip())
{
Debug.Log("船に乗れるようになった");
}
}
// 例4:属性の相性
Debug.Log($"炎→草:{DamageRate(Element.Fire, Element.Grass)}倍");
Debug.Log($"炎→水:{DamageRate(Element.Fire, Element.Water)}倍");
Debug.Log($"草→草:{DamageRate(Element.Grass, Element.Grass)}倍");
}
// 向きから、1マス進む方向を返す
private Vector2 ToVector(Direction direction)
{
switch (direction)
{
case Direction.North:
return Vector2.up;
case Direction.East:
return Vector2.right;
case Direction.South:
return Vector2.down;
case Direction.West:
return Vector2.left;
default:
return Vector2.zero;
}
}
// 右を向く(北→東→南→西→北…)
private Direction TurnRight(Direction direction)
{
int next = ((int)direction + 1) % 4;
return (Direction)next;
}
// 画面に出す向きの名前
private string DirectionName(Direction direction)
{
switch (direction)
{
case Direction.North:
return "北";
case Direction.East:
return "東";
case Direction.South:
return "南";
case Direction.West:
return "西";
default:
return "?";
}
}
private bool CanTakeShip()
{
return currentTown >= Town.PortTown;
}
// 次の町に進む(王都より先は無い)
private void GoToNextTown()
{
if (currentTown == Town.Capital)
{
Debug.Log("もう王都に着いています");
return;
}
currentTown = currentTown + 1;
Debug.Log($"{TownName(currentTown)}に着いた!");
}
// 画面に出す町の名前
private string TownName(Town town)
{
switch (town)
{
case Town.StartVillage:
return "はじまりの村";
case Town.ForestTown:
return "森の町";
case Town.PortTown:
return "港町";
case Town.Capital:
return "王都";
default:
return "?";
}
}
// 攻撃の属性と、相手の属性から、ダメージの倍率を返す
private float DamageRate(Element attack, Element target)
{
switch (attack)
{
case Element.Fire:
return target == Element.Grass ? 2f : (target == Element.Water ? 0.5f : 1f);
case Element.Water:
return target == Element.Fire ? 2f : (target == Element.Grass ? 0.5f : 1f);
case Element.Grass:
return target == Element.Water ? 2f : (target == Element.Fire ? 0.5f : 1f);
default:
return 1f;
}
}
}
再生すると、Consoleに次のように出れば成功!


- 右を4回向くと、北→東→南→西→北とぐるっと1周する
- 港町に着いたところから「船に乗れるようになった」が出る
- 王都の先には進まない
- 炎→草は2倍、炎→水は0.5倍、同じ属性は1倍
注意:途中に選択肢を足すとき
enumの中身は書いた順の数字なので、途中に選択肢を足すと、うしろの番号が全部ずれます。
public enum Town
{
StartVillage, // 0
ForestTown, // 1
DesertTown, // 2 ← あとから足した
PortTown, // 3(前は2だった)
Capital // 4(前は3だった)
}
- Inspectorで選んでおいた値や、セーブデータに数字で保存していた値は、番号のまま残る
- 前に「港町(2)」を選んでいたものが、足したあとは「砂漠の町(2)」になってしまう



セーブデータを作ったあとで町を足したら、ロードした瞬間に別の町にワープしました・・・
順番に意味がないenum(アイテムの種類など)は、新しい選択肢を一番うしろに足すのが安全です。町の順番のように途中に入れたいときは、Inspectorで選んでいる値や、セーブデータを見直しましょう。
よくあるエラーと対処法
エラー:Cannot implicitly convert type ‘int’ to ‘Direction’
- 原因:数字を、そのままenumの変数に入れようとした
- 対処法:
(Direction)nextのように、(enumの名前)を付けて変換する
エラー:’Direction’ does not contain a definition for ‘north’
- 原因:選択肢の名前の大文字・小文字がちがう(
Northをnorthと書いた) - 対処法:enumに書いたとおりの名前にする。VS Codeの候補から選ぶとまちがえにくい
エラー:Control cannot fall through from one case label (‘case Direction.North:’) to another
- 原因:caseの処理の最後に
breakやreturnを書き忘れた - 対処法:caseごとに
break;かreturn …;を書く
Inspectorで選んでいた値が変わった
- 原因:enumの途中に選択肢を足した(または消した)ので、番号がずれた
- 対処法:新しい選択肢は一番うしろに足す。ずれてしまった値は、Inspectorで選び直す
まとめ
- enumは「決まった選択肢の中から1つ」に名前を付ける型。打ちまちがいがエラーで分かる
[SerializeField]を付けると、Inspectorのドロップダウンで選べる- switch文で、選択肢ごとに処理を分けられる。caseの最後は
breakかreturn - 中身は書いた順の数字(0・1・2…)。
(int)で数字に、(enumの名前)でenumに戻せる。<や>=で比べられる - 途中に選択肢を足すと番号がずれるので、順番に意味がなければ一番うしろに足す
次のステップ
- カードの種類(攻撃・防御・回復・特殊)をenumで作る回:デッキ構築カードゲームの作り方#2(準備中)
- Unityスタートガイド 目次
コメント