- Switch,Method,Enum を学ぶ -
はじめに
こんにちは,Kaito です!
この記事はSwitch,Method,Enumを利用した小課題を出題する記事です.
また,これは私が所属している徳島大学ゲームクリエイトプロジェクトの勉強会で使用するものです.
興味がありましたら,UnityroomとX公式アカウントなども見に行ってください!
この記事の目標
過去3回に習ったSwitch,Method,Enumを利用して
簡単なプログラムの課題を解いてもらいます!
課題内容
概要
RPGの戦闘部分をイメージした簡単なCUIに近いゲームを作ってもらいます.
要件
- 各キャラクターはHpを保持する.
- クラスは最低でもプレイヤー用と敵用が存在する.
- コマンドは以下に記した二つとする.
- 攻撃コマンドは敵のHPを3減らす.
- 回復コマンドはプレイヤーのHPを3増やす.この際に簡単にするため,最大HP以上の回復を必ず制限する必要はない.
- 攻撃によりHPが減少して0以下となれば倒したこととする.この際に簡単にするため,死亡処理を必ずしも行う必要はない.
- プレイヤーのターンに合わせて敵が行動するのも望ましいが,この際に簡単にするため,サンドバックとする.
- Debug.Log等によりコマンド選択部分とコマンド実行部分でHpや行ったコマンドを表示する.
仕様
-
入力処理部分(例:
GetInput())は「入力の検出と記録」に限定する.入力検出時にゲームアクション(例:Attack(),Heal())やHPの直接操作を行ってはならない.コード例
- 以下の様な方法で組まないでください.
if(Input.GetKeyDown(KeyCode.Alpha1)) { Attack(); }- 以下のようにしてください
if(Input.GetKeyDown(KeyCode.Alpha1)) { /* 現在のコマンド */ = /* コマンドX */ ; } -
検出したコマンドはEnum値で保持する.ゲームループまたは専用の実行関数(例:
ExecuteCommand())で判定・実行すること. -
各コマンドの効果(HP増減)は必ず個別関数(例:
Attack(),Heal())として実装し,switch から呼び出す構成にすること.
補足
- Unityでは以下のような方法を例にキー入力検知をできます.
例:メインキーボード「1」を押下した場合
if(Input.GetKeyDown(KeyCode.Alpha1))
{
/* 処理 */
}
- UnityのDebugには以下の様なものが存在します.今回は状況に応じて使用してみてください.
Debug.Log("現在のスコア: " + score); // 通常ログ
Debug.LogWarning("スコアに意図しない入力がされた可能性"); // 警告ログ
Debug.LogError("スコアがマイナスになりました"); // エラーログ
- 以下のような方法で不正な値をEnumに意図的に設定することもできます.
/* Enum型変数 */ = (/* Enum型 */) 999; // 不正なコマンドを意図的に設定
期待する動作例
以下に一例としてUnityEditorのConsole上での期待動作例を示します.
- プレイヤーがコマンドAttackに相当する物をクリックすると
Attackを選択.
敵に3ダメージ.
- プレイヤーがコマンドHealに相当する物をクリックすると
Healを選択.
3回復しました.
- プレイヤーが該当しないコマンド入力をクリックすると
該当しないコマンドが選択されました.
- 敵のHPが攻撃されて0以下であれば
敵を倒した!戦闘終了!
ヒント
ヒント
解答例
ネタバレ注意!
以下のコードはあくまで一例であり,必ずしもこのように書く必要はないです.※解答例のコードを動かす際はBattleManagerとPlayer,Enemyをゲームオブジェクトにアタッチし,BattleManagerのインスペクター上にある空欄にPlayer,Enemyのスクリプトをセットしてください.
-
BattleManagerクラス
using UnityEngine; /// <summary> /// 戦闘の管理を行うクラス /// </summary> public class BattleManager : MonoBehaviour { [SerializeField] private Player _player; [SerializeField] private Enemy _enemy; private BattleCommand currentCommand = BattleCommand.None; void Start() { Debug.Log("==== 戦闘開始! ===="); Debug.Log("キーボードの [1] で攻撃,[2] で回復を選択してください."); Debug.Log($"プレイヤーの初期HP: {_player.GetHp()}"); Debug.Log($"敵の初期HP: {_enemy.GetHp()}"); } void Update() { // 敵のHPが0以下の場合は,すでに入力や処理を行わない if (_enemy.GetHp() > 0) { // 1. 入力の検出と記録のみを行う GetInput(); // 2. コマンドが入力・保持されていれば,判定・実行フェーズに移る if (currentCommand != BattleCommand.None) { ExecuteCommand(); } } } /// <summary> /// 入力処理部分:入力の検出とEnum値の保持のみを行う /// </summary> private void GetInput() { if (Input.GetKeyDown(KeyCode.Alpha1)) { currentCommand = BattleCommand.Attack; Debug.Log("Attackを選択."); } else if (Input.GetKeyDown(KeyCode.Alpha2)) { currentCommand = BattleCommand.Heal; Debug.Log("Healを選択."); } else if (Input.GetKeyDown(KeyCode.Alpha3)) { currentCommand = (BattleCommand)999; // 不正なコマンドを意図的に設定 } } /// <summary> /// 実行処理部分:保持したEnumをもとにSwitch文で個別関数を呼び出す /// </summary> private void ExecuteCommand() { switch (currentCommand) { case BattleCommand.Attack: _enemy.Damaged(); break; case BattleCommand.Heal: _player.Heal(); break; default: Debug.LogError("該当しないコマンドが選択されました."); break; } // コマンドを実行し終えたら,入力状態をリセットする currentCommand = BattleCommand.None; } } -
BattleCommandEnum
/// <summary> /// コマンドの種類を表すEnum /// </summary> public enum BattleCommand { None, // 何も入力されていない状態 Attack, // 攻撃コマンド Heal // 回復コマンド } -
Playerクラス
using UnityEngine; /// <summary> /// プレイヤー用のクラス /// </summary> public class Player : MonoBehaviour { private int _hp = 15; // 初期HP /// <summary> /// 回復コマンドの個別処理 /// </summary> public void Heal() { _hp += 3; Debug.Log($"3回復しました. (プレイヤーの現在のHP: {_hp})"); } public int GetHp() { return _hp; } } -
Enemyクラス
using UnityEngine; /// <summary> /// 敵用のクラス /// </summary> public class Enemy : MonoBehaviour { private int _hp = 10; // 初期HP /// <summary> /// 攻撃コマンド /// </summary> public void Damaged() { _hp -= 3; Debug.Log($"敵に3ダメージ.(敵の残りHP: {_hp})"); // HPが0以下になったかの判定 if (_hp <= 0) { Debug.LogWarning("敵を倒した!戦闘終了!"); } } public int GetHp() { return _hp; } }
まとめ
今回の課題ではCUIに近いコマンドバトルゲームを作成しました.
課題の内容を見てどうして入力の内部でコマンドの実行を行わないのか疑問に思う人もいるかもしれません.
理由は簡単で,入力と処理を分けることで,将来的に「ボタンをクリックした時」や「AIが自動で選んだ時」等,入力元が増えても対応しやすくなるからです.
また,Enumを利用することで,コマンドの種類を明確にし,コードの可読性も向上します.
さらに,Switch文を使用することで,コマンドの種類ごとに処理を分けることができ,コードの構造が整理されます.
