今回は戦闘シーンで味方のターンが回ってきた時に持っているスキルの中から選択肢を選ぶ機能を作成していきたいと思います。
前回は戦闘シーンでの敵のターンの行動処理を作成しました。
ユニティちゃんのRPGを作ってみようの他の記事は
から見ることが出来ます。
前回は戦闘での敵のターンの行動処理を作成しました。
敵の行動はあらかじめ何らかの行動パターンを作成し、それを実行することで行いましたが、
味方の行動は敵と同じように自動で行動を起こすようにしてもいいですが、基本的にはゲームのユーザーが自分で行動を選択して攻撃をする相手や魔法を使う相手を選択します。
戦闘に参加しているキャラクターには既に戦闘時のキャラクターの行動スクリプトCharacterBattleScriptを設定してあり、後はBattleManagerで作成したボタンでどのスキルを使って対象を誰にするか?を決定し、CharacterBattleScriptの機能を呼び出して行動をさせるだけです。
行動をさせるだけというと簡単に聞こえますが、ユーザーが選ぶ事が出来る行動をボタンとして用意しそれを選択したら攻撃等を行う対象者を選ぶといったように以前作成したアイテムコマンドの作成と同じように面倒な事をする必要があります。(^_^;)
前回に続き今回も結構大変ですが、この記事を終えたらユニティちゃんRPGの面倒な機能は作り終えると思って頑張ってみてください。(´Д`)
UIの作成
味方が起こす行動等を表示するUI群を作っていきます。
UIのサイズや表示する場所等はとりあえず作りました程度の作りとなっていますので、任意で調整してください。
どのスキルを使うか?の選択UI
まずはターンが回ってきた味方キャラクターが持っているスキルをボタンで作成します。
BattleUIを選択した状態で右クリックからUI→Panelを選択し、名前をCommandPanelとします。
CommandPanelはStatusPanelの横に配置します。
CommandPanelのAdd ComponentからLayout→Vertical Layout Group、Layout→Canvas Groupを取り付けます。
Vertical Layout GroupのSpacingに1、Control Child SizeのWidthとChild Force ExpandのWidthにチェックを入れ、
Canvas Groupのinteractableのチェックを外しておきます。
次にCommandPanelを選択した状態で右クリックからUI→Panelを選択し名前をCharacterNameとします。
CharacterNameのRectTransformのHeightを35にし、ImageのColorを緑色、Raycast Targetのチェックを外しマウス等で選択等を出来ないようにします。
CharacterNameを選択した状態で右クリックからUI→Textを選択し、Font Sizeを25、ParagraphのAlignmentを真ん中、Colorを白色にします。
CommandPanelにAssets/RPG/Prefabs/UI/CommandフォルダのCharacterButtonプレハブをドラッグ&ドロップし、ヒエラルキー上のCharacterButtonを選択した状態で右クリックからUnpack Prefab Completelyを選択しプレハブとのリンクを解除します。
名前をDirectAttackと変更します。
DirectAttackのインスペクタでCommandPanelButtonScriptスクリプトを削除します。
Add Componentを押してLayout→Horizontal Layout Groupを取り付けます。
PaddingのLeftを10、Control Child SizeのHeight、Child Force ExpandのHeightにチェックを入れます。
DirectAttackボタンの子要素の高さのサイズと拡張が自動でされるようになります。
DirectAttackのRectTransformのHeightを35にします。
Assets/RPG/Scripts/Battleフォルダに新しくBattleCommandPanelButtonScriptスクリプトを作成しDirectAttackに取り付けます。
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 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class BattleCommandPanelButtonScript : MonoBehaviour, ISelectHandler, IDeselectHandler { // ボタンを選択した時に表示する画像 private Image selectedImage; // 選択した時の音のAudioSource private AudioSource audioSource; void Awake() { selectedImage = transform.Find("Image").GetComponent<Image>(); audioSource = GetComponent<AudioSource>(); } private void OnEnable() { // アクティブになった時自身がEventSystemで選択されていたら if (EventSystem.current.currentSelectedGameObject == this.gameObject) { selectedImage.enabled = true; audioSource.Play(); } else { selectedImage.enabled = false; } } // ボタンが選択された時に実行 public void OnSelect(BaseEventData eventData) { selectedImage.enabled = true; audioSource.Play(); } // ボタンが選択解除された時に実行 public void OnDeselect(BaseEventData eventData) { selectedImage.enabled = false; } } |
中身はAssets/RPG/Scripts/CommandPanelButtonScriptスクリプトと同じです。
なんで作ったんだったか覚えてません・・・・(´Д`)
DirectAttack子要素のImageのwidthを30、
TextのWidthを150、TextのParagraphのAlignmentを真ん中にします。
Textには攻撃と入力します。
DirectAttackにはHorizontal Layout Groupコンポーネントを取り付けているので、子要素のImageをドラッグしてTextの上に移動させ、左側にImageがくるようにします。
DirectAttackを選択した状態でCtrl+Dキーを4回押し複製し、名前をGuard、Item、Magic、GetAwayと変更し、それぞれのボタンの子要素のTextに『防御』、『アイテム』、『魔法』、『逃げる』と入力します。
これでCommandPanelが出来ました。
CommandPanelの子要素のボタン群が押された時に実行する処理はBattleManagerスクリプトから後で取り付けます。
キャラクター選択パネル
次に攻撃等をした時に誰に攻撃をするか?の選択をするパネルを作成します。
BattleUIを選択した状態で右クリックからUI→Panelを選択し、名前をSelectCharacterPanelとしてCommandPanelの横にサイズを調整します。
SelectCharacterPanelにはVertical Layout GroupとCanvas Groupコンポーネントを取り付け以下のように設定します。
キャラクター選択ボタンの作成
SelectCharacterPanelに配置するボタンのプレハブを作成します。
Assets/RPG/Prefabs/UI/Command/CharacterButtonをSelectCharacterPanelの子要素に配置し、右クリックからUnpack Prefab Completelyを選択しプレハブと解除します。
名前をBattleCharacterButtonと変更し、インスペクタのCommandPanelButtonScriptを削除します。
そして先ほど作ったBattleCommandPanelButtonScriptを取り付けます。
またインスペクタのAdd Componentを押しLayout→Horizontal Layout Groupを取り付けます。
PaddingのLeftに10、Control Child SizeのHeight、Child Force ExpandのHeightにチェックを入れます。
BattleCharacterButtonの子要素のImageのRectTransformのWidthは30にし、
子要素のTextのWidthは200にしました。
数値は任意です。
BattleCharacterButtonの子要素のImageをドラッグしTextの上にくるようにし、左側にImageが表示されるようにします。
ここまで出来たらAssets/RPG/Prefabs/UI/BattleCommandフォルダを作成し、そこにBattleCharacterButtonをドラッグ&ドロップしてプレハブにします。
SelectCharacterPanelに表示するキャラクターのボタンはスクリプトから生成するので子要素にはあらかじめボタンを配置しません。
ヒエラルキー上のBattleCharacterButtonは削除しておきます。
魔法やアイテム表示パネル
次に魔法やアイテムの行動を起こした時に、どの魔法やアイテムを使うか?を選択するパネルを作成します。
魔法とアイテムの違いだけで表示するパネルは同じなので共通で使用します。
作り方としてはアイテムコマンドで作成したItemPanelと同じなのでそちらも参考にしてください。
この場合はアイテム一覧と魔法一覧のパネルを別に作る必要があります。
BattleUIを選択した状態で右クリックからUI→Panelを選択し、名前をMagirOrItemPanelとします。
以下のような位置とサイズにします。
MagicOrItemPanelを選択した状態で右クリックからUI→Panelを選択しMaskとします。
MaskはMagicOrItemPanelでマスクする領域に使います。
MaskのインスペクタのAdd Componentを押しUI→Maskを取り付け、Show Mask Graphicのチェックを外します。
Show Mask Graphicのチェックを外すと、マスク部分のグラフィックが非表示になります。
Maskのサイズは横のスクロールバー(この後作成する)を外した感じのサイズにします。
Maskを選択した状態で右クリックからUI→Panelを選択し、名前をContentとします。
ContentのRectTransformのAnchor Presetsからtop stretchを選択し、Heightを3000にします。
ContentのImageコンポーネントは使わないので横のチェックを外すか、削除します。
ContentのインスペクタのAdd Componentボタンを押し、Layout→Grid Layout Groupを取り付けPaddingのTopを3、Cell SizeのXを360、Yを50、SpacingのXを50、Yを10とします。
またScrollManagerスクリプトを取り付けScroll Speedを1000、Scroll Valueを300としました。
Contentが実際に魔法やアイテムのボタンを表示する場所になります。
MagicOrItemPanelを選択した状態で右クリックからUI→Scrollbarを選択します。
ScrollbarのRectTransformのAnchor Presetsでmiddle rightにし、Widthを20、Heightを160とします。
interactableのチェックを外しスクロールバーを操作出来ないようにします。
ScrollbarのDirectionをBottom To Topにします。
MagicOrItemPanelのインスペクタのAdd ComponentからUI→ScrollRectとLayout→Canvas Groupを取り付けます。
Scroll RectのContentに先ほど作ったContentゲームオブジェクト、Vertical Scrollbarには先ほど作ったScrollbarゲームオブジェクトを設定します。
MovementTypeはClampedにします。
Canvas Groupのinteractableのチェックは外しておきます。
アイテムのプレハブボタンの作成
MagicOrItemPanelボタンにアイテム一覧を表示する時のアイテムボタンのプレハブを作成します。
Assets/RPG/Prefabs/UI/Command/ItemPanelButtonをMagicOrItemPanelの子要素のContentにドラッグ&ドロップし、ヒエラルキー上のItemPanelButtonを選択して右クリックからUnpack Prefab Completelyを選択しプレハブとのリンクを解除します。
名前をBattleItemPanelButtonとし、インスペクタのItemPanelButtonScriptスクリプトを削除します。
ヒエラルキー上のBattlItemPanelButtonをAssets/RPG/Prefabs/UI/BattleCommandフォルダにドラッグ&ドロップしてプレハブにし、ヒエラルキー上のBattleItemPanelButtonは削除します。
魔法のプレハブボタンを作成
MagicOrItemPanelボタンに魔法一覧を表示する時の魔法ボタンのプレハブを作成します。
先ほど作成したAssets/RPG/Prefabs/UI/BattleCommand/BattleItemPanelButtonをContentにドラッグ&ドロップして右クリックからUnpack Prefab Completelyを選択しプレハブとのリンクを解除します。
名前をBattleMagicPanelButtonとします。
魔法の場合は選択時のアイコン、魔法の名前、使用MPの情報だけがあればいいので、子要素のEquip、Multiplyを削除します。
またItemNameという名前をMagicNameに、NumをAmountToUseMagicPointsに変更します。
BattleMagicPanelButtonの子要素のWidthは良い感じで調整してみてください・・・・・(;_;)/~~~
BattleMagicPanelButtonをAssets/RPG/Prefabs/UI/BattleCommandフォルダにドラッグ&ドロップしてプレハブにします。
Mask領域の調整をする
アイテムコマンドのアイテム一覧のスクロール機能と同じように戦闘シーンでのアイテムや魔法の一覧をスクロールする時の為にボタンが丁度良く表示されるようにMask領域を調整します。
MagicOrItemPanel/Mask/ContentにまだBattleMagicPanelButtonを残したままだと思うので、選択した状態でCtrl+Dキーを押してMagicOrItemPanelの表示領域を超えるぐらいのボタンを複製します。
すると下の方にボタンがはみ出て見えるので、Maskの領域を調整してボタンが丁度見えるように調整します。
細かい調整はスクリプトで設定した値との兼ね合いもあるので後で調整します(やり方はアイテムコマンドの時と同じ)。
これで味方キャラクターの行動の選択肢のUIが出来ました。
味方キャラクターの行動処理スクリプトの追加
UIが出来たのでBattleManagerに味方キャラクターの行動処理をする為の記述を追加します。
BattleManagerですることはCommandPanelのボタンを押した時に実行する処理を追加したり、攻撃等の対象の選択ボタンの作成、使用出来るアイテムや魔法一覧の表示等です。
実際に攻撃や魔法、アイテムの処理をするのはそのキャラクターが持つCharacterBattleScriptでBattleManagerから選択した行動を依頼します。
BattleManagerスクリプトに処理を追加していきます。
フィールドの追加
まずはフィールドを追加します。
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 | // 味方パーティーのコマンドパネル [SerializeField] private Transform commandPanel = null; // 戦闘用キャラクター選択ボタンプレハブ [SerializeField] private GameObject battleCharacterButton = null; // SelectCharacterPanel [SerializeField] private Transform selectCharacterPanel = null; // 魔法やアイテム選択パネル [SerializeField] private Transform magicOrItemPanel = null; // 魔法やアイテム選択パネルのContent private Transform magicOrItemPanelContent = null; // BattleItemPanelButtonプレハブ [SerializeField] private GameObject battleItemPanelButton = null; // BattleMagicPanelButtonプレハブ [SerializeField] private GameObject battleMagicPanelButton = null; // 最後に選択していたゲームオブジェクトをスタック private Stack<GameObject> selectedGameObjectStack = new Stack<GameObject>(); // MagicOrItemPanelでどの番号のボタンから上にスクロールするか [SerializeField] private int scrollDownButtonNum = 8; // MagicOrItemPanelでどの番号のボタンから下にスクロールするか [SerializeField] private int scrollUpButtonNum = 10; // ScrollManager private ScrollManager scrollManager; |
magicOrItemPanelはMagicOrItemPanelゲームオブジェクトをインスペクタで設定します。
magicOrItemPanelContentはMagicOrItemPanelの階層から取得します。
battleItemPanelButtonはアイテム一覧を表示する時の表示するボタンのプレハブBattleItemPanelButtonをインスペクタで設定します。
battleMagicPanelButtonは魔法一覧を表示する時の表示するボタンのプレハブBattleMagicPanelButtonをインスペクタで設定します。
selectedGameObjectStackは前に選択していたゲームオブジェクトを保持して前の選択に戻った時にそのゲームオブジェクトを選択しなおす為に使用します(アイテムコマンドの時と同じです)。
それ以降のフィールドは一覧をスクロールさせる為の設定で、アイテムコマンドの時と同じなので特に問題はないと思います。
Startメソッド
Startメソッドに処理を追加していきます。
追加する場所は味方パーティーのプレハブをインスタンス化している繰り返し処理の前にします。
1 2 3 4 | magicOrItemPanelContent = magicOrItemPanel.Find("Mask/Content"); scrollManager = magicOrItemPanelContent.GetComponent<ScrollManager>(); |
magicOrItemPanelContentはmagicOrItemPanelの子要素から取得します。
scrollManagerはMagicOrItemPanelから取得します。
Updateメソッド
Updateメソッドに処理を追加していきます。
まずはif文でbattleIsOverが真かどうかを判定している下に以下の処理を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 選択解除された時(マウスでUI外をクリックした)は現在のモードによって無理やり選択させる if (EventSystem.current.currentSelectedGameObject == null) { if (currentCommand == CommandMode.SelectCommand) { EventSystem.current.SetSelectedGameObject(commandPanel.GetChild(1).gameObject); } else if (currentCommand == CommandMode.SelectDirectAttacker) { EventSystem.current.SetSelectedGameObject(selectCharacterPanel.GetChild(0).gameObject); } else if (currentCommand == CommandMode.SelectMagic) { scrollManager.Reset(); EventSystem.current.SetSelectedGameObject(magicOrItemPanelContent.GetChild(0).gameObject); } else if (currentCommand == CommandMode.SelectMagicAttackTarget) { EventSystem.current.SetSelectedGameObject(selectCharacterPanel.GetChild(0).gameObject); } else if (currentCommand == CommandMode.SelectUseMagicOnAlliesTarget) { EventSystem.current.SetSelectedGameObject(selectCharacterPanel.GetChild(0).gameObject); } else if (currentCommand == CommandMode.SelectItem) { scrollManager.Reset(); EventSystem.current.SetSelectedGameObject(magicOrItemPanelContent.GetChild(0).gameObject); } else if (currentCommand == CommandMode.SelectRecoveryItemTarget) { EventSystem.current.SetSelectedGameObject(selectCharacterPanel.GetChild(0).gameObject); } } |
これはEventSystemがどのUIも選択していない時に現在のコマンド状況に応じて無理やりUIを選択させるための処理です。
例えばマウスでUIのボタン以外をクリックするとEventSystemは何も選択していない状態になり選択していたボタンのアイコンも消えてしまいます。
そこで上のような処理を記述して選択しているUIがなければ無理やり選択をさせるようにします。
CommandPanelだけは最初に名前を表示するパネルがあるのでGetChild(1)となります。
magicOrItemPanelでスクロールできる場合はスクロール値も初期位置に戻しています。
次にキャンセルボタンを押して前の選択肢に戻る時の処理を追加します。
UpdateメソッドのisStartBattleがtrueでisChoosingがtrueの時にキャンセルボタンが押された時の処理を追加します。
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 | // 戦闘開始 if (isStartBattle) { // 現在のキャラクターの攻撃が終わっている if (!isChoosing) { // 既に作成済みの処理群 } else { // キャンセルボタンを押した時の処理 if (Input.GetButtonDown("Cancel")) { if (currentCommand == CommandMode.SelectDirectAttacker) { // キャラクター選択ボタンがあれば全て削除 for (int i = selectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(selectCharacterPanel.transform.GetChild(i).gameObject); } selectCharacterPanel.GetComponent<CanvasGroup>().interactable = false; selectCharacterPanel.gameObject.SetActive(false); commandPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); currentCommand = CommandMode.SelectCommand; } else if (currentCommand == CommandMode.SelectMagic) { // magicOrItemPanelにボタンがあれば全て削除 for (int i = magicOrItemPanelContent.transform.childCount - 1; i >= 0; i--) { Destroy(magicOrItemPanelContent.transform.GetChild(i).gameObject); } magicOrItemPanel.GetComponent<CanvasGroup>().interactable = false; magicOrItemPanel.gameObject.SetActive(false); commandPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); currentCommand = CommandMode.SelectCommand; } else if (currentCommand == CommandMode.SelectMagicAttackTarget) { // selectCharacterPanelにボタンがあれば全て削除 for (int i = selectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(selectCharacterPanel.transform.GetChild(i).gameObject); } selectCharacterPanel.GetComponent<CanvasGroup>().interactable = false; selectCharacterPanel.gameObject.SetActive(false); magicOrItemPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); currentCommand = CommandMode.SelectMagic; } else if (currentCommand == CommandMode.SelectUseMagicOnAlliesTarget) { // selectCharacterPanelにボタンがあれば全て削除 for (int i = selectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(selectCharacterPanel.transform.GetChild(i).gameObject); } selectCharacterPanel.GetComponent<CanvasGroup>().interactable = false; selectCharacterPanel.gameObject.SetActive(false); magicOrItemPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); currentCommand = CommandMode.SelectMagic; } else if (currentCommand == CommandMode.SelectItem) { // magicOrItemPanelにボタンがあれば全て削除 for (int i = magicOrItemPanelContent.transform.childCount - 1; i >= 0; i--) { Destroy(magicOrItemPanelContent.transform.GetChild(i).gameObject); } magicOrItemPanel.GetComponent<CanvasGroup>().interactable = false; magicOrItemPanel.gameObject.SetActive(false); commandPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); currentCommand = CommandMode.SelectCommand; } else if (currentCommand == CommandMode.SelectRecoveryItemTarget) { // selectCharacterPanelにボタンがあれば全て削除 for (int i = selectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(selectCharacterPanel.transform.GetChild(i).gameObject); } selectCharacterPanel.GetComponent<CanvasGroup>().interactable = false; selectCharacterPanel.gameObject.SetActive(false); magicOrItemPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectedGameObjectStack.Pop()); currentCommand = CommandMode.SelectItem; } } } } else { // 既に作成済みの処理群 } |
やっていることは現在のモードに応じて該当するパネルにプレハブからインスタンス化したボタンを全て削除し、CanvasGroupのinteractableの変更やパネルの表示・非表示を行っています。
アイテムコマンドでも作ったので特に説明はいらないと思います。
味方パーティーの行動処理をするAllyAttack
味方パーティーの行動処理をするAllyAttackメソッドを作成します。
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 | // 味方の攻撃処理 public void AllyAttack(GameObject character) { currentCommand = CommandMode.SelectCommand; // キャラクター選択ボタンがあれば全て削除 for (int i = selectCharacterPanel.transform.childCount - 1; i >= 0; i--) { Destroy(selectCharacterPanel.transform.GetChild(i).gameObject); } // 魔法やアイテムパネルの子要素のContentにボタンがあれば全て削除 for (int i = magicOrItemPanelContent.transform.childCount - 1; i >= 0; i--) { Destroy(magicOrItemPanelContent.transform.GetChild(i).gameObject); } commandPanel.GetComponent<CanvasGroup>().interactable = true; selectCharacterPanel.GetComponent<CanvasGroup>().interactable = false; magicOrItemPanel.GetComponent<CanvasGroup>().interactable = false; // キャラクターがガード状態であればガードを解く if (character.GetComponent<Animator>().GetBool("Guard")) { character.GetComponent<CharacterBattleScript>().UnlockGuard(); } // キャラクターの名前を表示 commandPanel.Find("CharacterName/Text").GetComponent<Text>().text = character.gameObject.name; var characterSkill = character.GetComponent<CharacterBattleScript>().GetCharacterStatus().GetSkillList(); // 持っているスキルに応じてコマンドボタンの表示 if (characterSkill.Exists(skill => skill.GetSkillType() == Skill.Type.DirectAttack)) { var directAttackButtonObj = commandPanel.Find("DirectAttack").gameObject; var directAttackButton = directAttackButtonObj.GetComponent<Button>(); directAttackButton.onClick.RemoveAllListeners(); directAttackButtonObj.GetComponent<Button>().onClick.AddListener(() => SelectDirectAttacker(character)); directAttackButtonObj.SetActive(true); } else { commandPanel.Find("DirectAttack").gameObject.SetActive(false); } if (characterSkill.Exists(skill => skill.GetSkillType() == Skill.Type.Guard)) { var guardButtonObj = commandPanel.Find("Guard").gameObject; var guardButton = guardButtonObj.GetComponent<Button>(); guardButton.onClick.RemoveAllListeners(); guardButton.onClick.AddListener(() => Guard(character)); guardButtonObj.SetActive(true); } else { commandPanel.Find("Guard").gameObject.SetActive(false); } if (characterSkill.Exists(skill => skill.GetSkillType() == Skill.Type.Item)) { var itemButtonObj = commandPanel.Find("Item").gameObject; var itemButton = itemButtonObj.GetComponent<Button>(); itemButton.onClick.RemoveAllListeners(); itemButton.onClick.AddListener(() => SelectItem(character)); commandPanel.Find("Item").gameObject.SetActive(true); } else { commandPanel.Find("Item").gameObject.SetActive(false); } if (characterSkill.Exists(skill => skill.GetSkillType() == Skill.Type.MagicAttack) || characterSkill.Find(skill => skill.GetSkillType() == Skill.Type.IncreaseAttackPowerMagic) || characterSkill.Find(skill => skill.GetSkillType() == Skill.Type.IncreaseDefencePowerMagic) || characterSkill.Find(skill => skill.GetSkillType() == Skill.Type.NumbnessRecoveryMagic) || characterSkill.Find(skill => skill.GetSkillType() == Skill.Type.PoisonnouRecoveryMagic) || characterSkill.Find(skill => skill.GetSkillType() == Skill.Type.RecoveryMagic)) { var magicButtonObj = commandPanel.Find("Magic").gameObject; var magicButton = magicButtonObj.GetComponent<Button>(); magicButton.onClick.RemoveAllListeners(); magicButton.onClick.AddListener(() => SelectMagic(character)); magicButtonObj.SetActive(true); } else { commandPanel.Find("Magic").gameObject.SetActive(false); } if (characterSkill.Exists(skill => skill.GetSkillType() == Skill.Type.GetAway)) { var getAwayButtonObj = commandPanel.Find("GetAway").gameObject; var getAwayButton = getAwayButtonObj.GetComponent<Button>(); getAwayButton.onClick.RemoveAllListeners(); getAwayButton.onClick.AddListener(() => GetAway(character)); getAwayButtonObj.SetActive(true); } else { commandPanel.Find("GetAway").gameObject.SetActive(false); } EventSystem.current.SetSelectedGameObject(commandPanel.transform.GetChild(1).gameObject); commandPanel.gameObject.SetActive(true); } |
AllyAttackメソッドは現在ターンが回ってきている味方キャラクターのゲームオブジェクトを受け取ります。
currentModeに現在行う行動を選択している状態であるCommandMode.SelectCommandを入れます。
その後にアイテムや魔法の一覧や対象キャラクターの選択画面を前に開いていた場合はインスタンス化したボタンが残っているので全て削除します。
その後CommandPanelのCanvasGroupのinteractableをtrueにしCommandPanelのUIを操作出来るようにします。
selectCharacterPanel、magicOrItemPanelのCanvasGroupのinteractableはfalseにし操作出来ないようにします。
引数で受け取ったキャラクター(現在ターンが回ってきたキャラクター)のAnimatorのアニメーションパラメータのGuardがtrueであればfalseにし防御を解除します。
commandPanelから階層を辿ってCharacterName/TextゲームオブジェクトのTextコンポーネントを取得し、そこにキャラクター名を入れます。
その後キャラクターの持っているスキルリストを取得します。
取得したスキルリスト中に該当するスキルタイプのスキルがあるかどうかをExistsメソッドで調べあればCommandPanelに作成したボタンの表示、押した時に実行するメソッドの設定をします。
以下はDirectAttackの処理です。
1 2 3 4 5 6 7 8 9 10 11 12 | // 持っているスキルに応じてコマンドボタンの表示 if (characterSkill.Exists(skill => skill.GetSkillType() == Skill.Type.DirectAttack)) { var directAttackButtonObj = commandPanel.Find("DirectAttack").gameObject; var directAttackButton = directAttackButtonObj.GetComponent<Button>(); directAttackButton.onClick.RemoveAllListeners(); directAttackButtonObj.GetComponent<Button>().onClick.AddListener(() => SelectDirectAttacker(character)); directAttackButtonObj.SetActive(true); } else { commandPanel.Find("DirectAttack").gameObject.SetActive(false); } |
DirectAttackのスキルを持っていればCommandPanelの子要素のDirectAttackボタンを取得し、そのボタンのButtonコンポーネントを取得しButtonのonClickにAddListenerで実行するメソッドを指定しています。
ここら辺もアイテムコマンド作成時にやったので問題はないと思います。
DirectAttackのスキルを持っていなければDirectAttackボタンは表示しないようにします。
他のスキルもボタンを押した時に実行するメソッドが違うだけでやっていることは同じです。
これ以降の処理で同じような処理を作りますが、元のパネルから新しいパネルを開いたら、
元のパネルのCanvasGroupのinteractableをfalse、
新しいパネルのCanvasGroupのinteractableをtrueとパネルのゲームオブジェクトをアクティブにする。
という処理をしているだけなので説明は省きます。
直接攻撃をする相手を選択するSelectDirectAttackerメソッドの作成
DirectAttackボタンを押した時に実行するSelectDirectAttackerメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // キャラクター選択 public void SelectDirectAttacker(GameObject attackCharacter) { currentCommand = CommandMode.SelectDirectAttacker; commandPanel.GetComponent<CanvasGroup>().interactable = false; selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); GameObject battleCharacterButtonIns; foreach (var enemy in enemyCharacterInBattleList) { battleCharacterButtonIns = Instantiate<GameObject>(battleCharacterButton, selectCharacterPanel); battleCharacterButtonIns.transform.Find("Text").GetComponent<Text>().text = enemy.gameObject.name; battleCharacterButtonIns.GetComponent<Button>().onClick.AddListener(() => DirectAttack(attackCharacter, enemy)); } selectCharacterPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectCharacterPanel.GetChild(0).gameObject); selectCharacterPanel.gameObject.SetActive(true); } |
引数では攻撃をするキャラクターのゲームオブジェクトを受け取ります。
currentCommandを現在攻撃対象選択をしている状態のCommand.SelectDirectAttackerにします。
CommandPanelのCanvasGroupのinteractableをfalseにし、選択していたDirectAttackゲームオブジェクトをselectedGameObjectStackにプッシュします。
foreachを使って戦闘に参加している敵のリスト分繰り返しを行い、攻撃対象の敵数分のボタンを作成します。
battleCharacterButtonが戦闘シーン用のキャラクター選択ボタンのプレハブなのでこれをインスタンス化し、親をselectCharacterPanelにします。
battleCharacterButtonの子要素のTextゲームオブジェクトのTextコンポーネントを取得し、そこに敵のゲームオブジェクトの名前を設定します。
攻撃対象のボタンが押された時はDirectAttackメソッドに攻撃キャラクターと攻撃対象のキャラクターのゲームオブジェクトを渡して呼び出します。
攻撃対象の選択パネルに処理が移ったのでselectCharacterPanelのCanvasGroupのinteractableをtrueにしUIを選択可能にします。
EventSystem.current.SetSelectedGameObjectメソッドでSelectCharacterPanelの子要素の最初のUIを選択状態にします。
最後にSelectCharacterPanelをアクティブにします。
最終的な直接攻撃を決定する処理DirectAttackメソッド
SelectDirectAttackerメソッドで作成した攻撃対象者を選択するボタンが押された時に実行するDirectAttackメソッドを作成します。
DirectAttackメソッドは既に攻撃対象者が決定しているので、攻撃者のCharacterBattleScriptを呼び出して攻撃対象者に攻撃をする処理をしてもらうだけです。
1 2 3 4 5 6 7 8 9 10 11 | // 直接攻撃 public void DirectAttack(GameObject attackCharacter, GameObject attackTarget) { // 攻撃するキャラのDirectAttackスキルを取得する var characterSkill = attackCharacter.GetComponent<CharacterBattleScript>().GetCharacterStatus().GetSkillList(); Skill directAtatck = characterSkill.Find(skill => skill.GetSkillType() == Skill.Type.DirectAttack); attackCharacter.GetComponent<CharacterBattleScript>().ChooseAttackOptions(CharacterBattleScript.BattleState.DirectAttack, attackTarget, directAtatck); commandPanel.gameObject.SetActive(false); selectCharacterPanel.gameObject.SetActive(false); } |
CharacterBattleScriptのChooseAttackOptionsメソッドにSkill情報を渡したいので、攻撃者の持っているスキルリストからDirectAttackのスキルを探しそれを渡します。
防御処理をするGuardメソッド
防御を選択した時に実行するGuardメソッドを作成します。
1 2 3 4 5 6 7 8 | // 防御 public void Guard(GameObject guardCharacter) { guardCharacter.GetComponent<CharacterBattleScript>().Guard(); commandPanel.gameObject.SetActive(false); ChangeNextChara(); } |
引数で現在ターンが回ってきているキャラクターのゲームオブジェクトを受け取るので、そのゲームオブジェクトからCharacterBattleScriptコンポーネントを取得し、CharacterBattleScriptのGuardメソッドを実行させます。
防御した場合はそのまま次のキャラクターにターンを回します。
敵が防御をした場合は個別に処理を記述しましたが、Guardメソッドを呼び出すように変更してもいいかもしれませんね。
使用する魔法を選択するSelectMagicメソッド
CommandPanelの魔法ボタンを押した時の処理をするSelectMagicメソッドを作成します。
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 | // 使用する魔法の選択 public void SelectMagic(GameObject character) { currentCommand = CommandMode.SelectMagic; commandPanel.GetComponent<CanvasGroup>().interactable = false; selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); GameObject battleMagicPanelButtonIns; var skillList = character.GetComponent<CharacterBattleScript>().GetCharacterStatus().GetSkillList(); // MagicOrItemPanelのスクロール値の初期化 scrollManager.Reset(); int battleMagicPanelButtonNum = 0; foreach (var skill in skillList) { if (skill.GetSkillType() == Skill.Type.MagicAttack || skill.GetSkillType() == Skill.Type.RecoveryMagic || skill.GetSkillType() == Skill.Type.IncreaseAttackPowerMagic || skill.GetSkillType() == Skill.Type.IncreaseDefencePowerMagic || skill.GetSkillType() == Skill.Type.NumbnessRecoveryMagic || skill.GetSkillType() == Skill.Type.PoisonnouRecoveryMagic ) { battleMagicPanelButtonIns = Instantiate<GameObject>(battleMagicPanelButton, magicOrItemPanelContent); battleMagicPanelButtonIns.transform.Find("MagicName").GetComponent<Text>().text = skill.GetKanjiName(); battleMagicPanelButtonIns.transform.Find("AmountToUseMagicPoints").GetComponent<Text>().text = ((Magic)skill).GetAmountToUseMagicPoints().ToString(); // 指定した番号のアイテムパネルボタンにアイテムスクロール用スクリプトを取り付ける if (battleMagicPanelButtonNum != 0 && (battleMagicPanelButtonNum % scrollDownButtonNum == 0 || battleMagicPanelButtonNum % (scrollDownButtonNum + 1) == 0) ) { // アイテムスクロールスクリプトの取り付けて設定値のセット battleMagicPanelButtonIns.AddComponent<ScrollDownScript>(); } else if(battleMagicPanelButtonNum != 0 && (battleMagicPanelButtonNum % scrollUpButtonNum == 0 || battleMagicPanelButtonNum % (scrollUpButtonNum + 1) == 0) ) { battleMagicPanelButtonIns.AddComponent<ScrollUpScript>(); } // MPが足りない時はボタンを押しても何もせず魔法の名前を暗くする if (character.GetComponent<CharacterBattleScript>().GetMp() < ((Magic)skill).GetAmountToUseMagicPoints()) { battleMagicPanelButtonIns.transform.Find("MagicName").GetComponent<Text>().color = new Color(0.4f, 0.4f, 0.4f); } else { battleMagicPanelButtonIns.GetComponent<Button>().onClick.AddListener(() => SelectUseMagicTarget(character, skill)); } // ボタン番号を足す battleMagicPanelButtonNum++; if (battleMagicPanelButtonNum == scrollUpButtonNum + 2) { battleMagicPanelButtonNum = 2; } } } magicOrItemPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(magicOrItemPanelContent.GetChild(0).gameObject); magicOrItemPanel.gameObject.SetActive(true); } |
currentModeを現在魔法を選択している状態CommandMode.SelectMagicにします。
commandPanelのCanvasGroupのinteractableをfalseにし、CommandPanelのUIは操作出来ないようにします。
ScrollManagerスクリプトのResetメソッドを呼び出してスクロール値を初期値に戻します。
これは一度スクロールをして次に一覧パネルを開いた時に前のスクロール値が残ってしまうので初期値に戻しています。
battleMagicPanelButtonNumはボタンの番号を保持し、決められたボタンにスクロールをする為のスクリプトを取り付ける為に使用します。
持っている全てのスキルの中で魔法系のスキルを取得し、battleMagicPanelButtonをインスタンス化し、magicOrItemPanelContentを親にします。
作成したボタンの子要素のMagicNameにスキル情報の名前を入れ、AmountToUseMagicPointsにその魔法を使用するのに必要なMPを入れます。
その後にボタンの番号に応じてそのボタンにScrollDownScriptとScrollUpScriptを取り付けます。
キャラクターのMPがその魔法で使うMPより少ない時はMagicNameのテキストの色を灰色に変更します(ボタンを押しても何も実行しない)。
キャラクターのMPがその魔法で使うMP以上ある場合はボタンが押された時にSelectUseMagicTargetメソッドを呼び出すようにします。
一つボタンを作成したらbattleMagicPanelButtonNumをインクリメントして1増やします。
魔法を使う相手を選択する処理SelectUseMagicTargetメソッド
使う魔法を選択したら次は魔法を使う相手を選択します。
それを行うSelectUseMagicTargetメソッドを作成します。
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 | // 魔法を使う相手の選択 public void SelectUseMagicTarget(GameObject user, Skill skill) { currentCommand = CommandMode.SelectUseMagicOnAlliesTarget; magicOrItemPanel.GetComponent<CanvasGroup>().interactable = false; selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); GameObject battleCharacterButtonIns; if (skill.GetSkillType() == Skill.Type.MagicAttack) { foreach (var enemy in enemyCharacterInBattleList) { battleCharacterButtonIns = Instantiate<GameObject>(battleCharacterButton, selectCharacterPanel); battleCharacterButtonIns.transform.Find("Text").GetComponent<Text>().text = enemy.gameObject.name; battleCharacterButtonIns.GetComponent<Button>().onClick.AddListener(() => UseMagic(user, enemy, skill)); } } else { foreach (var allyCharacter in allyCharacterInBattleList) { battleCharacterButtonIns = Instantiate<GameObject>(battleCharacterButton, selectCharacterPanel); battleCharacterButtonIns.transform.Find("Text").GetComponent<Text>().text = allyCharacter.gameObject.name; battleCharacterButtonIns.GetComponent<Button>().onClick.AddListener(() => UseMagic(user, allyCharacter, skill)); } } selectCharacterPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectCharacterPanel.GetChild(0).gameObject); selectCharacterPanel.gameObject.SetActive(true); } |
SelectUseMagicTargetは魔法使用者のゲームオブジェクトと使用した魔法のスキルを引数で受け取ります。
スキルタイプがMagicAttackの時は攻撃対象者は敵なのでenemyCharacterInBattleListに登録されている敵数分のボタンを作成します。
そのボタンが押されたらUseMagicメソッドを実行するようにします。
スキルタイプがそれ以外の場合は対象者が味方なのでallyCharacterInBattleListに登録されている味方数分のボタンを作成します。
そのボタンが押されたらUseMagicメソッドを実行するようにします。
どのスキルタイプでもボタンが押されたらUseMagicメソッドを実行しますが、対象者が敵か味方かで別れます。
魔法を使用する相手が決定した時の処理をするUseMagicメソッド
魔法を使用する相手が決定したら後は魔法使用者のCharacterBattleScriptのChooseAttackOptionsメソッドを呼び出すだけです。
その処理をする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 40 41 42 43 44 45 46 47 | // 魔法を使う public void UseMagic(GameObject user, GameObject targetCharacter, Skill skill) { CharacterBattleScript.BattleState battleState = CharacterBattleScript.BattleState.Idle; // 魔法を使う相手のCharacterBattleScriptを取得しておく var targetCharacterBattleScript = targetCharacter.GetComponent<CharacterBattleScript>(); // 使う魔法の種類の設定と対象に使う必要がない場合の処理 if (skill.GetSkillType() == Skill.Type.MagicAttack) { battleState = CharacterBattleScript.BattleState.MagicAttack; } else if (skill.GetSkillType() == Skill.Type.RecoveryMagic) { if (targetCharacterBattleScript.GetHp() == targetCharacterBattleScript.GetCharacterStatus().GetMaxHp()) { Debug.Log(targetCharacter.name + "は全快です。"); return; } battleState = CharacterBattleScript.BattleState.Healing; } else if (skill.GetSkillType() == Skill.Type.IncreaseAttackPowerMagic) { if (targetCharacterBattleScript.IsIncreasePower()) { Debug.Log("既に攻撃力を上げています。"); return; } battleState = CharacterBattleScript.BattleState.IncreaseAttackPowerMagic; } else if (skill.GetSkillType() == Skill.Type.IncreaseDefencePowerMagic) { if (targetCharacterBattleScript.IsIncreaseStrikingStrength()) { Debug.Log("既に防御力を上げています。"); return; } battleState = CharacterBattleScript.BattleState.IncreaseDefencePowerMagic; } else if (skill.GetSkillType() == Skill.Type.NumbnessRecoveryMagic) { if (!targetCharacterBattleScript.IsNumbness()) { Debug.Log(targetCharacter.name + "は痺れ状態ではありません。"); return; } battleState = CharacterBattleScript.BattleState.NumbnessRecoveryMagic; } else if (skill.GetSkillType() == Skill.Type.PoisonnouRecoveryMagic) { if (!targetCharacterBattleScript.IsPoison()) { Debug.Log(targetCharacter.name + "は毒状態ではありません。"); return; } battleState = CharacterBattleScript.BattleState.PoisonnouRecoveryMagic; } user.GetComponent<CharacterBattleScript>().ChooseAttackOptions(battleState, targetCharacter, skill); commandPanel.gameObject.SetActive(false); magicOrItemPanel.gameObject.SetActive(false); selectCharacterPanel.gameObject.SetActive(false); } |
魔法を使用する対象者のHPが最大値であれば回復魔法を使用する必要がないのでreturnをして対象者を選択するところまで処理を戻します。
他の魔法の場合も使用する魔法を使っても意味がない場合はreturnで対象者を選択する状態に戻します。
何も問題がなければbattleStateにその魔法状態を入れます。
そして魔法使用者のCharacterBattleScriptのChooseAttackOptionsメソッドを呼び出して対象者に魔法を使用します。
選択するアイテムボタンを作成するSelectItemメソッド
アイテムを選択した時にアイテム一覧にアイテムボタンを表示させます。
その為の処理を行うSelectItemメソッドを作成します。
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 | // 使用するアイテムの選択 public void SelectItem(GameObject character) { var itemDictionary = ((AllyStatus)character.GetComponent<CharacterBattleScript>().GetCharacterStatus()).GetItemDictionary(); // MagicOrItemPanelのスクロール値の初期化 scrollManager.Reset(); var battleItemPanelButtonNum = 0; GameObject battleItemPanelButtonIns; foreach (var item in itemDictionary.Keys) { if (item.GetItemType() == Item.Type.HPRecovery || item.GetItemType() == Item.Type.MPRecovery || item.GetItemType() == Item.Type.NumbnessRecovery || item.GetItemType() == Item.Type.PoisonRecovery ) { battleItemPanelButtonIns = Instantiate<GameObject>(battleItemPanelButton, magicOrItemPanelContent); battleItemPanelButtonIns.transform.Find("ItemName").GetComponent<Text>().text = item.GetKanjiName(); battleItemPanelButtonIns.transform.Find("Num").GetComponent<Text>().text = ((AllyStatus)character.GetComponent<CharacterBattleScript>().GetCharacterStatus()).GetItemNum(item).ToString(); battleItemPanelButtonIns.GetComponent<Button>().onClick.AddListener(() => SelectItemTarget(character, item)); // 指定した番号のアイテムパネルボタンにアイテムスクロール用スクリプトを取り付ける if (battleItemPanelButtonNum != 0 && (battleItemPanelButtonNum % scrollDownButtonNum == 0 || battleItemPanelButtonNum % (scrollDownButtonNum + 1) == 0) ) { // アイテムスクロールスクリプトの取り付けて設定値のセット battleItemPanelButtonIns.AddComponent<ScrollDownScript>(); } else if (battleItemPanelButtonNum != 0 && (battleItemPanelButtonNum % scrollUpButtonNum == 0 || battleItemPanelButtonNum % (scrollUpButtonNum + 1) == 0) ) { battleItemPanelButtonIns.AddComponent<ScrollUpScript>(); } // ボタン番号を足す battleItemPanelButtonNum++; if (battleItemPanelButtonNum == scrollUpButtonNum + 2) { battleItemPanelButtonNum = 2; } } } if (magicOrItemPanelContent.childCount > 0) { currentCommand = CommandMode.SelectItem; commandPanel.GetComponent<CanvasGroup>().interactable = false; selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); magicOrItemPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(magicOrItemPanelContent.GetChild(0).gameObject); magicOrItemPanel.gameObject.SetActive(true); } else { Debug.Log("使えるアイテムがありません。"); } } |
キャラクターが持つアイテムリストを取得しitemDictionaryに入れます。
battleItemPanelButtonNumはアイテム一覧に並べたボタンの番号を表します。
itemDictionary.KeysでitemDictionaryのキーだけを取得し、foreachで繰り返しをしてそのキーに対する値を取得し実行します。
アイテムのタイプが戦闘中に使用出来るタイプのものだけを抽出し、battleItemPanelButtonプレハブをインスタンス化し、magicOrItemPanelContentを親にします。
インスタンス化したボタンの子要素のItemNameにアイテムの名前、Numにそのアイテムを持っている数を入れます。
ボタンが押されたらSelectItemTargetメソッドを実行するようにします。
スクロールをするボタンにだけScrollDownScriptとScrollUpScriptスクリプトを取り付けます。
戦闘中に使えるアイテム数分のボタンを作成した後にmagicOrItemPanelの子要素に一つもボタンがない場合は使えるアイテムがないので、CommandPanelで使用するスキルを選択している状態のままにします。
使えるアイテムが一つでもあればCommandPanelのCanvasGroupのinteractableをfalseにし、MagicOrItemPanelのCanvasGroupのinteractableをtrueにし、MagicOrItemPanel子要素のContentをアクティブにします。
アイテムを使用する相手を選択するSelectItemTargetメソッドの作成
使用するアイテムが決まったら次はアイテムを使う相手を選択します。
その処理を行うSelectItemTargetメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // アイテムを使用する相手を選択 public void SelectItemTarget(GameObject user, Item item) { currentCommand = CommandMode.SelectRecoveryItemTarget; magicOrItemPanel.GetComponent<CanvasGroup>().interactable = false; selectedGameObjectStack.Push(EventSystem.current.currentSelectedGameObject); GameObject battleCharacterButtonIns; foreach (var allyCharacter in allyCharacterInBattleList) { battleCharacterButtonIns = Instantiate<GameObject>(battleCharacterButton, selectCharacterPanel); battleCharacterButtonIns.transform.Find("Text").GetComponent<Text>().text = allyCharacter.gameObject.name; battleCharacterButtonIns.GetComponent<Button>().onClick.AddListener(() => UseItem(user, allyCharacter, item)); } selectCharacterPanel.GetComponent<CanvasGroup>().interactable = true; EventSystem.current.SetSelectedGameObject(selectCharacterPanel.GetChild(0).gameObject); selectCharacterPanel.gameObject.SetActive(true); } |
SelectItemTargetメソッドはアイテム使用者のゲームオブジェクトと使用したアイテムを引数で受け取ります。
SelectItemTargetメソッドは味方キャラクターにアイテムを使用した場合に呼ばれる処理のみを記述しています(敵を攻撃するアイテムを作らなかった為)。
敵に使用するアイテムを作成した場合は別途AttackItem等のItemタイプを作成し処理を分けて作ってください。
戦闘に参加している味方キャラクターのリストallyCharacterInBattleList数分のbattleCharacterButtonをインスタンス化し、親をselectCharacterPanelにします。
ボタンの子要素のTextに味方キャラクターの名前を設定し、ボタンが押されたらUseItemメソッドを実行するようにします。
アイテムを使用する相手が決まった後の処理をするUseItemメソッド
アイテムを使用する相手が決まったら後はアイテム使用者のCharacterBattleScriptのChooseAttackOptionsメソッドを呼び出します。
その処理を行う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 31 32 33 34 35 36 37 38 39 40 | // アイテム使用 public void UseItem(GameObject user, GameObject targetCharacter, Item item) { var userCharacterBattleScript = user.GetComponent<CharacterBattleScript>(); var targetCharacterBattleScript = targetCharacter.GetComponent<CharacterBattleScript>(); var skill = userCharacterBattleScript.GetCharacterStatus().GetSkillList().Find(skills => skills.GetSkillType() == Skill.Type.Item); CharacterBattleScript.BattleState battleState = CharacterBattleScript.BattleState.Idle; if (item.GetItemType() == Item.Type.HPRecovery) { if (targetCharacterBattleScript.GetHp() == targetCharacterBattleScript.GetCharacterStatus().GetMaxHp()) { Debug.Log(targetCharacter.name + "は全快です。"); return; } battleState = CharacterBattleScript.BattleState.UseHPRecoveryItem; } else if (item.GetItemType() == Item.Type.MPRecovery) { if (targetCharacterBattleScript.GetMp() == targetCharacterBattleScript.GetCharacterStatus().GetMaxMp()) { Debug.Log(targetCharacter.name + "はMP回復をする必要がありません。"); return; } battleState = CharacterBattleScript.BattleState.UseMPRecoveryItem; } else if (item.GetItemType() == Item.Type.NumbnessRecovery) { if (!targetCharacterBattleScript.IsNumbness()) { Debug.Log(targetCharacter.name + "は痺れ状態ではありません。"); return; } battleState = CharacterBattleScript.BattleState.UseNumbnessRecoveryItem; } else if (item.GetItemType() == Item.Type.PoisonRecovery) { if (!targetCharacterBattleScript.IsPoison()) { Debug.Log(targetCharacter.name + "は毒状態ではありません。"); return; } battleState = CharacterBattleScript.BattleState.UsePoisonRecoveryItem; } userCharacterBattleScript.ChooseAttackOptions(battleState, targetCharacter, skill, item); commandPanel.gameObject.SetActive(false); magicOrItemPanel.gameObject.SetActive(false); selectCharacterPanel.gameObject.SetActive(false); } |
アイテムの種類に応じて対象者にアイテムを使用する必要がない場合はreturnで対象者の選択に戻ります。
それ以外はbattleStateに状態を設定し、アイテム使用者のCharacterBattleScriptのChooseAttackOptionsメソッドを呼び出します。
逃げるを選択した時の処理GetAwayメソッド
CommandPanelで逃げるを選択した時の処理をするGetAwayメソッドを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // 逃げる public void GetAway(GameObject character) { var randomValue = Random.value; if (0f <= randomValue && randomValue <= 0.2f) { Debug.Log("逃げるのに成功した。"); battleIsOver = true; commandPanel.gameObject.SetActive(false); // 戦闘終了 } else { Debug.Log("逃げるのに失敗した。"); commandPanel.gameObject.SetActive(false); ChangeNextChara(); } } |
今回はRandom.valueで0~1のfloatのランダムな値を取得し、値が0~0.2だったら逃げるのに成功したことにし、battleIsOverをtrueにして戦闘終了にします。
逃げたらワールドマップシーンに戻るような処理が必要ですが、これは他の味方キャラクターが全滅した時や敵キャラクターを全滅させた時の処理と一緒に次回以降に作成していくので特に処理は記述しません。
逃げるのに失敗した時は次のキャラクターにターンを回します。
MagicOrItemPanelのスクロール処理の調整
機能は出来ましたが、アイテムや魔法一覧をスクロールした時にうまくスクロールされるように確認します。
MagicOrItemPanelの子要素のContentにBattleMagicPanelButtonプレハブを配置し、Ctrl+Dキーで複製しボタンを12個(数は任意)にします。
スクロールしない状態で表示されているボタン数が以下のようになっているとします。
表示されているボタンが10個なので11個目12個目のボタンが選択された時にスクロールされるようにBattleManagerのscrollDownButtonNumを8、scrollUpButtonNumを10(ボタン番号は0から始まる為)にします。
scrollValueの値はヒエラルキー上のContentをマニピュレータを操作し、11個目のボタンが上に表示された時のContentのRectTransformのPosYの値を設定します。
手動でスクロールして11個目、12個目のボタンが上に表示された時のPosYの値をBattleManagerのscrollValueに設定します。
値を設定したらContent以下に複製した全てのボタンはいらないので削除しておきます。
BattleManagerの設定は以下のようにしました。
CommandPanel、SelectCharacterPanel、MagicOrItemPanelは最初は表示しないので、インスペクタの名前の横のチェックを外しておきます(子要素のゲームオブジェクトはアクティブなまま)。
ボタンの選択速度を速める
以前の記事でEventSystemの設定を変えてボタンの選択速度を速めました。
BattleシーンのEventSystemも同じ設定を施します。
もしかしたら以前の記事で既に設定済みの可能性もありますが、覚えていないので書いておきました・・・・(^_^;)
BattleUIの子要素のCommandPanel、SelectCharacterPanel、MagicOrItemPanelの各インスペクタで名前の横のチェックを外し、最初は表示されないようにしておきます。
これで機能が出来ました。
実行して確認してみましょう。
上のようになりました。
終わりに
いやぁ・・・今回は非常記事が長くなりましたね。
もうやりたくないです。(´Д`)
痺れや毒状態の時の演出や効果についてはこの記事では作っていません。
痺れ状態の時は行動を出来なくしたり、毒状態の時はターンが回ってきたらHPを減らすといった処理を作ってみてください。
今回の機能が出来上がればこの後に作成していく機能はそんなに大変になることもないと思います。(-_-)
いや・・・どうでしょうね?( 一一)
この作品はユニティちゃんライセンス条項の元に提供されています