【Unity】RPG制作 その29-特技の実装1 基本部分を作成
今回から特技の実装をやっていきたいと思います。基本的にアイテムの実装と似ているところが多いので、アイテム実装の時に使った処理を流用していきます。
まずは特技の個々のデータを扱うSpecialDataクラスを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpecialData : MonoBehaviour { public enum PHYSICELEM //物理的な属性 { NONE,//なし SLASHING,//斬撃 PIERCING,//刺突 BLOW, //打撃 SHOOTING, //射撃 } public enum QUESTBUFF//探索時の一時特殊効果。デバフも { NONE, AVOIDENEMIES, //敵避け(敵と遭遇しにくくなる) CLEARNESS, //透明(敵と遭遇しない) } public enum SPECIALTYPE //特技の種類 { HEAL,//回復 ATTACK,//攻撃 ASSIST,//補助 SEARCH,//探索用 } public enum AVAILABLESCENES //使用可能な場面の列挙型 { QUESTONLY,//探索時のみ BATTLEONLY,//戦闘時のみ QUESTANDBATTLE,//探索と戦闘両方 } public enum TARGET { OneOfAllies, //味方一人 AllOfAllies, //味方全員 OneOfEnemy, //敵一人 AllOfEnemy, //敵全員 AllOfBattlers,//敵味方全員 UserHimself, //使用者自身 OneOfEnemyAtRandom,//敵ランダムに1体 } public enum WEAPONTYPE { Dagger, //短剣 Sword, //剣 Spear, //槍 Club, //棍棒 Axe, //斧 Bow, //弓 Wand, //杖 Nail, //爪 Gun, //銃 } [Header("特技識別変数")] public SpecialManager.SPECIAL specialID = SpecialManager.SPECIAL.クロスダガー; [Header("特技のアイコン")] public Sprite specialSprite = null; [Header("特技の名前")] public string specialName; [Header("特技の説明")] public string explanation = ""; [Header("特技の種類")] public SPECIALTYPE specialType; [Header("TP消費値")] public int useTpValue = 0; [Header("使用可能な場面")] public AVAILABLESCENES canUseScene = AVAILABLESCENES.BATTLEONLY; [Header("武器種専用特技?")] public bool IsExclusive = false; [Header("指定する武器")] public WEAPONTYPE weaponType= WEAPONTYPE.Dagger; [Header("物理的な属性")] public PHYSICELEM physicElem = PHYSICELEM.SLASHING; [Header("属性")] public GeneralEnum.ELEMENT element = GeneralEnum.ELEMENT.NONE; [Header("命中補正(%)")] public int HitCorrection = 0; [Header("必中か?")] public bool hittingTheTarget = false; [Header("HP回復量(固定量)")] public int healHPPoint = 0; [Header("MP回復量(固定量)")] public int healMPPoint = 0; [Header("TP回復量(固定量)")] public int healTPPoint = 0; [Header("HP回復率(最大の何%か)")] public int HPHealRateValue = 0; [Header("MP回復率(最大の何%か)")] public int MPHealRateValue = 0; [Header("TP回復率(最大の何%か)")] public int TPHealRateValue = 0; [Header("HPダメージ量(固定量)")] public int HPDamageValue = 0; [Header("MPダメージ量(固定量)")] public int MPDamageValue = 0; [Header("TPダメージ量(固定量)")] public int TPDamageValue = 0; [Header("攻撃力影響度(%)")] public int attackInfluence = 100; [Header("感覚影響度(%)")] public int senceInfluence = 0; [Header("速さ影響度")] public int agiInfluence = 0; [Header("魔力影響度(%)")] public int magicInfluence = 100; [Header("防御影響度(%)")] public int defInfluence = 0; [Header("魔防影響度(%)")] public int magdefInfluence = 0; [Header("運影響度(%)")] public int lukInfluence = 0; [Header("習得影響度(%)")] public int learnInfluence = 0; [Header("MPダメ攻撃力影響度(%)")] public int attackInfluenceOnMP = 100; [Header("MPダメ魔力影響度(%)")] public int magicInfluenceOnMP = 100; [Header("TPダメ攻撃力影響度(%)")] public int attackInfluenceOnTP = 100; [Header("TPダメ魔力影響度(%)")] public int magicInfluenceOnTP = 100; [Header("貫通率(%)")] public int penetrationRate = 0; [Header("ダメージ分散率(%)")] public int damageDispersionRate = 20; [Header("使用時文章(探索)")] public string useMessage_Quest = ""; [Header("使用時文章(戦闘)")] public string useMessage_Battle = ""; [Header("失敗時文章")] public string failedMessage = ""; [Header("発動回数")] public int activateCount = 1; [Header("エフェクト")] public GameObject effect = null; [Header("特殊技能制限対象か?")] public bool isInfluenceLimit = true; [Header("付与する状態異常1")] public GeneralEnum.STATUSCONDITION addCondition1 = GeneralEnum.STATUSCONDITION.NONE; [Header("付与するターン1")] public int addCondiTurn1 = 0; [Header("付与確率1")] public int addProbability1 = 0; [Header("付与する状態異常2")] public GeneralEnum.STATUSCONDITION addCondition2 = GeneralEnum.STATUSCONDITION.NONE; [Header("付与するターン2")] public int addCondiTurn2 = 0; [Header("付与確率2")] public int addProbability2 = 0; [Header("付与する状態異常3")] public GeneralEnum.STATUSCONDITION addCondition3 = GeneralEnum.STATUSCONDITION.NONE; [Header("付与するターン3")] public int addCondiTurn3 = 0; [Header("付与確率3")] public int addProbability3 = 0; [Header("回復する状態異常1")] public GeneralEnum.STATUSCONDITION careCondition1 = GeneralEnum.STATUSCONDITION.NONE; [Header("回復する状態異常2")] public GeneralEnum.STATUSCONDITION careCondition2 = GeneralEnum.STATUSCONDITION.NONE; [Header("回復する状態異常3")] public GeneralEnum.STATUSCONDITION careCondition3 = GeneralEnum.STATUSCONDITION.NONE; [Header("回復する状態異常4")] public GeneralEnum.STATUSCONDITION careCondition4 = GeneralEnum.STATUSCONDITION.NONE; [Header("変化させるステータス1")] public GeneralEnum.STATUS changeStatus1 = GeneralEnum.STATUS.NONE; [Header("変化させるターン1")] public int changeStatusTurn1 = 0; [Header("変化させる割合1(+)")] public int changeStatusRatePlus1 = 0; [Header("成功確率1")] public int successRateOfChangeStatus1 = 0; [Header("変化させるステータス2")] public GeneralEnum.STATUS changeStatus2 = GeneralEnum.STATUS.NONE; [Header("変化させるターン2")] public int changeStatusTurn2 = 0; [Header("変化させる割合1(+)")] public int changeStatusRatePlus2 = 0; [Header("成功確率2")] public int successRateOfChangeStatus2 = 0; [Header("変化させるステータス3")] public GeneralEnum.STATUS changeStatus3 = GeneralEnum.STATUS.NONE; [Header("変化させるターン3")] public int changeStatusTurn3 = 0; [Header("変化させる割合1(+)")] public int changeStatusRatePlus3 = 0; [Header("成功確率3")] public int successRateOfChangeStatus3 = 0; [Header("探索時一時特殊効果1")] public QUESTBUFF tempQuestBuff1 = QUESTBUFF.NONE; [Header("|_ターン数")] public int buffTurnTurn1 = 0; [Header("探索時一時特殊効果2")] public QUESTBUFF tempQuestBuff2 = QUESTBUFF.NONE; [Header("|_ターン数")] public int buffTurnTurn2 = 0; [Header("探索時一時特殊効果3")] public QUESTBUFF tempQuestBuff3 = QUESTBUFF.NONE; [Header("|_ターン数")] public int buffTurnTurn3 = 0; [Header("回避率無視?")] public bool isIgnoreEvasion = true; [Header("相手の魔法防御反映率")] public int thingE_MDEFRate = 100; [Header("自分にダメージを跳ね返す率(-で吸収)")] public int reflectRate = 0; [Header("使用時のSE(-1で再生しない)")] public int UseSEID = 36; //デフォルトはアイテム使用音3 }
SpecialDataを管理するクラスSpecialManagerクラスを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using System; using UnityEngine; public class SpecialManager : MonoBehaviour { //シングルトン(全てのシーンで共有) public static SpecialManager instance; private void Awake() { if (instance == null) { instance = this; DontDestroyOnLoad(this.gameObject); } else { Destroy(this.gameObject); } } //--シングルトン終わり-- public SpecialData[] specialDatas; // 特技の種類を設定 public enum SPECIAL { Heal, //HPを30回復 High_Heal, //HPを80回復 クロスダガー,//at*1.4 短剣専用 ダブルスラッシュ, //at* 0.7 2回攻撃 剣専用 岩砕き, //at * 1.2 25%の確率で防御下げ 大地属性 棍棒専用 ファイアクロー, //at * 1.3 20%の確率で火傷 炎属性 爪専用 ドラゴンクロー, //at * 1.5 龍属性 爪専用 雷光弾, //at*0.5 + sense * 0.8 雷属性 銃専用 重氷断, //at*1.4 氷属性 斧専用 疾風矢, //at * 0.8 + agi * 0.5 風属性 弓専用 }; // Start is called before the first frame update void Start() { TestInit(); } //デバッグ用。プレイヤーの所持スキルをセット public void TestInit() { PlayerManager.instance.canUseSpecials[SPECIAL.Heal]=0; PlayerManager.instance.canUseSpecials[SPECIAL.High_Heal]=0; PlayerManager.instance.canUseSpecials[SPECIAL.クロスダガー]=0; PlayerManager.instance.canUseSpecials[SPECIAL.ダブルスラッシュ]=0; PlayerManager.instance.canUseSpecials[SPECIAL.岩砕き] = 0; PlayerManager.instance.canUseSpecials[SPECIAL.ファイアクロー] = 0; PlayerManager.instance.canUseSpecials[SPECIAL.ドラゴンクロー] = 0; PlayerManager.instance.canUseSpecials[SPECIAL.雷光弾] = 0; PlayerManager.instance.canUseSpecials[SPECIAL.重氷断] = 0; PlayerManager.instance.canUseSpecials[SPECIAL.疾風矢] = 0; } }
PlayerManager.csにプレイヤーが使用可能な特技を設定するDictionaryとその初期化関数を設定します。
クリックで展開
[NonSerialized] public Dictionary<SpecialManager.SPECIAL, int> canUseSpecials = new Dictionary<SpecialManager.SPECIAL, int>();//New public void InitSpecialDictionary() //New { foreach (SpecialManager.SPECIAL value in Enum.GetValues(typeof(SpecialManager.SPECIAL))) { canUseSpecials[value] = -1;//全て-1(使えない状態にしておく) } }
特技の処理を扱うSpecialEventクラスを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using System; using UnityEngine; using UnityEngine.UI; using UnityEngine.Events; //特技UIでButtonコンポーネント付きのオブジェクトにアタッチするスクリプト //各特技の処理を行う public class SpecialEvent : MonoBehaviour { SpecialManager specialManager; public SpecialData specialData; public GameObject specialCanvas; public SpecialUsePanel specialUsePanel; public SpecialUI specialUI; public GameObject specialUIView; public GameObject useSpecialMessagePanel; public Text useSpecialText; TermManager termManagerF; public PlayerUIManager playerUIManager; public GameObject cancelButton; public CommandUIManager commandUI; public BattleManager battleManager; public PlayerManager player; public EnemyManager enemy_grobal; public SpecialEvent attackSpecialEvent;//Attack特技を使用する際に作成するspecialEventクラスの入れ物 //関数登録 public UnityAction DecideUseSpecial;//特技使用時に実行する関数を登録する(登録のタイミングはSpecialUsePanel生成時) public IEnumerator IEUseSpecialRegister; //BattleManagerで特技使用時に実行させるコルーチンを入れる bool hasEffectivedItem = false; private void Awake() { specialManager = GameObject.Find("SpecialManager").GetComponent<SpecialManager>();//階層上のSpecialManagerを取得 specialUI = GameObject.Find("SpecialUISystem").GetComponent<SpecialUI>(); specialUIView = GameObject.Find("SpecialUI_Scroll View"); battleManager = GameObject.Find("BattleManager").GetComponent<BattleManager>(); player = PlayerManager.instance; termManagerF = new TermManager(); } public void SetObjects() { specialManager = GameObject.Find("SpecialManager").GetComponent<SpecialManager>();//階層上のSpecialManagerを取得 specialUI = GameObject.Find("SpecialUISystem").GetComponent<SpecialUI>(); specialUIView = GameObject.Find("SpecialUI_Scroll View"); battleManager = GameObject.Find("BattleManager").GetComponent<BattleManager>(); player = PlayerManager.instance; termManagerF = new TermManager(); } public void SetSpecialTargetPanel() { if (specialUI.GetComponent<SpecialUI>().canTapSpecialUI) { specialUI.GetComponent<SpecialUI>().canTapSpecialUI = false; useSpecialText = useSpecialMessagePanel.transform.GetChild(0).GetComponent<Text>(); if(specialData.useTpValue > player.tp) { SoundManager.instance.PlaySE(11); //ブザー音 specialUI.GetComponent<SpecialUI>().canTapSpecialUI = true; return; } if(GameManager.instance.gamePhase == GameManager.GAMEPHASE.QUEST) //ゲームフェーズがクエストの場合 { if(specialData.canUseScene == SpecialData.AVAILABLESCENES.BATTLEONLY)//戦闘時のみ使用可の場合は使えない { SoundManager.instance.PlaySE(11); //ブザー音 specialUI.GetComponent<SpecialUI>().canTapSpecialUI = true; return; } if (specialData.specialType == SpecialData.SPECIALTYPE.HEAL) //回復アイテムの場合の処理 { specialUsePanel.gameObject.SetActive(true); specialUsePanel.SetHealSpecialUsePanel(useSpecialMessagePanel, specialData, specialUsePanel); } else if(specialData.specialType == SpecialData.SPECIALTYPE.SEARCH)//探索アイテムの場合の処理 { specialUsePanel.gameObject.SetActive(true); } }else if(GameManager.instance.gamePhase == GameManager.GAMEPHASE.BATTLE)//BATTLEフェーズの場合 { if(specialData.canUseScene == SpecialData.AVAILABLESCENES.QUESTONLY) { SoundManager.instance.PlaySE(11);//ブザー音 specialUI.GetComponent<SpecialUI>().canTapSpecialUI = true; return; } if(specialData.specialType == SpecialData.SPECIALTYPE.HEAL)//回復アイテムの場合の処理 { specialUsePanel.gameObject.SetActive(true); specialUsePanel.SetHealSpecialUsePanel(useSpecialMessagePanel, specialData, specialUsePanel); } else if(specialData.specialType == SpecialData.SPECIALTYPE.ATTACK) { specialUIView.SetActive(false); useSpecialMessagePanel.SetActive(true); useSpecialText.text = "使用対象を選択してください"; //attackSpecialに、特技使用処理を実行するに当たって必要な情報を設定しておく(HealSpecialはuseSpecialPanelを介してSpecialEventを作成するが、AttackSpecialはこの場で新規のSpecialEvent(ゲームオブジェクト)を作成する) attackSpecialEvent = (new GameObject("AttackSpecialEvent")).AddComponent<SpecialEvent>(); attackSpecialEvent.SetObjects(); specialUsePanel.SetTargetSelectOnAttackSpecial(useSpecialMessagePanel, specialData, specialUsePanel, attackSpecialEvent); //attackSpecialEventの処理をEnemyのTap処理に登録 foreach(EnemyManager enemy in battleManager.enemysList.Values) { enemy.InitEventListenerOnTap(); enemy.AddEventListenerOnTap(attackSpecialEvent.DecidePlayerUseSpecialOnBattle); } attackSpecialEvent.battleManager = battleManager; //attackSpecialEventの登録関数をここで行っておく attackSpecialEvent.IEUseSpecialRegister = attackSpecialEvent.IEUseAttackSpecial();//battleManagerで実行されるアイテム使用処理の関数登録 attackSpecialEvent.DecideUseSpecial += battleManager.StartBattleTurn; } } } } public void UseHealSpecial(PlayerManager player) { if (specialUsePanel.canTapSpecialUsePanel) { specialUsePanel.canTapSpecialUsePanel = false; StartCoroutine(IEUseHealSpecial(player)); } } //回復特技を使用した時の処理(状態異常治療、能力強化なども含む) public IEnumerator IEUseHealSpecial(PlayerManager player) { useSpecialMessagePanel.SetActive(true); useSpecialText = useSpecialMessagePanel.transform.GetChild(0).GetComponent<Text>(); useSpecialText.text = player.pname + specialData.useMessage_Battle; yield return new WaitForSeconds(0.5f); if(specialData.UseSEID != -1) { SoundManager.instance.PlaySE(specialData.UseSEID); } yield return new WaitForSeconds(0.7f); useSpecialText.text = ""; yield return new WaitForSeconds(0.5f); //回復特技の回復量を計算する(最大HP * 回復割合 * 固定回復量) int hpPoint = (int)(player.maxHp * specialData.HPHealRateValue / 100f + specialData.healHPPoint); int mpPoint = (int)(player.maxMp * specialData.MPHealRateValue / 100f + specialData.healMPPoint); int tpPoint = (int)(player.maxTp * specialData.TPHealRateValue / 100f + specialData.healTPPoint); bool wasSpecialEffective = false;//アイテムが何かしらの効果を与えたか?(メッセージに影響する) player.hp += hpPoint; player.mp += mpPoint; player.tp += tpPoint; if(player.hp > player.maxHp) { hpPoint -= player.hp - player.maxHp; //回復量をテキストに出力するために計算 player.hp = player.maxHp; } if (hpPoint > 0) { useSpecialText.text = player.pname + "のHPが" + hpPoint + "回復した!"; SoundManager.instance.PlaySE(12);//回復SE yield return StartCoroutine(MessageWait1()); wasSpecialEffective = true; } if (player.mp > player.maxMp) { mpPoint -= player.mp - player.maxMp; player.mp = player.maxMp; } if (mpPoint > 0) { useSpecialText.text = player.pname + "のMPが" + mpPoint + "回復した!"; SoundManager.instance.PlaySE(12); yield return StartCoroutine(MessageWait1()); wasSpecialEffective = true; } if (player.tp > player.maxTp) { tpPoint -= player.tp - player.maxTp; player.tp = player.maxTp; } if (tpPoint > 0) { useSpecialText.text = player.pname + "のTPが" + tpPoint + "回復した!"; SoundManager.instance.PlaySE(12); yield return StartCoroutine(MessageWait1()); wasSpecialEffective = true; } TermManager termManager = new TermManager(); // もし特技の治療対象の状態異常にかかっていれば(1以上でかかっている) 探索時は特定の状態でしか機能しないようにする予定 if(player.statusCondiWithLastTurn[specialData.careCondition1] > 0) { player.statusCondiWithLastTurn[specialData.careCondition1] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition1, false); useSpecialText.text = player.pname + statusMessage; yield return StartCoroutine(MessageWait1()); wasSpecialEffective = true; } if (player.statusCondiWithLastTurn[specialData.careCondition2] > 0) { player.statusCondiWithLastTurn[specialData.careCondition2] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition2, false); useSpecialText.text = player.pname + statusMessage; yield return StartCoroutine(MessageWait1()); wasSpecialEffective = true; } if (player.statusCondiWithLastTurn[specialData.careCondition3] > 0) { player.statusCondiWithLastTurn[specialData.careCondition3] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition3, false); useSpecialText.text = player.pname + statusMessage; yield return StartCoroutine(MessageWait1()); wasSpecialEffective = true; } if (player.statusCondiWithLastTurn[specialData.careCondition4] > 0) { player.statusCondiWithLastTurn[specialData.careCondition4] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition4, false); useSpecialText.text = player.pname + statusMessage; yield return StartCoroutine(MessageWait1()); wasSpecialEffective = true; } //探索用の特殊効果実装部分(未実装) if(specialData.tempQuestBuff1 == SpecialData.QUESTBUFF.AVOIDENEMIES) { } if (specialData.tempQuestBuff1 == SpecialData.QUESTBUFF.AVOIDENEMIES) { } if (specialData.tempQuestBuff1 == SpecialData.QUESTBUFF.AVOIDENEMIES) { } //TPをへらす player.tp -= specialData.useTpValue; if (!wasSpecialEffective) { useSpecialText.text = "しかし何もおこらなかった"; yield return new WaitForSeconds(1.2f); } playerUIManager.UpdateUI(PlayerManager.instance); CloseSpecialMessageAndPanel(); AfterUseSpecial(); } //プレイヤーがバトル中に使う特技を決定した時の処理(自身の特技イベントを登録、プレイヤーの行動タイプをMOVEに 他) public void DecidePlayerUseSpecialOnBattle() { commandUI.HideCancelButton(); specialUsePanel.gameObject.SetActive(false); useSpecialMessagePanel.SetActive(false); if(specialUIView != null) { specialUIView.SetActive(false); } battleManager.playerSpecialEvent = this; battleManager.SetPlayerBattleActionType(BattleManager.BATTLEACTIONTYPE.MOVE); DecideUseSpecial(); } //戦闘中に回復アイテムを使う処理 public IEnumerator IEUseHealSpecialOnBattle() { DialogTextManager.instance.SetScenarios(new string[] { player.pname + "は" + specialData.specialName + "を使った!" }); if (specialData.UseSEID != -1) { SoundManager.instance.PlaySE(specialData.UseSEID); } yield return new WaitForSeconds(1.0f); //回復アイテムの回復量を計算する(最大HP * 回復割合 + 固定回復量) int hpPoint = (int)(player.battleStatusValues[GeneralEnum.STATUS.HP] * specialData.HPHealRateValue / 100f + specialData.healHPPoint); int mpPoint = (int)(player.battleStatusValues[GeneralEnum.STATUS.MP] * specialData.MPHealRateValue / 100f + specialData.healMPPoint); int tpPoint = (int)(player.battleStatusValues[GeneralEnum.STATUS.TP] * specialData.TPHealRateValue / 100f + specialData.healTPPoint); player.hp += hpPoint; player.mp += mpPoint; player.tp += tpPoint; bool wasSpecialEffective = false; if(player.hp > player.maxHp) { hpPoint -= player.hp - player.maxHp; //回復量をテキストに出力するために計算 player.hp = player.maxHp; } if(hpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { player.pname + "のHPが" + hpPoint + "回復した!" }); SoundManager.instance.PlaySE(12); yield return new WaitForSeconds(1.2f); wasSpecialEffective = true; } if (player.mp > player.maxMp) { mpPoint -= player.mp - player.maxMp; player.mp = player.maxMp; } if (mpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { player.pname + "のHPが" + mpPoint + "回復した!" }); SoundManager.instance.PlaySE(12); yield return new WaitForSeconds(1.2f); wasSpecialEffective = true; } if (player.tp > player.maxTp) { tpPoint -= player.tp - player.maxTp; player.tp = player.maxTp; } if (tpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { player.pname + "のTPが" + tpPoint + "回復した!" }); SoundManager.instance.PlaySE(12); yield return new WaitForSeconds(1.2f); wasSpecialEffective = true; } TermManager termManager = new TermManager(); // もし特技の治療対象の状態異常にかかっていれば(1以上でかかっている) if (player.statusCondiWithLastTurn[specialData.careCondition1] > 0) { player.statusCondiWithLastTurn[specialData.careCondition1] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition1, false); DialogTextManager.instance.SetScenarios(new string[] { player.pname + statusMessage }); yield return new WaitForSeconds(1.2f); wasSpecialEffective = true; } if(player.statusCondiWithLastTurn[specialData.careCondition2] > 0) { player.statusCondiWithLastTurn[specialData.careCondition2] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition2, false); DialogTextManager.instance.SetScenarios(new string[] { player.pname + statusMessage }); yield return new WaitForSeconds(1.2f); wasSpecialEffective = true; } if(player.statusCondiWithLastTurn[specialData.careCondition3] > 0) { player.statusCondiWithLastTurn[specialData.careCondition3] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition3, false); DialogTextManager.instance.SetScenarios(new string[] { player.pname + statusMessage }); yield return new WaitForSeconds(1.2f); wasSpecialEffective = true; } if (player.statusCondiWithLastTurn[specialData.careCondition4] > 0) { player.statusCondiWithLastTurn[specialData.careCondition4] = 0; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.careCondition4, false); DialogTextManager.instance.SetScenarios(new string[] { player.pname + statusMessage }); yield return new WaitForSeconds(1.2f); wasSpecialEffective = true; } if (specialData.changeStatus1 != GeneralEnum.STATUS.NONE) { if (specialData.changeStatusRatePlus1 >= 0)//0以上の場合は強化 { yield return StartCoroutine(StatusEnforce(player, specialData.changeStatus1, specialData.changeStatusTurn1, specialData.changeStatusRatePlus1)); wasSpecialEffective = true; } else { yield return StartCoroutine(StatusWeakened(player, specialData.changeStatus1, specialData.changeStatusTurn1, specialData.changeStatusRatePlus1)); wasSpecialEffective = true; } } if (specialData.changeStatus2 != GeneralEnum.STATUS.NONE) { if (specialData.changeStatusRatePlus2 >= 0)//0以上の場合は強化 { yield return StartCoroutine(StatusEnforce(player, specialData.changeStatus2, specialData.changeStatusTurn2, specialData.changeStatusRatePlus2)); wasSpecialEffective = true; } else { yield return StartCoroutine(StatusWeakened(player, specialData.changeStatus2, specialData.changeStatusTurn2, specialData.changeStatusRatePlus2)); wasSpecialEffective = true; } } if (specialData.changeStatus3 != GeneralEnum.STATUS.NONE) { if (specialData.changeStatusRatePlus3 >= 0)//0以上の場合は強化 { yield return StartCoroutine(StatusEnforce(player, specialData.changeStatus3, specialData.changeStatusTurn3, specialData.changeStatusRatePlus3)); wasSpecialEffective = true; } else { yield return StartCoroutine(StatusWeakened(player, specialData.changeStatus3, specialData.changeStatusTurn3, specialData.changeStatusRatePlus3)); wasSpecialEffective = true; } } if (!wasSpecialEffective) { DialogTextManager.instance.SetScenarios(new string[] { "しかし何もおこらなかった" }); yield return new WaitForSeconds(1.2f); } //TPを消費させる player.tp -= specialData.useTpValue; useSpecialMessagePanel.SetActive(false); playerUIManager.UpdateUI(PlayerManager.instance); specialUI.canTapSpecialUI = true; specialUsePanel.canTapSpecialUsePanel = true; specialUsePanel.gameObject.SetActive(false); specialUIView.SetActive(false); } //戦闘中に攻撃特技を使う処理 IEnumerator IEUseAttackSpecial() { DialogTextManager.instance.SetScenarios(new string[] { player.pname + specialData.useMessage_Battle }); yield return new WaitForSeconds(1.0f); if (specialData.UseSEID != -1) { SoundManager.instance.PlaySE(specialData.UseSEID); } //攻撃特技のダメージ量を計算する((player 攻撃力 * 攻撃影響率 / 100)+(player 魔力 * 魔力影響率 / 100) + 固定ダメージ量) if (CheckHitAttackSpecial(enemy_grobal)) { //HPダメージ量を計算する int pAtk = player.battleStatusValues[GeneralEnum.STATUS.ATK]; int pAgi = player.battleStatusValues[GeneralEnum.STATUS.AGI]; int pMag = player.battleStatusValues[GeneralEnum.STATUS.MAGPOW]; int pDef = player.battleStatusValues[GeneralEnum.STATUS.DEF]; int pMdef = player.battleStatusValues[GeneralEnum.STATUS.MAGDEF]; int pLuk = player.battleStatusValues[GeneralEnum.STATUS.LUK]; int pLearn = player.battleStatusValues[GeneralEnum.STATUS.LEARNABI]; int sIAtk = specialData.attackInfluence; int sIAgi = specialData.agiInfluence; int sIMag = specialData.magicInfluence; int sIDef = specialData.defInfluence; int sIMDef = specialData.magdefInfluence; int sLuk = specialData.lukInfluence; int sLearn = specialData.learnInfluence; int hpPoint = (int)((pAtk * sIAtk / 100) + (pAgi * sIAgi / 100) + (pMag * sIMag / 100) + (pDef * sIDef / 100) + (pMdef * sIMDef / 100) + (pLuk * sLuk / 100) + (pLearn * sLearn / 100) + specialData.HPDamageValue); //MPダメージ量を計算する int sIAtkOnMP = specialData.attackInfluenceOnMP; int sIMagOnMP = specialData.attackInfluenceOnMP; int mpPoint = (int)((pAtk * sIAtkOnMP / 100) + (pMag * sIMagOnMP / 100) + specialData.MPDamageValue); //TPダメージ量を計算する int sIAtkOnTP = specialData.attackInfluenceOnTP; int sIMagOnTP = specialData.attackInfluenceOnTP; int tpPoint = (int)((pAtk * sIAtkOnTP / 100) + (pMag * sIMagOnTP / 100) + specialData.TPDamageValue); enemy_grobal.hp -= hpPoint; enemy_grobal.mp -= mpPoint; enemy_grobal.tp -= tpPoint; bool wasEffecitveSpecial = false; if (enemy_grobal.hp < 0) hpPoint = 0; if (enemy_grobal.mp < 0) mpPoint = 0; if (enemy_grobal.tp < 0) tpPoint = 0; if(hpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { enemy_grobal.name + "に" + hpPoint + "のダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (mpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { enemy_grobal.name + "に" + mpPoint + "のMPダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (tpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { enemy_grobal.name + "に" + tpPoint + "のTPダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (hpPoint == 0 && mpPoint == 0 && tpPoint == 0) { DialogTextManager.instance.SetScenarios(new string[] { enemy_grobal.name + "にダメージを与えられなかった!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); } yield return StartCoroutine(AddConditions()); yield return StartCoroutine(AddStatuEnforceORWeakended()); if (!wasEffecitveSpecial) { DialogTextManager.instance.SetScenarios(new string[] { "しかし何もおこらなかった" }); yield return new WaitForSeconds(1.2f); } } else//攻撃が命中しなかった場合 { DialogTextManager.instance.SetScenarios(new string[] { player.pname + "の攻撃は外れた" }); yield return new WaitForSeconds(1.2f); } //TPを消費する player.tp -= specialData.useTpValue; useSpecialMessagePanel.SetActive(false); playerUIManager.UpdateUI(PlayerManager.instance); enemy_grobal.gameObject.GetComponent<EnemyUIManager>().UpdateUI(enemy_grobal); specialUI.canTapSpecialUI = true; specialUsePanel.canTapSpecialUsePanel = true; specialUsePanel.gameObject.SetActive(false); } /// <summary> /// 使用した特技のデータを元にターゲットに状態異常を付与する関数です。 /// </summary> /// <returns></returns> IEnumerator AddConditions() { TermManager termManager = new TermManager(); // 状態異常付与の処理 if (specialData.addCondition1 != GeneralEnum.STATUSCONDITION.NONE) { if (specialData.addProbability1 >= UnityEngine.Random.Range(1, 101)) { enemy_grobal.statusCondiWithLastTurn[specialData.addCondition1] = specialData.addCondiTurn1; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.addCondition1, true); DialogTextManager.instance.SetScenarios(new string[] { enemy_grobal.name + statusMessage }); yield return new WaitForSeconds(1.2f); hasEffectivedItem = true; } } if (specialData.addCondition2 != GeneralEnum.STATUSCONDITION.NONE) { if (specialData.addProbability2 >= UnityEngine.Random.Range(1, 101)) { enemy_grobal.statusCondiWithLastTurn[specialData.addCondition2] = specialData.addCondiTurn2; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.addCondition2, true); DialogTextManager.instance.SetScenarios(new string[] { enemy_grobal.name + statusMessage }); yield return new WaitForSeconds(1.2f); hasEffectivedItem = true; } } if (specialData.addCondition3 != GeneralEnum.STATUSCONDITION.NONE) { if (specialData.addProbability3 >= UnityEngine.Random.Range(1, 101)) { enemy_grobal.statusCondiWithLastTurn[specialData.addCondition3] = specialData.addCondiTurn3; string statusMessage = termManager.Get_STATUSCONDI_Message(specialData.addCondition3, true); DialogTextManager.instance.SetScenarios(new string[] { enemy_grobal.name + statusMessage }); yield return new WaitForSeconds(1.2f); hasEffectivedItem = true; } } yield return null; } /// <summary> /// 使用した特技のデータを元に、ターゲットにステータスの強化・弱体を付与する関数です。 /// </summary> /// <returns></returns> IEnumerator AddStatuEnforceORWeakended() { if (specialData.changeStatus1 != GeneralEnum.STATUS.NONE) { if (specialData.changeStatusRatePlus1 >= 0) { yield return StartCoroutine(EnemyStatusEnforce(enemy_grobal, specialData.changeStatus1, specialData.changeStatusTurn1, specialData.changeStatusRatePlus1)); hasEffectivedItem = true; } else { yield return StartCoroutine(EnemyStatusWeakened(enemy_grobal, specialData.changeStatus1, specialData.changeStatusTurn1, specialData.changeStatusRatePlus1)); hasEffectivedItem = true; } } if (specialData.changeStatus2 != GeneralEnum.STATUS.NONE) { if (specialData.changeStatusRatePlus2 >= 0) { yield return StartCoroutine(EnemyStatusEnforce(enemy_grobal, specialData.changeStatus2, specialData.changeStatusTurn2, specialData.changeStatusRatePlus2)); hasEffectivedItem = true; } else { yield return StartCoroutine(EnemyStatusWeakened(enemy_grobal, specialData.changeStatus2, specialData.changeStatusTurn2, specialData.changeStatusRatePlus2)); hasEffectivedItem = true; } } if (specialData.changeStatus3 != GeneralEnum.STATUS.NONE) { if (specialData.changeStatusRatePlus3 >= 0) { yield return StartCoroutine(EnemyStatusEnforce(enemy_grobal, specialData.changeStatus3, specialData.changeStatusTurn3, specialData.changeStatusRatePlus3)); hasEffectivedItem = true; } else { yield return StartCoroutine(EnemyStatusWeakened(enemy_grobal, specialData.changeStatus3, specialData.changeStatusTurn3, specialData.changeStatusRatePlus3)); hasEffectivedItem = true; } } } IEnumerator MessageWait1() { yield return new WaitForSeconds(1.5f); useSpecialText.text = ""; yield return new WaitForSeconds(0.5f); } //戦闘中のステータスアップの処理(プレイヤー) IEnumerator StatusEnforce(PlayerManager player, GeneralEnum.STATUS upStatus, int enforceTurn, int enforceRate) { if (upStatus == GeneralEnum.STATUS.NONE) { DialogTextManager.instance.SetScenarios(new string[] { "・・・?" }); yield return new WaitForSeconds(1.2f); yield break; } if (player.statusUpWithLastTurn[upStatus] < enforceTurn) { player.statusUpWithLastTurn[upStatus] = enforceTurn; } if (player.statusUpRate[upStatus] <= 300) //強化率300を超えていなければ { player.statusUpRate[upStatus] += enforceRate; Mathf.Clamp(player.statusUpRate[upStatus], 0, 300); } TermManager termManager = new TermManager(); string statusMessage = termManager.Get_STATUS_EnforcedMessage(upStatus); DialogTextManager.instance.SetScenarios(new string[] { player.pname + statusMessage }); yield return new WaitForSeconds(1.2f); } //戦闘中のステータスダウンの処理(プレイヤー) IEnumerator StatusWeakened(PlayerManager player, GeneralEnum.STATUS downStatus, int weakenedTurn, int weakenedRate) { if (downStatus == GeneralEnum.STATUS.NONE) { DialogTextManager.instance.SetScenarios(new string[] { "・・・?" }); yield return new WaitForSeconds(2.4f); yield break; } if (player.statusUpWithLastTurn[downStatus] < weakenedTurn) { player.statusUpWithLastTurn[downStatus] = weakenedTurn; } if (player.statusUpRate[downStatus] >= 20) { player.statusUpRate[downStatus] += weakenedRate; Mathf.Clamp(player.statusUpRate[downStatus], 20, 300); } TermManager termManager = new TermManager(); string statusMessage = termManager.Get_STATUS_EnforcedMessage(downStatus); DialogTextManager.instance.SetScenarios(new string[] { player.pname + statusMessage }); yield return new WaitForSeconds(1.2f); } //戦闘中のステータスアップの処理(エネミー) IEnumerator EnemyStatusEnforce(EnemyManager enemy, GeneralEnum.STATUS upStatus, int enforceTurn, int enforceRate) { if (upStatus == GeneralEnum.STATUS.NONE) { DialogTextManager.instance.SetScenarios(new string[] { "・・・?" }); yield return new WaitForSeconds(1.2f); yield break; } if (enemy.statusUpWithLastTurn[upStatus] < enforceTurn) { enemy.statusUpWithLastTurn[upStatus] = enforceTurn; } if (enemy.statusUpRate[upStatus] <= 300) { enemy.statusUpRate[upStatus] += enforceRate; Mathf.Clamp(enemy.statusUpRate[upStatus],0,300); } TermManager termManager = new TermManager(); string statusMessage = termManager.Get_STATUS_EnforcedMessage(upStatus); DialogTextManager.instance.SetScenarios(new string[] { enemy.name + statusMessage }); yield return new WaitForSeconds(1.2f); } IEnumerator EnemyStatusWeakened(EnemyManager enemy, GeneralEnum.STATUS downStatus, int weakenedTurn, int weakenedRate) { if (downStatus == GeneralEnum.STATUS.NONE) { DialogTextManager.instance.SetScenarios(new string[] { "・・・?" }); yield return new WaitForSeconds(2.4f); yield break; } if (enemy.statusUpWithLastTurn[downStatus] < weakenedTurn) { enemy.statusUpWithLastTurn[downStatus] = weakenedTurn; } if (enemy.statusUpRate[downStatus] >= 20) { enemy.statusUpRate[downStatus] -= weakenedRate; Mathf.Clamp(enemy.statusUpRate[downStatus],20,300); } TermManager termManager = new TermManager(); string statusMessage = termManager.Get_STATUS_EnforcedMessage(downStatus); DialogTextManager.instance.SetScenarios(new string[] { enemy.name + statusMessage }); yield return new WaitForSeconds(1.2f); } IEnumerator CloseMessagePanel() { yield return new WaitForSeconds(1.0f); useSpecialMessagePanel.SetActive(false); } public void CloseSpecialMessageAndPanel() { specialUI.canTapSpecialUI = true; specialUsePanel.canTapSpecialUsePanel = true; useSpecialMessagePanel.SetActive(false); specialUsePanel.gameObject.SetActive(false); specialUIView.SetActive(true); } public void AfterUseSpecial() //キャンセルボタンが押された時の挙動をitemEventで実行 { if (GameManager.instance.gamePhase == GameManager.GAMEPHASE.QUEST) { cancelButton.GetComponent<Button>().onClick.Invoke(); } } public bool CheckHitAttackSpecial(EnemyManager enemy) { //特技が必中ならすぐにtrueをかえす。 if (specialData.hittingTheTarget) { return true; } int calcHitRate; int pHitRate = player.battleStatusValues[GeneralEnum.STATUS.HIT]; int pSence = player.battleStatusValues[GeneralEnum.STATUS.SENCE]; int pLuk = player.battleStatusValues[GeneralEnum.STATUS.LUK]; int eEvasion = enemy.battleStatusValues[GeneralEnum.STATUS.EVASION]; int eAgi = enemy.battleStatusValues[GeneralEnum.STATUS.AGI]; int eLuk = enemy.battleStatusValues[GeneralEnum.STATUS.LUK]; calcHitRate = (int)((pHitRate + (pSence / 10.0f) + (pLuk / 50.0f)) - (eEvasion + (eAgi / 10.0f) + (eLuk / 20.0f)) + specialData.HitCorrection); if (calcHitRate >= UnityEngine.Random.Range(1, 101)) { return true; } else { return false; } } }
特技を使用する時に表示するUIを作成します。
特技のUIを制御するSpecialUIスクリプトを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using System; using UnityEngine; using UnityEngine.UI; public class SpecialUI : MonoBehaviour { public SpecialManager specialManager; public Canvas specialCanvas; public SpecialUsePanel specialUsePanel; public GameObject useSpecialMessagePanel; public PlayerManager player; public bool canTapSpecialUI = true; SpecialManager.SPECIAL sEnum; GameObject scrollView; Transform viewPort; Transform content; void Start() { scrollView = GameObject.Find("SpecialUI_Scroll View"); viewPort = scrollView.transform.Find("Viewport"); content = viewPort.transform.Find("Content"); //デバッグで特技のUIを表示する前に、プレイヤーの特技のセットをする。 specialManager.TestInit(); SetSpecialUI(); specialCanvas.gameObject.SetActive(false); specialUsePanel.gameObject.SetActive(false); useSpecialMessagePanel.gameObject.SetActive(false); } public void SetSpecialUI() { //テキストを表示する for (int i = 0; i < Enum.GetValues(typeof(SpecialManager.SPECIAL)).Length; i++) { sEnum = (SpecialManager.SPECIAL)Enum.ToObject(typeof(SpecialManager.SPECIAL), i); if (player.canUseSpecials[sEnum] == -1) { continue; } else { GameObject Contents = new GameObject("Contents" + (i + 1).ToString()); Contents.transform.parent = content.transform; var Rect = Contents.AddComponent<RectTransform>(); Rect.transform.localPosition = new Vector3(0, 0, 0); Rect.transform.localScale = new Vector3(1, 1, 1); Rect.sizeDelta = new Vector2(0, 100); Contents.AddComponent<CanvasRenderer>(); Contents.AddComponent<Image>(); Contents.AddComponent<LayoutElement>().preferredHeight = 100; var buttonState = Contents.AddComponent<Button>(); //背景の色を変えて見やすくする var colors = buttonState.colors; if (content.transform.childCount % 2 == 0) { colors.normalColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); colors.highlightedColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); colors.pressedColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); colors.disabledColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); } else { colors.normalColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.highlightedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.pressedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.disabledColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); } buttonState.colors = colors; GameObject text = new GameObject("Special" + (i + 1).ToString()); text.transform.parent = Contents.transform; var rect = text.AddComponent<RectTransform>(); rect.transform.localPosition = new Vector3(0, 0, 0); rect.transform.localScale = new Vector3(1, 1, 1); rect.sizeDelta = new Vector2(900, 90); text.AddComponent<CanvasRenderer>(); var textChild = text.AddComponent<Text>(); //-----------特技名 + 必要なTP------ string viewText = ""; string nameText = specialManager.specialDatas[i].specialName; string tpValue = " TP " + specialManager.specialDatas[i].useTpValue.ToString(); textChild.text = nameText + tpValue; textChild.color = GetElementColor(specialManager.specialDatas[i]);//属性に応じて色を変える textChild.fontSize = 30; textChild.alignment = TextAnchor.MiddleCenter; textChild.font = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font; //-------------テキストここまで------------- //ボタンを押した時のイベント時に参照するspecialEventをつける specialUsePanel.gameObject.SetActive(true);//Findで検知させるため、一度アクティブにする var specialEvent = Contents.AddComponent<SpecialEvent>(); specialEvent.specialData = specialManager.specialDatas[i]; specialEvent.specialUsePanel = specialUsePanel; specialUsePanel.gameObject.SetActive(false);//非アクティブに戻しておく specialEvent.useSpecialMessagePanel = useSpecialMessagePanel; buttonState.onClick.AddListener(specialEvent.SetSpecialTargetPanel); //--------------------イベントここまで---------------- //ボタン上の左側にスキルのアイコンを表示する GameObject specialIcon = new GameObject("SpecialIcon" + (i + 1).ToString()); specialIcon.transform.parent = buttonState.transform; var iconRect = specialIcon.AddComponent<RectTransform>(); iconRect.transform.localPosition = new Vector3(-250, 0, 0); iconRect.transform.localScale = new Vector3(1, 1, 1); //rect.sizeDelta = new Vector2(900, 90); specialIcon.AddComponent<CanvasRenderer>(); var iconImage = specialIcon.AddComponent<Image>(); iconImage.sprite = specialManager.specialDatas[i].specialSprite; } } } public void UpdateSpecialUI() { DestroyAllSpecial(); SetSpecialUI(); } public void DestroyAllSpecial() { if (content.gameObject.transform.childCount != 0) { foreach (Transform child in content.gameObject.transform) { //全要素削除 Destroy(child.gameObject); } } } public void ShowSpecialUI() { SoundManager.instance.PlaySE(20); UpdateSpecialUI(); specialCanvas.gameObject.SetActive(true); scrollView.gameObject.SetActive(true); } //アイテムUIを消す(見えなくする) public void HideSpecialUI() { SoundManager.instance.PlaySE(7); DestroyAllSpecial(); specialCanvas.gameObject.SetActive(false); } /// <summary> /// スキルに付与された属性に応じた色を返す関数 /// </summary> /// <returns></returns> public Color GetElementColor(SpecialData specialData) { Color elementColor = new Color(); switch (specialData.element) { case GeneralEnum.ELEMENT.NONE: elementColor = new Color(255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.FIRE: elementColor = new Color(255f / 255f, 60f / 255f, 60f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.WIND: elementColor = new Color(181f / 255f, 20f / 255f, 60f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.GROUND: elementColor = new Color(180f / 255f, 113f / 255f, 66f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.THUNDER: elementColor = new Color(255f / 255f, 255f / 255f, 32f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.AQUA: elementColor = new Color(31f / 255f, 133f / 255f, 255f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.ICE: elementColor = new Color(175f / 255f, 240f / 255f, 255f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.LIGHT: elementColor = new Color(255f / 255f, 244f / 255f, 156f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.DARK: elementColor = new Color(78f / 255f, 24f / 255f, 109f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.DRAGON: elementColor = new Color(73f / 255f, 28f / 255f, 10f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.SOUND: elementColor = new Color(255f / 255f, 183f / 255f, 149f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.STAR: elementColor = new Color(13f / 255f, 43f / 255f, 182f / 255f, 255f / 255f); break; case GeneralEnum.ELEMENT.ALL: elementColor = new Color(242f / 255f, 155f / 255f, 243f / 255f, 255f / 255f); break; } return elementColor; } }
GetElementColor関数は特技の持つ属性によってテキストの色を決める関数です。今回特技のテキストを属性によって色を変えて表示してみました。(のちのち戻すかもしれません)
特使を選択した際に表示する対象選択のためのパネルを制御するSpecialUsePanelクラスを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class SpecialUsePanel : MonoBehaviour { public PlayerUIManager playerUIManager; public GameObject specialCanvas; public GameObject specialUI; public GameObject cancelButton; public CommandUIManager commandUI; public BattleManager battleManager; public bool canTapSpecialUsePanel = true; public void SetHealSpecialUsePanel(GameObject useSpecialMessagePanel, SpecialData specialData, SpecialUsePanel specialUsePanel) { ResetSpecialUsePanel(); for (int i = 0; i < GameManager.instance.partyMemberCount; i++) { GameObject targetPartyMember = new GameObject("PartyMember" + (i + 1).ToString()); targetPartyMember.transform.parent = this.transform; //ItemUsePanelオブジェクトを親にする var Rect = targetPartyMember.AddComponent<RectTransform>(); Rect.transform.localPosition = new Vector3(0, 0, 0); Rect.transform.localScale = new Vector3(1, 1, 1); Rect.sizeDelta = new Vector3(0, 100); targetPartyMember.AddComponent<CanvasRenderer>(); targetPartyMember.AddComponent<Image>(); targetPartyMember.AddComponent<LayoutElement>().preferredHeight = 100; var buttonState = targetPartyMember.AddComponent<Button>(); //背景の色を変えて見やすく var colors = buttonState.colors; if (this.transform.childCount % 2 == 0) { colors.normalColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); colors.highlightedColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); colors.pressedColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); colors.disabledColor = new Color(0F / 255F, 0F / 255F, 0F / 255F, 128F / 255F); } else { colors.normalColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.highlightedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.pressedColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); colors.disabledColor = new Color(0 / 255F, 0 / 255F, 0 / 255F, 50 / 255F); } buttonState.colors = colors; GameObject text = new GameObject("Special" + (i + 1).ToString()); text.transform.parent = targetPartyMember.transform; var rect = text.AddComponent<RectTransform>(); rect.transform.localPosition = new Vector3(0, 0, 0); rect.transform.localScale = new Vector3(1, 1, 1); rect.sizeDelta = new Vector2(900, 90); text.AddComponent<CanvasRenderer>(); var textChild = text.AddComponent<Text>(); //----------------プレイヤー名のテキスト生成----------- textChild.text = PlayerManager.instance.pname; textChild.color = new Color(255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f); textChild.fontSize = 30; textChild.alignment = TextAnchor.MiddleCenter; textChild.font = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font; //-----------ボタンを押したときの処理------ var specialEvent = targetPartyMember.AddComponent<SpecialEvent>(); specialEvent.useSpecialMessagePanel = useSpecialMessagePanel; specialEvent.specialData = specialData; specialEvent.specialUsePanel = specialUsePanel; specialEvent.playerUIManager = this.playerUIManager; specialEvent.cancelButton = cancelButton; specialEvent.commandUI = this.commandUI; specialEvent.specialCanvas = this.specialCanvas; if (GameManager.instance.gamePhase == GameManager.GAMEPHASE.QUEST) { buttonState.onClick.AddListener(() => specialEvent.UseHealSpecial(PlayerManager.instance)); } else if (GameManager.instance.gamePhase == GameManager.GAMEPHASE.BATTLE) { //buttonState.onClick.AddListener(() => itemEvent.UseHealItemOnBattle(PlayerManager.instance)); 削除 buttonState.onClick.AddListener(() => specialEvent.DecidePlayerUseSpecialOnBattle()); //変更 specialEvent.DecideUseSpecial += battleManager.StartBattleTurn; specialEvent.IEUseSpecialRegister = specialEvent.IEUseHealSpecialOnBattle(); } //if (GameManager.instance.gamePhase == GameManager.GAMEPHASE.QUEST) //{ // //itemEvent.AddEventListenerAfterUseItemAction(); //} //----------------ボタンを押した時の処理ここまで----------- } } //SpecialUIでATTACKの特技を選択した時に呼び出される関数 public void SetTargetSelectOnAttackSpecial(GameObject useSpecialMessagePanel, SpecialData specialData, SpecialUsePanel specialUsePanel, SpecialEvent specialEventA) { battleManager.SetCanAttackTap(true); //敵をタップできるようにする specialEventA.useSpecialMessagePanel = useSpecialMessagePanel; specialEventA.specialData = specialData; specialEventA.specialUsePanel = specialUsePanel; specialEventA.playerUIManager = this.playerUIManager; specialEventA.commandUI = this.commandUI; specialEventA.specialCanvas = this.specialCanvas; } public void ResetSpecialUsePanel() { if (this.gameObject.transform.childCount != 0) { foreach (Transform child in this.gameObject.transform) { //パネルの要素を全て削除する Destroy(child.gameObject); } } } }
battleManagerに特技関連の処理を追加します。ついでにSetupBattle関数でプレイヤーの戦闘用のDictionaryを初期化する関数を呼び出します。
クリックで展開
//特技使用時に実行する関数を登録する入れ物 Action UseSpecialAction; //New public SpecialEvent playerSpecialEvent; //New public void SetUpBattle() { SoundManager.instance.PlayBGM("Battle"); player = PlayerManager.instance; player.InitBattleDictionary(); //New playerUI.SetupUI(player); commandUI.gameObject.SetActive(true); commandUI.SetBattleCommand(); battleResult = new BattleResult(); // クラスから実体生成 isBattleEnd = false; InitBattleActionDic(); //行動タイプDictionray初期化 } IEnumerator StartPlayerTurn() { switch (battleActionDic[0]) { case BATTLEACTIONTYPE.NORMALATTACK://通常攻撃の場合 yield return StartCoroutine(PlayerNormalAttack()); break; case BATTLEACTIONTYPE.GUARD://防御の場合 break; case BATTLEACTIONTYPE.ITEM://アイテムの場合 yield return StartCoroutine(PlayerUseItem()); break; case BATTLEACTIONTYPE.MAGIC://魔法の場合 break; case BATTLEACTIONTYPE.MOVE://特技の場合 yield return StartCoroutine(PlayerUseSpecial()); //New break; case BATTLEACTIONTYPE.ESCAPE: //逃げるの場合 break; } //----------敵を倒した時の処理--------------- if (enemysList[targetIndex].hp <= 0) { yield return StartCoroutine(EnemyDeath(targetIndex)); if (CheckAllEnemyDeath()) { yield return StartCoroutine(EndBattle()); } } } IEnumerator PlayerUseSpecial() //New { commandUI.gameObject.SetActive(false); playerSpecialEvent.enemy_grobal = enemysList[targetIndex]; //実行するspecialEventのターゲットを設定 yield return StartCoroutine(playerSpecialEvent.IEUseSpecialRegister); Destroy(playerSpecialEvent.gameObject); yield return null; }
StageUIManagerに探索中に特技ボタンを押した時の処理を記述します。
クリックで展開
public GameObject specialButton; //new public GameObject specialUI; //New public GameObject specialUsePanel; //New public void HideButtons() { nextButton.SetActive(false); toTownButton.SetActive(false); itemButton.SetActive(false); statusButton.SetActive(false); mapButton.SetActive(false); debugButton.SetActive(false); arrowsButtons.SetActive(false); cancelButton.SetActive(false); actionButton.SetActive(false); equipmentButton.SetActive(false); specialButton.SetActive(false);//New } public void ShowButtons() { nextButton.SetActive(true); toTownButton.SetActive(true); itemButton.SetActive(true); statusButton.SetActive(true); mapButton.SetActive(true); debugButton.SetActive(true); arrowsButtons.SetActive(true); if (isEventPosition) { actionButton.SetActive(true); } equipmentButton.SetActive(true); specialButton.SetActive(true);//New } public void PushCancelButton() { if (itemUsePanel.activeInHierarchy) { itemUsePanel.gameObject.SetActive(false); itemUI.GetComponent<ItemUI>().canTapItemUI = true; return; } if (specialUsePanel.activeInHierarchy) //New { specialUsePanel.gameObject.SetActive(false); specialUI.GetComponent<SpecialUI>().canTapSpecialUI = true; return; } nextButton.SetActive(true); toTownButton.SetActive(true); itemButton.SetActive(true); statusButton.SetActive(true); cancelButton.SetActive(false); mapButton.SetActive(true); debugButton.SetActive(true); arrowsButtons.SetActive(true); if (isEventPosition) { actionButton.SetActive(true); } equipmentButton.SetActive(true); specialButton.SetActive(true);//New }
CommandUIManager.csに戦闘中に特技ボタンを押した時の処理を記述します。
クリックで展開
public GameObject specialUI; //New public GameObject specialUIView; //New public GameObject specialUsePanel;//New public GameObject useSpecialMessagePanel;//New private bool isOpenSpecialUI = false; //New public void PushSpecialButton()//New { attackButton.gameObject.SetActive(false); specialButton.gameObject.SetActive(false); itemButton.gameObject.SetActive(false); escapeButton.gameObject.SetActive(false); DialogUI.gameObject.SetActive(false); //キャンセルボタンの位置を下にずらす cancelButton.gameObject.transform.Translate(0, -150, 0); isOpenSpecialUI = true; cancelButton.gameObject.SetActive(true); } public void PushCancelButton() { if (itemUsePanel.activeInHierarchy) { itemUsePanel.gameObject.SetActive(false); itemUI.GetComponent<ItemUI>().canTapItemUI = true; return; } if (useItemMessaagePanel.activeInHierarchy) { GameObject itemEventA = GameObject.Find("AttackItemEvent"); if(itemEventA != null) { Destroy(itemEventA); } useItemMessaagePanel.gameObject.SetActive(false); itemUIView.SetActive(true); itemUI.GetComponent<ItemUI>().canTapItemUI = true; return; } if (specialUsePanel.activeInHierarchy)//特技のターゲット選択パネルが開いている場合 New { specialUsePanel.gameObject.SetActive(false); specialUI.GetComponent<SpecialUI>().canTapSpecialUI = true; return; } if (useSpecialMessagePanel.activeInHierarchy) //New { GameObject specialEventA = GameObject.Find("AttackSpecialEvent"); if (specialEventA != null) { Destroy(specialEventA); } useSpecialMessagePanel.gameObject.SetActive(false); specialUIView.SetActive(true); specialUI.GetComponent<SpecialUI>().canTapSpecialUI = true; return; } attackButton.gameObject.SetActive(true); specialButton.gameObject.SetActive(true); cancelButton.gameObject.SetActive(false); itemButton.gameObject.SetActive(true); escapeButton.gameObject.SetActive(true); DialogUI.gameObject.SetActive(true); //アイテム選択画面から戻る場合はキャンセルボタンの位置をもとに戻す if (isOpenItemUI) { cancelButton.gameObject.transform.Translate(0, 150, 0); itemUI.GetComponent<ItemUI>().HideItemUI(); //itemUI.GetComponent<ItemUI>().itemUsePanel.gameObject.SetActive(false); isOpenItemUI = false; } //特技の場合も同様 if (isOpenSpecialUI)//New { cancelButton.gameObject.transform.Translate(0, 150, 0); specialUI.GetComponent<SpecialUI>().HideSpecialUI(); isOpenSpecialUI = false; } } public void HideCancelButton() { cancelButton.SetActive(false); cancelButton.gameObject.transform.Translate(0, 150, 0); isOpenItemUI = false; isOpenSpecialUI = false; //New }
公開変数の設定、Buttonの関数設定をして実際に戦闘してみます。
探索イベント関連で少しバグがありますが動作しました。
次回は特技使用時のアニメーション再生を実装したいと思います。