この記事はUnityでハクスラローグライク×デッキ構築型カードバトルRPG「呪術迷宮」を作る講座の第17回です。
前回は敵撃破時に手に入るカード・経験値・お金を獲得できる戦闘終了後アイテムドロップシステムを実装しました。
前回の記事:
今回からは手に入れたお金と経験値を消費してプレイヤーを強化できる転職システム、そして新しいカードを購入できるカードショップ機能を実装していきます。
まずは経験値を消費してパラメータを強化し、新しい職業を得られる訓練場(転職システム)から作成していきましょう。
キャラクター強化に関しては、最大HP上昇処理と手札の保有枚数を増加させる処理を作ります。
職業は複数存在し、それぞれステージ攻略中に異なる効果を発動します。講座で実装予定の職業は以下の6つ(+初期職)です。
職業名 | 効果 |
(職業なし) | 初期職業・効果なし |
闘士 | 武器ダメージを与える時に+2追加 |
風水師 | 自身の悪性状態異常の減少量+1 敵に悪性状態異常を与える時+1 |
僧侶 | 自身の体力を回復する度に最大体力+2 |
賢者 | ターン開始時の手札1枚追加 |
侍 | 左端のカードが与えるダメージ2倍 (敵のカードならダメージ5減少) |
呪術師 | 右端で発動するカードの効果量が全て3倍 |
これらのジョブと転職システムを実装します。
ハクスラ系ローグライクゲームはもちろん、このシステムを応用すればウィザードリィ、ドラクエ3、FF5のようなジョブチェンジ・転職システムを作ることも可能になるでしょう(条件を満たせばジョブを解禁&転職)。
転職・パラメータ強化システムのための訓練場ウィンドウの作成
Titleシーンを編集し、訓練場ボタンをタップした時に開かれる訓練場ウィンドウを作成していきます。
訓練場では経験値を消費してプレイヤーの手札枚数や最大HPを強化したり、職業を開放する事が出来ます。職業・転職システムについては後ほど説明します。
各強化項目および職業解放項目がポップアップしたメニューのスクロールビューの中に生成されるという構図を目指します。
訓練場ウィンドウオブジェクト
StageSelectWindowオブジェクトをコピー&ペーストし、訓練場ウィンドウとして作成していきます。
StageSelectWindowコンポーネントは外し、子オブジェクトについてはCloseButton以外全て削除しておきます。
- オブジェクト名:TrainingWindow
- 親:GameWindow
- PosX:0 PosY:0
- Width:860 Height:500
- (Image)Source Image:Textures/GUIs/Title/window_B.png
ウィンドウを閉じるボタン
- オブジェクト名:CloseButton
- 親:TrainingWindow
- PosX:366 PosY:188
訓練場ロゴText
- オブジェクト名:LogoText
- 親:TrainingWindow
- PosX:-120 PosY:140
- Width:300 Height:48
- (Text)Overflow設定:Overflow
- SimpleTranslationTextをアタッチ:(日本語)訓練場 (英語)Training
ステータスロゴText
- オブジェクト名:StatusLogo
- 親:TrainingWindow
- PosX:70 PosY:140
- Width:70 Height:32
- (Text)Overflow設定:Overflow
ステータスアイコン画像
- オブジェクト名:StatusIcon
- 親:TrainingWindow
- PosX:130 PosY:140
- Width:40 Height:40
- (Image)Source Image:Textures/CardIcons/lists_755.png
ステータス数量(経験値量)表示Text
現在の経験値の値をスクリプトで表示させます。Battleシーンで作成した時と同様に4桁以上はカンマ表示を行います。
- オブジェクト名:StatusValueText
- 親:TrainingWindow
- PosX:220 PosY:140
- Width:140 Height:32
- (Text)Overflow設定:Overflow
パラメータ強化と転職システムのための訓練項目表示スクロールビュー
経験値を消費して強化および職業の解禁項目は選択肢の種類分だけ必要になります。
また、既に解放済みの職業については項目を表示する必要が無くなる仕様とします。一度解放した職業を再び購入する必要はありませんからね。そのため、解放可能な数量はゲーム進行度によって可変になります。
可変個数の要素を持つスクロールビュー画面を作るので、デッキ編集画面で作成したときと同じものをここでも使用します。
まずDeckEditWindowからStorageSVオブジェクトをコピー&ペーストします。
- オブジェクト名:ItemRowsSV
- 親:TrainingWindow
- PosX:0 PosY:-26
- Width:670 Height:260
Content以下に訓練項目オブジェクトを並べていきますが、縦に並べて表示させるのでGrid Layout GroupではなくVertical Layout Groupを使用するように変更します。
これでウィンドウの準備は完了です。
訓練項目プレハブの作成
先ほどのスクロールビュー上に表示する各訓練項目のオブジェクトを作成していきます。
強化対象の説明Textや実行ボタン等を置きます。完成したらプレハブにし、ウィンドウの初期化時に必要分だけ生成されるようにします。
まずは空オブジェクトをItemRowsSVのContent以下に作成します。
- オブジェクト名:TrainingItemRow
- 親:Content
- Width:620 Height:80
項目アイコン画像
訓練項目のアイコンを表示するスペースです。Spriteはスクリプトから指定します。
- オブジェクト名:ItemIcon
- 親:TrainingItemRow
- PosX:-270 PosY:0
- Width:48 Height:48
項目名Text
訓練項目の名前を表示するTextです。
- オブジェクト名:ItemNameText
- 親:TrainingItemRow
- PosX:-170 PosY:0
- Width:130 Height:70
- (Text)BestFit設定:1~20のサイズ
項目説明Text
訓練項目の説明文を表示するTextです。
- オブジェクト名:ItemExplainText
- 親:TrainingItemRow
- PosX:32 PosY:0
- Width:274 Height:70
- (Text)BestFit設定:1~18のサイズ
項目の購入・獲得ボタン
この項目を購入してキャラクターの強化や職業の解放を実行するButtonUIです。
- オブジェクト名:ObtainButton
- 親:TrainingItemRow
- PosX:236 PosY:0
- Width:140 Height:48
- (Image)Source Image:Textures/GUIs/Title/buttons_3.png
(ボタン内UI)ステータスアイコン画像
項目の購入には経験値を消費しますが、必要な量についてはボタン上のUIに表示する事にします。
TrainingWindowオブジェクト下のStatusIconをコピー&ペーストして配置します。
- オブジェクト名:PriceIcon
- 親:ObtainButton
- PosX:-38 PosY:12
- Width:22 Height:22
(ボタン内UI)ステータス必要量Text
必要な経験値量を表示するTextです。もしButtonに最初からついてるTextオブジェクトを使いまわす場合はAnchorsとPivotの位置に注意。
- オブジェクト名:PriceValueText
- 親:ObtainButton
- PosX:12 PosY:12
- Width:80 Height:22
- (Text)BestFit設定:1~20のサイズ
(ボタン内UI)ボタンロゴText
- オブジェクト名:ObtainLogo
- 親:ObtainButton
- PosX:0 PosY:-8
- Width:100 Height:24
- (Text)Overflow設定:Overflow
- SimpleTranslationTextをアタッチ:(日本語)取 得 (英語)Obtain
訓練項目スクリプト仮作成&アタッチ&プレハブ化
ここからTrainingItemRowオブジェクトをプレハブ化していきますが、先にこのオブジェクトのUIを処理するスクリプトを仮作成してアタッチしておく事で、後からプレハブに対して編集する作業を削減する事ができます。
よってまずTrainingItemクラスを作成してTrainingItemRowオブジェクトにアタッチしましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; /// <summary> /// 各訓練項目UI処理クラス /// </summary> public class TrainingItem : MonoBehaviour { // UIオブジェクト [SerializeField] private Image iconImage = null; // 項目アイコン [SerializeField] private Text nameText = null; // 項目名Text [SerializeField] private Text explainText = null; // 項目説明Text [SerializeField] private Button obtainButton = null; // 取得ボタン [SerializeField] private Text priceText = null; // 価格Text /// <summary> /// 取得ボタン押下時処理 /// </summary> public void ObtainButton () { } } |
編集できたら各種参照をセットします。
ほか、ObtainButtonのButtonコンポーネントにてタップ時呼び出し処理にTrainingItem.ObtainButtonメソッドを指定します。
最後にTrainingItemRowオブジェクトをプレハブ化し、シーン内に存在していたオブジェクトを削除すれば準備完了です。
最大HP・手札枚数強化システム
ここからは訓練場ウィンドウスクリプトを作成してプレイヤーの強化を実装していく流れになります。
まずはDataクラスを編集して「プレイヤーの最大HP」と「各ターン開始時の手札枚数」をデータとして記録・変更できるようにしておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// (DataManagerオブジェクトにアタッチ) /// データマネージャー /// ゲーム起動中常に同じインスタンス(オブジェクト)が1つ存在している /// </summary> public class Data : MonoBehaviour { #region シングルトン維持用処理(変更不要) // シングルトン維持用 public static Data instance; // Awake(Startより前に1度だけ実行) private void Awake () { // シングルトン用処理 if (instance != null) { Destroy (gameObject); return; } instance = this; DontDestroyOnLoad (gameObject); // ゲーム起動時処理 InitialProcess (); } #endregion // 各種コンポーネント public PlayerDeckData playerDeckData; // デッキ管理クラス // シーン間保存データ public static SystemLanguage nowLanguage; // 現在の設定言語 // タイトル画面で選択可能な全ステージのリスト public List<StageSO> stageSOs; // 進行中のステージID [HideInInspector] public int nowStageID; // プレイヤーデータ public int playerGold; // 所持金貨 public int playerEXP; // 獲得済み経験値 public int playerMaxHP = 20; // プレイヤーの最大HP public int playerHandNum = 5; // プレイヤーの各ターンの手札枚数(職業による増加分は含まない) /// <summary> /// ゲーム開始時(インスタンス生成時)に一度だけ実行される処理 /// </summary> private void InitialProcess () { // 乱数シード値初期化 Random.InitState (System.DateTime.Now.Millisecond); // 実行環境の言語設定を取得する nowLanguage = GetLanguageData (); //nowLanguage = SystemLanguage.English; // (テスト用)英語設定に変更する // プレイヤーデッキデータ初期化処理 playerDeckData.Init (); // プレイヤー所持カードデータ初期化(セーブ機能実装後は別のタイミングで呼び出し) playerDeckData.DataInitialize (); } /// <summary> /// 実行環境の言語設定を取得して返す /// </summary> /// <returns>言語データ</returns> private SystemLanguage GetLanguageData () { // 実行環境の言語設定を取得 var language = Application.systemLanguage; // 日本語以外の言語だった場合全て英語で対応する if (language != SystemLanguage.Japanese) language = SystemLanguage.English; return language; } #region 各種プレイヤーデータ変更処理 /// <summary> /// プレイヤーの所持金貨を変更する /// </summary> /// <param name="value">変化量(+で増加)</param> public void ChangePlayerGold (int value) { playerGold += value; } /// <summary> /// プレイヤーの経験値量を変更する /// </summary> /// <param name="value">変化量(+で増加)</param> public void ChangePlayerEXP (int value) { playerEXP += value; } /// <summary> /// プレイヤーの最大HPを変更する /// </summary> /// <param name="value">変化量(+で増加)</param> public void ChangePlayerMaxHP (int value) { playerMaxHP += value; } /// <summary> /// プレイヤーの各ターンの手札枚数を変更する /// </summary> /// <param name="value">変化量(+で増加)</param> public void ChangePlayerHandNum (int value) { playerHandNum += value; } #endregion } |
- 暫定的に変数に初期値を設定していますが、データのセーブ&ロードを実装した時に正式な初期化処理を用意する予定です。
訓練場ウィンドウ処理クラス
TrainingWindowにアタッチして訓練場ウィンドウを制御し、各訓練項目(現在は2つ)を表示させるスクリプトTrainingWindowを作成します。
まとめ
経験値を消費してプレイヤーを強化できるシステム『訓練場』を作成し、ステージ攻略を繰り返す度に少しずつ強くなっていく楽しみを得られるようになりました。
また、この訓練所ではキャラクターのジョブ転職も実現しています。
今回のスクリプトの中ではEnumとDictionaryを使った新しい定義方法が便利なので覚えておくと他のゲーム開発でも役に立つかもしれません。
また、本作では実装していませんが、敵キャラクターに職業を持たせることで独特の永続効果を実装することもできそうですね。JobDataDefine.csと敵キャラクター用のScriptable Objectに変更を加え、useCharaID=CharaID_Enemyの時に発動する処理を各種スクリプトに組み込めば実現できそうですね。
腕試しに試してみるのも良いでしょう。
次回は引き続きタイトル画面からの強化システムとして『術札屋』を作成して新たなカードをランダムに購入できるようにしていきましょう。
次の記事:
コメント