今回は戦闘時のメッセージをUIに表示する機能を作成していきたいと思います。
前回は戦闘シーンでの味方のターンの行動処理を作成しました。
ユニティちゃんのRPGを作ってみようの他の記事は
から見ることが出来ます。
前回まではBattleManagerスクリプト(戦闘管理スクリプト)やCharacterBattleScriptスクリプト(戦闘時のキャラクター毎の行動処理スクリプト)内でDebug.Logを使ってコンソールに戦闘時のメッセージを表示していました。
ですがコンソールで確認出来るのはゲーム開発者がUnityエディターを開いている時だけなので、メッセージをゲーム内のUIに表示してわかりやすくしたいと思います。
戦闘時のゲーム画面の下の方はコマンドパネル関連で埋めてしまったので、メッセージはゲーム画面の上に表示するようにします。
新しいメッセージが表示されたら古いメッセージが上に流れていくような表示方法もあると思いますが、今回は一言メッセージを表示するだけで過去のメッセージは追えないようにします。
なぜそうするかというとこちらの方が簡単だからです。(´Д`)
また古いメッセージは新しいメッセージが表示されるタイミングで消すことにします。
新しいメッセージが表示されなくても一定の時間が経ったら古いメッセージは消えるようにします。
メッセージ表示パネルのプレハブを作成
まずは戦闘時のメッセージを表示するパネルのプレハブを作成していきます。
BattleUIゲームオブジェクトを選択した状態で右クリックからUI→Panelを選択し名前をMessagePanelとし、インスペクタのImageのColorを他のUIと同じように少し透けた黒色にします。
MessagePanelの位置とサイズは以下のようにしました。
MessagePanelを選択した状態で右クリックからUI→Textを選択しRectTransformのAnchor Presetsでstretch stretchを選択しMessagePanelのサイズに合わせてTextの領域も変わるようにします。
Textにはデフォルトのメッセージを表示し、Font Sizeは24にしました。
ParagraphのAlignmentは真ん中表示にし、Colorは緑色にします。
出来たらAssets/RPG/Prefabs/UI/BattleCommandフォルダにヒエラルキー上のMessagePanelをドラッグ&ドロップしてプレハブにします。
ヒエラルキー上のMessagePanelは使わないので削除します。
BattleManagerスクリプトにメッセージ機能を追加
メッセージ表示機能はBattleManagerスクリプトに作成し、CharacterBattleScriptからメッセージを表示する場合はBattleManagerスクリプトのメッセージ表示機能を介して行います。
まずはBattleManagerスクリプトにフィールドを追加します。
1 2 3 4 5 6 7 8 9 10 | // メッセージパネルプレハブ [SerializeField] private GameObject messagePanel; // BattleUI [SerializeField] private Transform battleUI; // メッセージパネルインスタンス private GameObject messagePanelIns; |
messagePanelは先ほど作ったMessagePanelプレハブをインスペクタで設定します。
battleUIはインスペクタでヒエラルキー上のBattleUIゲームオブジェクトを設定します。
messagePanelInsはmessagePanelプレハブから作成したインスタンスを入れておくフィールドです。
次に受け取ったメッセージを表示するメソッドを定義します。
1 2 3 4 5 6 7 8 9 10 | // メッセージ表示 public void ShowMessage(string message) { if(messagePanelIns != null) { Destroy(messagePanelIns); } messagePanelIns = Instantiate<GameObject>(messagePanel, battleUI); messagePanelIns.transform.Find("Text").GetComponent<Text>().text = message; } |
ShowMessageメソッドはstring型の引数を受け取ります。
messagePanelInsがnullでなければ既にメッセージが表示されているのでmessagePanelInsに入っているゲームオブジェクトを削除します。
その後messagePanelをインスタンス化しbattleUIを親にします。
messagePanelの子要素のTextゲームオブジェクトのTextコンポーネントを取得し、そこに引数で受け取ったメッセージを表示します。
MessagePanelを一定時間が経過したら自動で削除させるスクリプト
MessagePanelをインスタンス化する事が出来ましたが、次のメッセージが表示されない限りずっと残ってしまいます。
そこでAssets/RPG/Scripts/Battleフォルダに新しくDeleteMessagePanelスクリプトを作成しMessagePanelプレハブに取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class DeleteMessagePanel : MonoBehaviour { [SerializeField] private float waitTime = 3f; // Start is called before the first frame update void Start() { StartCoroutine(Delete()); } IEnumerator Delete() { yield return new WaitForSeconds(waitTime); Destroy(this.gameObject); } } |
waitTimeはMessagePanelが表示されてから消えるまでの時間で、インスペクタで設定出来るようにします。
Startメソッドはこのスクリプトが設定されたゲームオブジェクトが登場した時に呼ばれるので、その中でコルーチンを使ってDeleteメソッドを呼び出し、
1 2 3 | yield return new WaitForSeconds(waitTime); |
でwaitTime秒を経過した後にDestroyでこのスクリプトが設定されたゲームオブジェクトを削除しています。
コルーチンに関しては
を参照してください。
BattleManagerスクリプトでShowMessageメソッドを呼び出す
メッセージ表示メソッドShowMessageが出来たので後はそれを呼び出すだけです。
まずはBattleManagerスクリプト内でShowMessageメソッドを呼び出す処理を追加します。
ShowMessageメソッドを挿入する箇所以外は省いています。
元々あったDebug.Logは残してもいいですし、消してもいいです。
まずはStartメソッド内に追加します。
1 2 3 4 5 | void Start() { ShowMessage("戦闘開始"); } |
EnemyAttackメソッド内に追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public void EnemyAttack(GameObject character) { if (nowSkill.GetSkillType() == Skill.Type.DirectAttack) { } else if (nowSkill.GetSkillType() == Skill.Type.MagicAttack) { if (characterBattleScript.GetMp() >= ((Magic)nowSkill).GetAmountToUseMagicPoints()) { } else { ShowMessage("MPが足りない!"); } } else if (nowSkill.GetSkillType() == Skill.Type.RecoveryMagic) { if (characterBattleScript.GetMp() >= ((Magic)nowSkill).GetAmountToUseMagicPoints()) { } else { ShowMessage("MPが足りない!"); } } else if (nowSkill.GetSkillType() == Skill.Type.Guard) { ShowMessage(character.name + "は" + nowSkill.GetKanjiName() + "を行った"); } } |
UseMagicメソッド内に追加します。
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 | // 魔法を使う public void UseMagic(GameObject user, GameObject targetCharacter, Skill skill) { // 使う魔法の種類の設定と対象に使う必要がない場合の処理 if (skill.GetSkillType() == Skill.Type.MagicAttack) { } else if (skill.GetSkillType() == Skill.Type.RecoveryMagic) { if (targetCharacterBattleScript.GetHp() == targetCharacterBattleScript.GetCharacterStatus().GetMaxHp()) { ShowMessage(targetCharacter.name + "は全快です。"); return; } battleState = CharacterBattleScript.BattleState.Healing; } else if (skill.GetSkillType() == Skill.Type.IncreaseAttackPowerMagic) { if (targetCharacterBattleScript.IsIncreasePower()) { ShowMessage("既に攻撃力を上げています。"); return; } battleState = CharacterBattleScript.BattleState.IncreaseAttackPowerMagic; } else if (skill.GetSkillType() == Skill.Type.IncreaseDefencePowerMagic) { if (targetCharacterBattleScript.IsIncreaseStrikingStrength()) { ShowMessage("既に防御力を上げています。"); return; } battleState = CharacterBattleScript.BattleState.IncreaseDefencePowerMagic; } else if (skill.GetSkillType() == Skill.Type.NumbnessRecoveryMagic) { if (!targetCharacterBattleScript.IsNumbness()) { ShowMessage(targetCharacter.name + "は痺れ状態ではありません。"); return; } battleState = CharacterBattleScript.BattleState.NumbnessRecoveryMagic; } else if (skill.GetSkillType() == Skill.Type.PoisonnouRecoveryMagic) { if (!targetCharacterBattleScript.IsPoison()) { ShowMessage(targetCharacter.name + "は毒状態ではありません。"); return; } } } |
SelectItemメソッドに追加します。
1 2 3 4 5 6 7 8 9 10 11 | // 使用するアイテムの選択 public void SelectItem(GameObject character) { if (magicOrItemPanelContent.childCount > 0) { } else { ShowMessage("使えるアイテムがありません。"); } } |
UseItemメソッドに追加します。
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 | // アイテム使用 public void UseItem(GameObject user, GameObject targetCharacter, Item item) { if (item.GetItemType() == Item.Type.HPRecovery) { if (targetCharacterBattleScript.GetHp() == targetCharacterBattleScript.GetCharacterStatus().GetMaxHp()) { ShowMessage(targetCharacter.name + "は全快です。"); return; } battleState = CharacterBattleScript.BattleState.UseHPRecoveryItem; } else if (item.GetItemType() == Item.Type.MPRecovery) { if (targetCharacterBattleScript.GetMp() == targetCharacterBattleScript.GetCharacterStatus().GetMaxMp()) { ShowMessage(targetCharacter.name + "はMP回復をする必要がありません。"); return; } battleState = CharacterBattleScript.BattleState.UseMPRecoveryItem; } else if (item.GetItemType() == Item.Type.NumbnessRecovery) { if (!targetCharacterBattleScript.IsNumbness()) { ShowMessage(targetCharacter.name + "は痺れ状態ではありません。"); return; } battleState = CharacterBattleScript.BattleState.UseNumbnessRecoveryItem; } else if (item.GetItemType() == Item.Type.PoisonRecovery) { if (!targetCharacterBattleScript.IsPoison()) { ShowMessage(targetCharacter.name + "は毒状態ではありません。"); return; } } } |
GetAwayメソッドに追加します。
1 2 3 4 5 6 7 8 9 10 11 12 | // 逃げる public void GetAway(GameObject character) { var randomValue = Random.value; if (0f <= randomValue && randomValue <= 0.2f) { ShowMessage("逃げるのに成功した。"); } else { ShowMessage("逃げるのに失敗した。"); } } |
DeleteAllyCharacterInBattleListメソッドとDeleteEnemyCharacterInBattleListメソッドに追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | public void DeleteAllyCharacterInBattleList(GameObject deleteObj) { if (allyCharacterInBattleList.Count == 0) { ShowMessage("味方が全滅"); } } public void DeleteEnemyCharacterInBattleList(GameObject deleteObj) { if (enemyCharacterInBattleList.Count == 0) { ShowMessage("敵が全滅"); } } |
味方、敵が全滅した時は戦闘が終了するので別のメッセージ表示機能に変える可能性がありますが、とりあえず設定しました。
CharacterBattleScriptでShowMessageメソッドを呼び出す
CharacterBattleScriptスクリプトでShowMessageメソッドを呼び出す処理を追加します。
まずはChooseAttackOptionsメソッドでスキルを使ったキャラクターのメッセージを表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // 選択肢から選んだモードを実行 public void ChooseAttackOptions(BattleState selectOption, GameObject target, Skill skill = null, Item item = null) { if (selectOption == BattleState.DirectAttack) { battleManager.ShowMessage(gameObject.name + "は" + currentTarget.name + "に" + currentSkill.GetKanjiName() + "を行った。"); } else if (selectOption == BattleState.MagicAttack || selectOption == BattleState.Healing || selectOption == BattleState.IncreaseAttackPowerMagic || selectOption == BattleState.IncreaseDefencePowerMagic || selectOption == BattleState.NumbnessRecoveryMagic || selectOption == BattleState.PoisonnouRecoveryMagic ) { battleManager.ShowMessage(gameObject.name + "は" + currentTarget.name + "に" + currentSkill.GetKanjiName() + "を使った。"); } else if (selectOption == BattleState.UseHPRecoveryItem || selectOption == BattleState.UseMPRecoveryItem || selectOption == BattleState.UseNumbnessRecoveryItem || selectOption == BattleState.UsePoisonRecoveryItem ) { battleManager.ShowMessage(gameObject.name + "は" + currentTarget.name + "に" + item.GetKanjiName() + "を使った。"); } } |
DirectAttackメソッドに追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public void DirectAttack() { // 攻撃相手のStatus if (targetCharacterStatus as AllyStatus != null) { damage = Mathf.Max(0, (characterStatus.GetPower() + auxiliaryPower) - targetDefencePower); battleManager.ShowMessage(currentTarget.name + "は" + damage + "のダメージを受けた。"); // 相手のステータスのHPをセット targetCharacterBattleScript.SetHp(targetCharacterBattleScript.GetHp() - damage); } else if (targetCharacterStatus as EnemyStatus != null) { damage = Mathf.Max(0, (characterStatus.GetPower() + (((AllyStatus)characterStatus).GetEquipWeapon()?.GetAmount() ?? 0) + auxiliaryPower) - targetDefencePower); battleManager.ShowMessage(currentTarget.name + "は" + damage + "のダメージを受けた。"); // 敵のステータスのHPをセット targetCharacterBattleScript.SetHp(targetCharacterBattleScript.GetHp() - damage); } else { } Debug.Log(gameObject.name + "は" + currentTarget.name + "に" + currentSkill.GetKanjiName() + "をして" + damage + "を与えた。"); } |
DirectAttackではダメージを計算した後にすぐダメージ表示をShowMessageメソッドで行っています。
これはCharacterBattleScriptのSetHpメソッド内でHPが0以下になったかどうかで死んだかどうか判定し、Deadメソッドを呼び出すために、Debug.Logの位置と同じ個所でShowMessageメソッドを呼ぶと、
死んだ後に『~に何ダメージを与えた。』というメッセージが表示されてしまうからです。
ただ今回のメッセージ機能の仕様上、ダメージを表示したメッセージの直ぐ後にSetHpメソッド内でDeadメソッドが呼ばれて死んだ場合はダメージ数のメッセージ表示がされず(見えない)『倒れた』というメッセージが表示されます。
MagicAttackに追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public void MagicAttack() { // 攻撃相手のStatus if (targetCharacterStatus as AllyStatus != null) { damage = Mathf.Max(0, ((Magic)currentSkill).GetMagicPower() - targetDefencePower); battleManager.ShowMessage(currentTarget.name + "は" + damage + "のダメージを受けた。"); //// 相手のステータスのHPをセット targetCharacterBattleScript.SetHp(targetCharacterBattleScript.GetHp() - damage); } else if (targetCharacterStatus as EnemyStatus != null) { damage = Mathf.Max(0, ((Magic)currentSkill).GetMagicPower() - targetDefencePower); battleManager.ShowMessage(currentTarget.name + "は" + damage + "のダメージを受けた。"); // 相手のステータスのHPをセット targetCharacterBattleScript.SetHp(targetCharacterBattleScript.GetHp() - damage); } else { } Debug.Log(gameObject.name + "は" + currentTarget.name + "に" + currentSkill.GetKanjiName() + "をして" + damage + "を与えた。"); } |
UseMagicに処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public void UseMagic() { if (magicType == Skill.Type.RecoveryMagic) { Debug.Log(gameObject.name + "は" + ((Magic)currentSkill).GetKanjiName() + "を使って" + currentTarget.name + "を" + recoveryPoint + "回復した。"); battleManager.ShowMessage(currentTarget.name + "を" + recoveryPoint + "回復した。"); } else if (magicType == Skill.Type.IncreaseAttackPowerMagic) { Debug.Log(gameObject.name + "は" + ((Magic)currentSkill).GetKanjiName() + "を使って" + currentTarget.name + "の力を" + increasePowerPoint + "増やした。"); battleManager.ShowMessage(currentTarget.name + "の力を" + increasePowerPoint + "増やした。"); } else if (magicType == Skill.Type.IncreaseDefencePowerMagic) { Debug.Log(gameObject.name + "は" + ((Magic)currentSkill).GetKanjiName() + "を使って" + currentTarget.name + "の打たれ強さを" + increaseStrikingStrengthPoint + "増やした。"); battleManager.ShowMessage(currentTarget.name + "の打たれ強さを" + increaseStrikingStrengthPoint + "増やした。"); } else if (magicType == Skill.Type.NumbnessRecoveryMagic) { Debug.Log(gameObject.name + "は" + ((Magic)currentSkill).GetKanjiName() + "を使って" + currentTarget.name + "の痺れを消した"); battleManager.ShowMessage(currentTarget.name + "の痺れを消した"); } else if (magicType == Skill.Type.PoisonnouRecoveryMagic) { Debug.Log(gameObject.name + "は" + ((Magic)currentSkill).GetKanjiName() + "を使って" + currentTarget.name + "の毒を消した"); battleManager.ShowMessage(currentTarget.name + "の毒を消した"); } } |
UseItemに処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public void UseItem() { if (currentItem.GetItemType() == Item.Type.HPRecovery) { Debug.Log(gameObject.name + "は" + currentItem.GetKanjiName() + "を使って" + currentTarget.name + "のHPを" + recoveryPoint + "回復した。"); battleManager.ShowMessage(currentTarget.name + "のHPを" + recoveryPoint + "回復した。"); } else if (currentItem.GetItemType() == Item.Type.MPRecovery) { Debug.Log(gameObject.name + "は" + currentItem.GetKanjiName() + "を使って" + currentTarget.name + "のMPを" + recoveryPoint + "回復した。"); battleManager.ShowMessage(currentTarget.name + "のMPを" + recoveryPoint + "回復した。"); } else if(currentItem.GetItemType() == Item.Type.NumbnessRecovery) { Debug.Log(gameObject.name + "は" + currentItem.GetKanjiName() + "を使って" + currentTarget.name + "の痺れを消した。"); battleManager.ShowMessage(currentTarget.name + "の痺れを消した。"); } else if(currentItem.GetItemType() == Item.Type.PoisonRecovery) { Debug.Log(gameObject.name + "は" + currentItem.GetKanjiName() + "を使って" + currentTarget.name + "の毒を消した。"); battleManager.ShowMessage(currentTarget.name + "の毒を消した。"); } } |
Guardメソッドに処理を追加します。
1 2 3 4 5 6 | // 防御 public void Guard() { battleManager.ShowMessage(gameObject.name + "は防御を行った。"); } |
Deadメソッドに処理を追加します。
1 2 3 4 5 6 7 | // 死んだときに実行する処理 public void Dead() { Debug.Log(gameObject.name + "は倒れた。"); battleManager.ShowMessage(gameObject.name + "は倒れた。"); } |
CheckIncreaseAttackPowerメソッドとCheckIncreaseStrikingStrengthメソッドに処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public void CheckIncreaseAttackPower() { // 自分のターンが来た時に何らかの効果魔法を使ってたらターン数を増やす if (IsIncreasePower()) { if (numOfTurnsSinceIncreasePower >= numOfTurnsIncreasePower) { Debug.Log(gameObject.name + "の攻撃力アップの効果が消えた"); battleManager.ShowMessage(gameObject.name + "の攻撃力アップの効果が消えた"); } } } public void CheckIncreaseStrikingStrength() { if (IsIncreaseStrikingStrength()) { if (numOfTurnsSinceIncreaseStrikingStrength >= numOfTurnsIncreaseStrikingStrength) { Debug.Log(gameObject.name + "の防御力アップの効果が消えた"); battleManager.ShowMessage(gameObject.name + "の防御力アップの効果が消えた"); } } } |
これで処理の追加が終わりました。
BattleManagerのインスペクタの設定は以下のようになります。
実際に実行して確認してみます。
上のようになりました。
終わりに
戦闘中の攻撃やアイテムの使用等はパーティクルなどのエフェクトでわかりやすくするのももちろんですが、テキスト表示をすることで何をしたか?がわかりやすくなりますね。
この作品はユニティちゃんライセンス条項の元に提供されています