【Unity】RPG制作 その9- プレイヤーのステータス成長処理
前回はプレイヤー死亡時の処理と戦闘終了時の経験値とお金の入手処理を実装しました。今回はプレイヤーの能力経験値が一定値溜まった時にプレイヤー能力を上げる処理を実装していきます。
最初に、ステータスのデータを扱いやすくするために、能力の項目を列挙型で宣言しておきます。
更にステータスを上昇させる際に使用する一時変数のDictionary型を宣言します。
このstatusUpCountには能力ごとに能力値を1上げる回数を格納します。(Exp100につき能力を1上昇させる)その回数を調べてリストに格納する関数と初期化関数,、実際にプレイヤーの能力を上げる関数を次のように定義します。
クリックで展開
public void InitStatusUpCount() { foreach(STATUS value in Enum.GetValues(typeof(STATUS))) { statusUpCount[value] = 0; } } public bool CheckPlayerExpForUpStatus() { InitStatusUpCount(); bool isUpStatus = false; // 経験値100につき能力を1上昇させる。 // 経験値が100以上ある場合はループさせる while(hpExp >= 100) { statusUpCount[STATUS.HP]++; hpExp -= 100; isUpStatus = true; } while (mpExp >= 100) { statusUpCount[STATUS.MP]++; mpExp -= 100; isUpStatus = true; } while (atExp >= 100) { statusUpCount[STATUS.ATK]++; atExp -= 100; isUpStatus = true; } while (defExp >= 100) { statusUpCount[STATUS.DEF]++; defExp -= 100; isUpStatus = true; } while (agiExp >= 100) { statusUpCount[STATUS.AGI]++; agiExp -= 100; isUpStatus = true; } while (lukExp >= 100) { statusUpCount[STATUS.LUK]++; lukExp -= 100; isUpStatus = true; } while (senceExp >= 100) { statusUpCount[STATUS.SENCE]++; senceExp -= 100; isUpStatus = true; } while (magPowExp >= 100) { statusUpCount[STATUS.MAGPOW]++; magPowExp -= 100; isUpStatus = true; } while (magDefExp >= 100) { statusUpCount[STATUS.MAGDEF]++; magDefExp -= 100; isUpStatus = true; } while (learnAbiExp >= 100) { statusUpCount[STATUS.LEARNABI]++; learnAbiExp -= 100; isUpStatus = true; } return isUpStatus; } public void PlayerStatusUp() { maxHp += statusUpCount[STATUS.HP]; maxMp += statusUpCount[STATUS.MP]; at += statusUpCount[STATUS.ATK]; def += statusUpCount[STATUS.DEF]; agi += statusUpCount[STATUS.AGI]; luk += statusUpCount[STATUS.LUK]; sence += statusUpCount[STATUS.SENCE]; magPow += statusUpCount[STATUS.MAGPOW]; magDef += statusUpCount[STATUS.MAGDEF]; learnAbi += statusUpCount[STATUS.LEARNABI]; InitStatusUpCount(); }
とりあえずこの関数を戦闘終了後に呼び出します。
クリックで展開
IEnumerator EndBattle() { Debug.Log("戦闘終了"); yield return new WaitForSeconds(2f); DialogTextManager.instance.SetScenarios(new string[] { "戦闘終了!!" }); yield return new WaitForSeconds(1f); battleResult.AddGoldToPlayer(); battleResult.AddExpToPlayer(player); player.CheckPlayerExpForUpStatus(); //能力経験値が一定値貯まってるかチェック player.PlayerStatusUp(); //プレイヤーのステータスを上げる処理 DialogTextManager.instance.SetScenarios(new string[] { battleResult.gainGold + "ゴールドを手に入れた。" }); yield return new WaitForSeconds(2f); SoundManager.instance.PlayBGM("Quest"); questManager.EndBattle(); }
これで経験値が一定値貯まったらプレイヤーのステータスを上げる処理が実装できました。ただ、今のままだとステータスが上がったかどうかが目で見て確認できないため、能力値が一つでも上がった場合は、成長がわかるUIを表示するようにします。
経験値取得表とステータス上昇表を画像のように作成しました。
戦闘終了時にこれらのUIを表示します。スクリプトを3つ新規作成し、名前をそれぞれExpList,GrowList,Grow_ExpUIManagerとします。ExpList.csを開き以下のように記述します。
クリックで展開
using System.Collections; using System.Collections.Generic; using System; using UnityEngine; using UnityEngine.UI; public class ExpList : MonoBehaviour { public Slider hpExpBar; public Slider mpExpBar; public Slider atkExpBar; public Slider defExpBar; public Slider agiExpBar; public Slider lukExpBar; public Slider senceExpBar; public Slider magPowExpBar; public Slider magDefExpBar; public Slider learnAbiExpBar; Dictionary<GeneralEnum.STATUS, float> fromValues = new Dictionary<GeneralEnum.STATUS, float>(); //値変更前の経験値Dictionary Dictionary<GeneralEnum.STATUS, float> toValues = new Dictionary<GeneralEnum.STATUS, float>(); //値変更後の経験値Dictionary // ゲージを徐々に増やしたいので、プレイヤーの能力経験値を加算する前に // 現在の能力経験値を保持しておく関数 public void StoreNowPlayerExp(PlayerManager player) { fromValues[GeneralEnum.STATUS.HP] = player.hpExp / 100f; fromValues[GeneralEnum.STATUS.MP] = player.mpExp / 100f; fromValues[GeneralEnum.STATUS.ATK] = player.atExp / 100f; fromValues[GeneralEnum.STATUS.DEF] = player.defExp / 100f; fromValues[GeneralEnum.STATUS.AGI] = player.agiExp / 100f; fromValues[GeneralEnum.STATUS.LUK] = player.lukExp / 100f; fromValues[GeneralEnum.STATUS.SENCE] = player.senceExp / 100f; fromValues[GeneralEnum.STATUS.MAGPOW] = player.magPowExp / 100f; fromValues[GeneralEnum.STATUS.MAGDEF] = player.magDefExp / 100f; fromValues[GeneralEnum.STATUS.LEARNABI] = player.learnAbiExp / 100f; } public IEnumerator ShowPlayerExpList(PlayerManager player) { toValues[GeneralEnum.STATUS.HP] = player.hpExp / 100f; toValues[GeneralEnum.STATUS.MP] = player.mpExp / 100f; toValues[GeneralEnum.STATUS.ATK] = player.atExp / 100f; toValues[GeneralEnum.STATUS.DEF] = player.defExp / 100f ; toValues[GeneralEnum.STATUS.AGI] = player.agiExp / 100f; toValues[GeneralEnum.STATUS.LUK] = player.lukExp / 100f; toValues[GeneralEnum.STATUS.SENCE] = player.senceExp / 100f; toValues[GeneralEnum.STATUS.MAGPOW] = player.magPowExp / 100f; toValues[GeneralEnum.STATUS.MAGDEF] = player.magDefExp / 100f; toValues[GeneralEnum.STATUS.LEARNABI] = player.learnAbiExp / 100f; SoundManager.instance.PlaySE(9); yield return StartCoroutine(GaugeIncrease(2.0f)); yield return new WaitForSeconds(0.3f); } //徐々にゲージを増やすコルーチン IEnumerator GaugeIncrease(float durationTime) { float nowTime = 0.0f; while(nowTime <= 2.0f) { hpExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.HP], toValues[GeneralEnum.STATUS.HP], nowTime / durationTime); mpExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.MP], toValues[GeneralEnum.STATUS.MP], nowTime / durationTime); atkExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.ATK], toValues[GeneralEnum.STATUS.ATK], nowTime / durationTime); defExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.DEF], toValues[GeneralEnum.STATUS.DEF], nowTime / durationTime); agiExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.AGI], toValues[GeneralEnum.STATUS.AGI], nowTime / durationTime); lukExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.LUK], toValues[GeneralEnum.STATUS.LUK], nowTime / durationTime); senceExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.SENCE], toValues[GeneralEnum.STATUS.SENCE], nowTime / durationTime); magPowExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.MAGPOW], toValues[GeneralEnum.STATUS.MAGPOW], nowTime / durationTime); magDefExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.MAGDEF], toValues[GeneralEnum.STATUS.MAGDEF], nowTime / durationTime); learnAbiExpBar.value = Mathf.Lerp(fromValues[GeneralEnum.STATUS.LEARNABI], toValues[GeneralEnum.STATUS.LEARNABI], nowTime / durationTime); nowTime += Time.deltaTime; yield return new WaitForSeconds(0.001f); } yield return new WaitForSeconds(1.0f); yield return new WaitUntil(() => Input.GetMouseButtonDown(0)); } }
ExpList.csを先ほど作成したUIのExpListに貼り付け、BattleManagerの変数に渡します。このスクリプトでは、戦闘終了時に表示する能力経験値の取得表を表示し、経験値の貯まり具合をゲージで視覚化します。元々の数値から少しづつ経験値加算する表現をMathf.Lerp関数で実装しています。
次にGrowList.csを次のように記述します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GrowList : MonoBehaviour { public Text hpText; public Text mpText; public Text atkText; public Text defText; public Text agiText; public Text lukText; public Text senceText; public Text magpowText; public Text magdefText; public Text learnAbiText; Dictionary<GeneralEnum.STATUS, int> nowValue = new Dictionary<GeneralEnum.STATUS, int>(); //値変更前のステータスのDictionary //ステータスを上昇させる前の値を保持しておく関数 public void StoreNowPlayerStatus(PlayerManager player) { nowValue[GeneralEnum.STATUS.HP] = player.maxHp; nowValue[GeneralEnum.STATUS.MP] = player.maxMp; nowValue[GeneralEnum.STATUS.ATK] = player.at; nowValue[GeneralEnum.STATUS.DEF] = player.def; nowValue[GeneralEnum.STATUS.AGI] = player.agi; nowValue[GeneralEnum.STATUS.LUK] = player.luk; nowValue[GeneralEnum.STATUS.SENCE] = player.sence; nowValue[GeneralEnum.STATUS.MAGPOW] = player.magPow; nowValue[GeneralEnum.STATUS.MAGDEF] = player.magDef; nowValue[GeneralEnum.STATUS.LEARNABI] = player.learnAbi; } //ステータス上昇後に表示するリストのShow関数 public IEnumerator ShowStatusTexts(PlayerManager player) { SoundManager.instance.PlaySE(10); hpText.text = "HP " + nowValue[GeneralEnum.STATUS.HP] + " + " + player.statusUpCount[PlayerManager.STATUS.HP]; mpText.text = "MP " + nowValue[GeneralEnum.STATUS.MP] + " + " + player.statusUpCount[PlayerManager.STATUS.MP]; atkText.text = "攻撃 " + nowValue[GeneralEnum.STATUS.ATK] + " + " + player.statusUpCount[PlayerManager.STATUS.ATK]; defText.text = "防御 " + nowValue[GeneralEnum.STATUS.DEF] + " + " + player.statusUpCount[PlayerManager.STATUS.DEF]; agiText.text = "速さ " + nowValue[GeneralEnum.STATUS.AGI] + " + " + player.statusUpCount[PlayerManager.STATUS.AGI]; lukText.text = "運 " + nowValue[GeneralEnum.STATUS.LUK] + " + " + player.statusUpCount[PlayerManager.STATUS.LUK]; senceText.text = "感覚 " + nowValue[GeneralEnum.STATUS.LUK] + " + " + player.statusUpCount[PlayerManager.STATUS.LUK]; magpowText.text = "魔力 " + nowValue[GeneralEnum.STATUS.MAGPOW] + " + " + player.statusUpCount[PlayerManager.STATUS.MAGPOW]; magdefText.text = "魔防 " + nowValue[GeneralEnum.STATUS.MAGDEF] + " + " + player.statusUpCount[PlayerManager.STATUS.MAGDEF]; learnAbiText.text = "習得 " + nowValue[GeneralEnum.STATUS.LEARNABI] + " + " + player.statusUpCount[PlayerManager.STATUS.LEARNABI]; yield return new WaitForSeconds(2.0f); yield return new WaitUntil(() => Input.GetMouseButtonDown(0)); } }
このスクリプトを"GrowList"ゲームオブジェクトに渡します。このスクリプトは能力が上昇した際に表示する能力のもとの値と増加した値を、能力ごとにテキストに書き表すものです。
それぞれコルーチンのWaitUntil関数を使ってマウスクリック(あるいはタッチ)したら表を閉じるようにしています。
そしてGrow_ExpUIManager.csを次のように記述します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Grow_ExpUIManager : MonoBehaviour { public GameObject basePanel; public ExpList expList; public GrowList growList; private void Start() { basePanel.SetActive(false); } public void ShowExpList() { basePanel.SetActive(true); expList.gameObject.SetActive(true); growList.gameObject.SetActive(false); } public void ShowGrowList() { expList.gameObject.SetActive(false); growList.gameObject.SetActive(true); } public void CloseGrow_EXPUI() { basePanel.SetActive(false); } }
このスクリプトでは、ExpListとGrowListの表示非表示の制御を行います。
以上のスクリプトを制作したら、BattleManageで以下のように処理を実装します。
BattleManagerのEndBattle関数を以下のように記述します。
クリックで展開
IEnumerator EndBattle() { Debug.Log("戦闘終了"); yield return new WaitForSeconds(2f); DialogTextManager.instance.SetScenarios(new string[] { "戦闘終了!!" }); yield return new WaitForSeconds(1f); grow_ExpUIManager.expList.StoreNowPlayerExp(player); //加算前の能力経験値保存 grow_ExpUIManager.growList.StoreNowPlayerStatus(player); //変更前のプレイヤーステータス値保存 battleResult.AddGoldToPlayer(); //獲得金貨加算処理 battleResult.AddExpToPlayer(player);//能力経験値加算処理 grow_ExpUIManager.ShowExpList(); //経験値表を見せる yield return StartCoroutine(grow_ExpUIManager.expList.ShowPlayerExpList(player)); bool isStatusUp = player.CheckPlayerExpForUpStatus(); //能力経験値が一定値貯まってるかチェック if (isStatusUp) { grow_ExpUIManager.ShowGrowList(); //成長表を見せる yield return StartCoroutine(grow_ExpUIManager.growList.ShowStatusTexts(player)); player.PlayerStatusUp(); //UIを見せ終わったらプレイヤーのステータスを上げる処理 } grow_ExpUIManager.CloseGrow_EXPUI(); DialogTextManager.instance.SetScenarios(new string[] { battleResult.gainGold + "ゴールドを手に入れた。" }); yield return new WaitForSeconds(2f); SoundManager.instance.PlayBGM("Quest"); questManager.EndBattle(); }
経験値表と能力上昇表をコルーチンを使って表示します。能力上昇表は能力が一つでも上昇した場合のみ表示します。
実際にテストするとこんな感じです。
今回は以上です。