【Unity】RPG制作 その32-特技の実装3 特技の効果対象による処理分岐、コードの整理
今回は特技の効果対象によって敵を複数回攻撃したりランダムで攻撃したりできるようにしていきます。
SpecialEvent.csのIEUseAttackSpecialコルーチンに処理を描いていきます。現状条件文の中の実行コードがかなり長くなっており、処理全体の見通しが悪くなっているので、実際に処理を行う部分を関数にします。
クリックで展開
public IEnumerator AllOfEnemyAttackSpecialProcess()//New { //全体攻撃の場合、ダメージの減衰をさせたいのでカウント変数を用意する int enemyCount = 0; for (int i = 0; i < 3; i++) { if (battleManager.enemysList.ContainsKey(i)) { enemyCount++;//ダメージ減衰用のカウント変数を1増やす //攻撃特技のダメージ量を計算する((player 攻撃力 * 攻撃影響率 / 100)+(player 魔力 * 魔力影響率 / 100) + 固定ダメージ量) if (CheckHitAttackSpecial(battleManager.enemysList[i])) { //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; battleManager.enemysList[i].CalcBattleStatusValues();//敵の戦闘時ステータスを計算する int eDef = battleManager.enemysList[i].baseStatusValue[GeneralEnum.STATUS.DEF]; int eMdef = battleManager.enemysList[i].baseStatusValue[GeneralEnum.STATUS.MAGDEF]; //攻撃側の値を計算する float hpAtkValue = (pAtk * sIAtk / 100f) + (pAgi * sIAgi / 100f) + (pMag * sIMag / 100f) + (pDef * sIDef / 100f) + (pMdef * sIMDef / 100f) + (pLuk * sLuk / 100f) + (pLearn * sLearn / 100f) + specialData.HPDamageValue; //防御側の値を計算する(防御力がダメージを減らす割合は基本25%) _ = eMdef * specialData.thingE_MDEFRate / 100f;//特技の魔法防御反映率処理 float hpDefValue = (eDef / 4f) + (eMdef); hpDefValue -= (hpDefValue * (specialData.penetrationRate / 100f));//貫通率処理 float calcDamage = hpAtkValue - hpDefValue; calcDamage = calcDamage * (1.00f - (0.15f * enemyCount)); //敵の数によるダメージの減衰(右の敵ほどダメージが減る) calcDamage *= UnityEngine.Random.Range(1.0f - specialData.damageDispersionRate, 1.0f + specialData.damageDispersionRate); //ダメージを分散させる New int hpPoint = (int)calcDamage; if (PlayerCheckCritical(battleManager.enemysList[i])) hpPoint *= 2; if (hpPoint < 1) hpPoint = 1;//最低ダメージ1 //MPダメージ量を計算する int sIAtkOnMP = specialData.attackInfluenceOnMP; int sIMagOnMP = specialData.attackInfluenceOnMP; int mpPoint = (int)((pAtk * sIAtkOnMP / 100f) + (pMag * sIMagOnMP / 100f) + specialData.MPDamageValue); //TPダメージ量を計算する int sIAtkOnTP = specialData.attackInfluenceOnTP; int sIMagOnTP = specialData.attackInfluenceOnTP; int tpPoint = (int)((pAtk * sIAtkOnTP / 100f) + (pMag * sIMagOnTP / 100f) + specialData.TPDamageValue); battleManager.enemysList[i].hp -= hpPoint; battleManager.enemysList[i].mp -= mpPoint; battleManager.enemysList[i].tp -= tpPoint; bool wasEffecitveSpecial = false; if (battleManager.enemysList[i].hp < 0) battleManager.enemysList[i].hp = 0; if (battleManager.enemysList[i].mp < 0) battleManager.enemysList[i].mp = 0; if (battleManager.enemysList[i].tp < 0) battleManager.enemysList[i].tp = 0; if (hpPoint > 0) { battleManager.enemysList[i].transform.DOShakePosition(0.3f, 0.5f, 20, 0, false, true); DialogTextManager.instance.SetScenarios(new string[] { battleManager.enemysList[i].name + "に" + hpPoint + "のダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (mpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { battleManager.enemysList[i].name + "に" + mpPoint + "のMPダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (tpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { battleManager.enemysList[i].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[] { battleManager.enemysList[i].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); } battleManager.enemysList[i].gameObject.GetComponent<EnemyUIManager>().UpdateUI(battleManager.enemysList[i]); } else//攻撃が命中しなかった場合 { DialogTextManager.instance.SetScenarios(new string[] { player.pname + "の攻撃は外れた" }); yield return new WaitForSeconds(1.2f); } } } } public IEnumerator OneOfEnemyAttackSpecialProcess() //New { //攻撃特技のダメージ量を計算する((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; enemy_grobal.CalcBattleStatusValues();//敵の戦闘時ステータスを計算する int eDef = enemy_grobal.baseStatusValue[GeneralEnum.STATUS.DEF]; int eMdef = enemy_grobal.baseStatusValue[GeneralEnum.STATUS.MAGDEF]; //攻撃側の値を計算する float hpAtkValue = (pAtk * sIAtk / 100f) + (pAgi * sIAgi / 100f) + (pMag * sIMag / 100f) + (pDef * sIDef / 100f) + (pMdef * sIMDef / 100f) + (pLuk * sLuk / 100f) + (pLearn * sLearn / 100f) + specialData.HPDamageValue; //防御側の値を計算する(防御力がダメージを減らす割合は基本25%) _ = eMdef * specialData.thingE_MDEFRate / 100f;//特技の魔法防御反映率処理 float hpDefValue = (eDef / 4f) + eMdef; hpDefValue -= (hpDefValue * (specialData.penetrationRate / 100f));//貫通率処理 float calcDamage = hpAtkValue - hpDefValue; calcDamage *= UnityEngine.Random.Range(1.0f - specialData.damageDispersionRate, 1.0f + specialData.damageDispersionRate); //ダメージを分散させる New int hpPoint = (int)calcDamage; if (PlayerCheckCritical(enemy_grobal)) hpPoint *= 2; if (hpPoint < 1) hpPoint = 1;//最低ダメージ1 //MPダメージ量を計算する int sIAtkOnMP = specialData.attackInfluenceOnMP; int sIMagOnMP = specialData.attackInfluenceOnMP; int mpPoint = (int)((pAtk * sIAtkOnMP / 100f) + (pMag * sIMagOnMP / 100f) + specialData.MPDamageValue); //TPダメージ量を計算する int sIAtkOnTP = specialData.attackInfluenceOnTP; int sIMagOnTP = specialData.attackInfluenceOnTP; int tpPoint = (int)((pAtk * sIAtkOnTP / 100f) + (pMag * sIMagOnTP / 100f) + specialData.TPDamageValue); enemy_grobal.hp -= hpPoint; enemy_grobal.mp -= mpPoint; enemy_grobal.tp -= tpPoint; bool wasEffecitveSpecial = false; if (enemy_grobal.hp < 0) enemy_grobal.hp = 0; if (enemy_grobal.mp < 0) enemy_grobal.mp = 0; if (enemy_grobal.tp < 0) enemy_grobal.tp = 0; if (hpPoint > 0) { enemy_grobal.transform.DOShakePosition(0.3f, 0.5f, 20, 0, false, true);//New 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); } enemy_grobal.gameObject.GetComponent<EnemyUIManager>().UpdateUI(enemy_grobal); }
SpecialEvent.csのIEUseAttackSpecialコルーチンの処理を作成した関数に置き換えます。
クリックで展開
IEnumerator IEUseAttackSpecial() { DialogTextManager.instance.SetScenarios(new string[] { player.pname + specialData.useMessage_Battle }); yield return new WaitForSeconds(1.5f); int activateCount = specialData.activateCount;//特技を発動する回数(複数回攻撃する時の処理) for (int j = 0; j < activateCount; j++) { yield return StartCoroutine(PlayBattleEffect()); player.CalcBattleStatusValues();//プレイヤーの戦闘時ステータスを計算する //敵への全体攻撃の場合はBattleManagerのenemysListの要素でループさせる if (specialData.target == SpecialData.TARGET.AllOfEnemy) //New { yield return StartCoroutine(AllOfEnemyAttackSpecialProcess());//全体攻撃の処理 } else //全体攻撃でない場合 { yield return StartCoroutine(OneOfEnemyAttackSpecialProcess());//単体攻撃の処理 } } //TPを消費する player.tp -= specialData.useTpValue; useSpecialMessagePanel.SetActive(false); playerUIManager.UpdateUI(PlayerManager.instance); specialUI.canTapSpecialUI = true; specialUsePanel.canTapSpecialUsePanel = true; specialUsePanel.gameObject.SetActive(false); }
これで攻撃特技の処理が分かりやすくなります。specialDataのactivateCount(特技の発動回数)分For文でループさせるようにしたのでこれで複数回攻撃の実装ができます。
敵をランダムに攻撃する処理を作るのに当たって、Dictinary型からランダムにKeyを取得する処理を使いたいと思います。Dictionary自体にそういった機能持つメソッドが用意されていない(多分)ので、ネットで調べた方法でDictinaryからランダムにKeyを取得できるようにします。こちらのサイトを参考にさせていただきました。
Dictionary型の拡張メソッドクラスDictionaryExtクラスを作成します。
クリックで展開
using System.Collections.Generic; using System; using System.Linq; //Dictionary型からランダムにKeyやValueを取得するための拡張メソッド public static class DictionaryExt { private static Random m_random; private static Random random => m_random ?? (m_random = new Random()); public static KeyValuePair<TKey, TValue> RandomAt<TKey, TValue>(this Dictionary<TKey, TValue> source) { if( source == null) { throw new ArgumentNullException( nameof(source) ); } return source.ElementAt( random.Next( 0, source.Count) ); } public static TKey RandomAt<TKey, TValue>(this Dictionary<TKey, TValue>.KeyCollection source) { if( source == null) { throw new ArgumentNullException(nameof(source)); } return source.ElementAt(random.Next(0, source.Count)); } public static TValue RandomAt<TKey, TValue>(this Dictionary<TKey, TValue>.ValueCollection source) { if(source == null) { throw new ArgumentNullException(nameof(source)); } return source.ElementAt(random.Next(0, source.Count)); } }
このクラスをプロジェクト内に置いておけばプロジェクト内のコードのDictionary型は全て拡張メソッドを使えます。
クリックで展開
//戦闘中に攻撃特技を使う処理 IEnumerator IEUseAttackSpecial() { DialogTextManager.instance.SetScenarios(new string[] { player.pname + specialData.useMessage_Battle }); yield return new WaitForSeconds(1.5f); int activateCount = specialData.activateCount;//特技を発動する回数(複数回攻撃する時の処理) int randomIndex = 0; for (int j = 0; j < activateCount; j++) { if (specialData.target == SpecialData.TARGET.OneOfEnemyAtRandom) { //enemysListからキーをランダムに取得 randomIndex = battleManager.enemysList.Keys.RandomAt();//DirectionaryExtの拡張メソッドを使用する yield return StartCoroutine(PlayBattleEffectWhenRandom(randomIndex)); } else { yield return StartCoroutine(PlayBattleEffect()); } player.CalcBattleStatusValues();//プレイヤーの戦闘時ステータスを計算する //敵への全体攻撃の場合はBattleManagerのenemysListの要素でループさせる if (specialData.target == SpecialData.TARGET.AllOfEnemy) //New { yield return StartCoroutine(AllOfEnemyAttackSpecialProcess());//全体攻撃の処理 } else if (specialData.target == SpecialData.TARGET.OneOfEnemyAtRandom) { yield return StartCoroutine(OneOfEnemyAtRandomAttackSpecialProcess(randomIndex)); } else //それ以外の場合 { yield return StartCoroutine(OneOfEnemyAttackSpecialProcess());//単体攻撃の処理 } if (battleManager.CheckAllEnemyDeath())//敵を全て倒している場合はループさせたくないのでbreak { break; } } //TPを消費する player.tp -= specialData.useTpValue; useSpecialMessagePanel.SetActive(false); playerUIManager.UpdateUI(PlayerManager.instance); specialUI.canTapSpecialUI = true; specialUsePanel.canTapSpecialUsePanel = true; specialUsePanel.gameObject.SetActive(false); if (battleManager.CheckAllEnemyDeath())//敵を全て倒している場合はここで戦闘を終了させる { yield return StartCoroutine(battleManager.EndBattle()); } } public IEnumerator PlayBattleEffectWhenRandom(int index) //New { //SEの再生 if (specialData.UseSEID != -1) { SoundManager.instance.PlaySE(specialData.UseSEID); } //アニメーションの再生 if (specialData.spAnimation != null) //アニメーションが設定されていたら { PlayEffect playEffect = new PlayEffect(); playEffect.playAllEffectPoint = allEffectPoint; yield return StartCoroutine(playEffect.IEPlaySpecialEffect(battleManager.enemysList[index].transform.position, specialData)); } } public IEnumerator OneOfEnemyAtRandomAttackSpecialProcess(int index) //New { EnemyManager enemy = battleManager.enemysList[index]; //攻撃特技のダメージ量を計算する((player 攻撃力 * 攻撃影響率 / 100)+(player 魔力 * 魔力影響率 / 100) + 固定ダメージ量) if (CheckHitAttackSpecial(enemy)) { //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; enemy.CalcBattleStatusValues();//敵の戦闘時ステータスを計算する int eDef = enemy.baseStatusValue[GeneralEnum.STATUS.DEF]; int eMdef = enemy.baseStatusValue[GeneralEnum.STATUS.MAGDEF]; //攻撃側の値を計算する float hpAtkValue = (pAtk * sIAtk / 100f) + (pAgi * sIAgi / 100f) + (pMag * sIMag / 100f) + (pDef * sIDef / 100f) + (pMdef * sIMDef / 100f) + (pLuk * sLuk / 100f) + (pLearn * sLearn / 100f) + specialData.HPDamageValue; //防御側の値を計算する(防御力がダメージを減らす割合は基本25%) _ = eMdef * specialData.thingE_MDEFRate / 100f;//特技の魔法防御反映率処理 float hpDefValue = (eDef / 4f) + eMdef; hpDefValue -= (hpDefValue * (specialData.penetrationRate / 100f));//貫通率処理 float calcDamage = hpAtkValue - hpDefValue; calcDamage *= UnityEngine.Random.Range(1.0f - specialData.damageDispersionRate / 100f, 1.0f + specialData.damageDispersionRate / 100f); //ダメージを分散させる New int hpPoint = (int)calcDamage; if (PlayerCheckCritical(enemy)) hpPoint *= 2; if (hpPoint < 1) hpPoint = 1;//最低ダメージ1 //MPダメージ量を計算する int sIAtkOnMP = specialData.attackInfluenceOnMP; int sIMagOnMP = specialData.attackInfluenceOnMP; int mpPoint = (int)((pAtk * sIAtkOnMP / 100f) + (pMag * sIMagOnMP / 100f) + specialData.MPDamageValue); //TPダメージ量を計算する int sIAtkOnTP = specialData.attackInfluenceOnTP; int sIMagOnTP = specialData.attackInfluenceOnTP; int tpPoint = (int)((pAtk * sIAtkOnTP / 100f) + (pMag * sIMagOnTP / 100f) + specialData.TPDamageValue); enemy.hp -= hpPoint; enemy.mp -= mpPoint; enemy.tp -= tpPoint; bool wasEffecitveSpecial = false; if (enemy.hp < 0) enemy.hp = 0; if (enemy.mp < 0) enemy.mp = 0; if (enemy.tp < 0) enemy.tp = 0; if (hpPoint > 0) { enemy.transform.DOShakePosition(0.3f, 0.5f, 20, 0, false, true);//New DialogTextManager.instance.SetScenarios(new string[] { enemy.name + "に" + hpPoint + "のダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (mpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { enemy.name + "に" + mpPoint + "のMPダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (tpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { enemy.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.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); } enemy.gameObject.GetComponent<EnemyUIManager>().UpdateUI(enemy); //HPが0ならここで敵撃破処理を行う if (enemy.hp <= 0) { yield return StartCoroutine(battleManager.EnemyDeath(index)); } }
効果対象がOneOfEnemyAtRandom(ランダムに敵一体)の時にbattleManagerのenemysListからKeyをランダムに取得して敵を攻撃する処理を入れました。PlayBattleEffectWhenRandomコルーチンで攻撃する敵の場所にエフェクトが再生されるようにしています。OneOfEnemyAtRandomAttackSpecialProcessコルーチンでランダムに敵一体を攻撃する時の処理を行っています。もし途中で敵を撃破した場合はbattleManagerのEnemyDeath関数を実行してたおした敵にまた攻撃しないようにします。そしてIEUseAttackSpecialコルーチンのfor文の最後でbattleManager.CheckAllEnemyDeathを行い敵が全て倒された場合はfor文を抜けてそれ以上攻撃が実行されないようにします。
IEUseAttackSpecialコルーチンの最後で再度battleManager.CheckAllEnemyDeathをし、trueなら戦闘終了処理をします。battleManagerの
StartPlayerTurnコルーチンの最後にも戦闘終了処理があるので、そちらはisBattleEndがfalseの場合に実行されるようにし、EndBattleが2回実行されないようにします。
クリックで展開
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()); break; case BATTLEACTIONTYPE.ESCAPE: //逃げるの場合 break; } //----------敵を倒した時の処理--------------- if (!isBattleEnd)//SpecialEventの途中でEndBattleする可能性があるので戦闘が終了したかここで判定しておく(判定しないとENdBattleコルーチンが2回実行されてしまう) { for (int i = 0; i < 3; i++) { if (enemysList.ContainsKey(i)) { if (enemysList[i].hp <= 0) { yield return StartCoroutine(EnemyDeath(i)); } } } if (CheckAllEnemyDeath()) { yield return StartCoroutine(EndBattle()); } } }
これで戦闘テストをしてみます。
今回は以上です。
【Unity】RPG制作 その31-特技の実装2 全体攻撃実装
今回は全体攻撃の特技を実装していきたいと思います。
SpecialData.csの列挙型TARGETのtargetに使用対象を設定するようにしているので、targetの中身がTARGET.AllOfEnemy(敵全体)の場合の処理をSpecialEvent.csに記述します。
クリックで展開
//戦闘中に攻撃特技を使う処理 IEnumerator IEUseAttackSpecial() { DialogTextManager.instance.SetScenarios(new string[] { player.pname + specialData.useMessage_Battle }); yield return new WaitForSeconds(1.5f); //SEの再生 if (specialData.UseSEID != -1) { SoundManager.instance.PlaySE(specialData.UseSEID); } //アニメーションの再生 if (specialData.spAnimation != null) //アニメーションが設定されていたら { PlayEffect playEffect = new PlayEffect(); playEffect.playAllEffectPoint = allEffectPoint; if(specialData.target == SpecialData.TARGET.AllOfEnemy) { Vector3 eCenter = new Vector3(0,0,0); yield return StartCoroutine(playEffect.IEPlayAllSpecialEffect(specialData)); } else { yield return StartCoroutine(playEffect.IEPlaySpecialEffect(enemy_grobal.transform.position, specialData)); } } player.CalcBattleStatusValues();//プレイヤーの戦闘時ステータスを計算する //敵への全体攻撃の場合はBattleManagerのenemysListの要素でループさせる if (specialData.target == SpecialData.TARGET.AllOfEnemy) //New { //全体攻撃の場合、ダメージの減衰をさせたいのでカウント変数を用意する int enemyCount = 0; for(int i = 0; i < 3; i++) { if (battleManager.enemysList.ContainsKey(i)) { enemyCount++;//ダメージ減衰用のカウント変数を1増やす //攻撃特技のダメージ量を計算する((player 攻撃力 * 攻撃影響率 / 100)+(player 魔力 * 魔力影響率 / 100) + 固定ダメージ量) if (CheckHitAttackSpecial(battleManager.enemysList[i])) { //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; battleManager.enemysList[i].CalcBattleStatusValues();//敵の戦闘時ステータスを計算する int eDef = battleManager.enemysList[i].baseStatusValue[GeneralEnum.STATUS.DEF]; int eMdef = battleManager.enemysList[i].baseStatusValue[GeneralEnum.STATUS.MAGDEF]; //攻撃側の値を計算する int hpAtkValue = (int)((pAtk * sIAtk / 100f) + (pAgi * sIAgi / 100f) + (pMag * sIMag / 100f) + (pDef * sIDef / 100f) + (pMdef * sIMDef / 100f) + (pLuk * sLuk / 100f) + (pLearn * sLearn / 100f) + specialData.HPDamageValue); //防御側の値を計算する(防御力がダメージを減らす割合は基本25%) _ = (int)(eMdef * specialData.thingE_MDEFRate / 100f);//特技の魔法防御反映率処理 int hpDefValue = (int)((eDef/4f) + (eMdef)); hpDefValue -= (int)( hpDefValue * (specialData.penetrationRate/100f));//貫通率処理 int hpPoint = hpAtkValue- hpDefValue; //New if (PlayerCheckCritical(battleManager.enemysList[i])) hpPoint *= 2; hpPoint = (int)( hpPoint * (1.00f - (0.15f * enemyCount) ) ); //敵の数によるダメージの減衰(右の敵ほどダメージが減る) if (hpPoint < 1) hpPoint = 1;//最低ダメージ1 //MPダメージ量を計算する int sIAtkOnMP = specialData.attackInfluenceOnMP; int sIMagOnMP = specialData.attackInfluenceOnMP; int mpPoint = (int)((pAtk * sIAtkOnMP / 100f) + (pMag * sIMagOnMP / 100f) + specialData.MPDamageValue); //TPダメージ量を計算する int sIAtkOnTP = specialData.attackInfluenceOnTP; int sIMagOnTP = specialData.attackInfluenceOnTP; int tpPoint = (int)((pAtk * sIAtkOnTP / 100f) + (pMag * sIMagOnTP / 100f) + specialData.TPDamageValue); battleManager.enemysList[i].hp -= hpPoint; battleManager.enemysList[i].mp -= mpPoint; battleManager.enemysList[i].tp -= tpPoint; bool wasEffecitveSpecial = false; if (battleManager.enemysList[i].hp < 0) battleManager.enemysList[i].hp = 0; if (battleManager.enemysList[i].mp < 0) battleManager.enemysList[i].mp = 0; if (battleManager.enemysList[i].tp < 0) battleManager.enemysList[i].tp = 0; if (hpPoint > 0) { battleManager.enemysList[i].transform.DOShakePosition(0.3f, 0.5f, 20, 0, false, true); DialogTextManager.instance.SetScenarios(new string[] { battleManager.enemysList[i].name + "に" + hpPoint + "のダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (mpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { battleManager.enemysList[i].name + "に" + mpPoint + "のMPダメージ!" }); SoundManager.instance.PlaySE(15); yield return new WaitForSeconds(1.2f); wasEffecitveSpecial = true; } if (tpPoint > 0) { DialogTextManager.instance.SetScenarios(new string[] { battleManager.enemysList[i].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[] { battleManager.enemysList[i].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); } battleManager.enemysList[i].gameObject.GetComponent<EnemyUIManager>().UpdateUI(battleManager.enemysList[i]); } else//攻撃が命中しなかった場合 { DialogTextManager.instance.SetScenarios(new string[] { player.pname + "の攻撃は外れた" }); yield return new WaitForSeconds(1.2f); } } } } else { //攻撃特技のダメージ量を計算する((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; enemy_grobal.CalcBattleStatusValues();//敵の戦闘時ステータスを計算する int eDef = enemy_grobal.baseStatusValue[GeneralEnum.STATUS.DEF]; //New int eMdef = enemy_grobal.baseStatusValue[GeneralEnum.STATUS.MAGDEF]; //New //攻撃側の値を計算する int hpAtkValue = (int)((pAtk * sIAtk / 100f) + (pAgi * sIAgi / 100f) + (pMag * sIMag / 100f) + (pDef * sIDef / 100f) + (pMdef * sIMDef / 100f) + (pLuk * sLuk / 100f) + (pLearn * sLearn / 100f) + specialData.HPDamageValue); //New //防御側の値を計算する(防御力がダメージを減らす割合は基本25%) _ = (int)(eMdef * specialData.thingE_MDEFRate / 100f);//特技の魔法防御反映率処理 New int hpDefValue = (int)((eDef / 4f) + (eMdef)); hpDefValue -= (int)(hpDefValue * (specialData.penetrationRate / 100f));//貫通率処理 New int hpPoint = hpAtkValue - hpDefValue; //New if (PlayerCheckCritical(enemy_grobal)) hpPoint *= 2 ; //New if (hpPoint < 1) hpPoint = 1;//最低ダメージ1 //MPダメージ量を計算する int sIAtkOnMP = specialData.attackInfluenceOnMP; int sIMagOnMP = specialData.attackInfluenceOnMP; int mpPoint = (int)((pAtk * sIAtkOnMP / 100f) + (pMag * sIMagOnMP / 100f) + specialData.MPDamageValue); //TPダメージ量を計算する int sIAtkOnTP = specialData.attackInfluenceOnTP; int sIMagOnTP = specialData.attackInfluenceOnTP; int tpPoint = (int)((pAtk * sIAtkOnTP / 100f) + (pMag * sIMagOnTP / 100f) + specialData.TPDamageValue); enemy_grobal.hp -= hpPoint; enemy_grobal.mp -= mpPoint; enemy_grobal.tp -= tpPoint; bool wasEffecitveSpecial = false; if (enemy_grobal.hp < 0) enemy_grobal.hp = 0; if (enemy_grobal.mp < 0) enemy_grobal.mp = 0; if (enemy_grobal.tp < 0) enemy_grobal.tp = 0; if (hpPoint > 0) { enemy_grobal.transform.DOShakePosition(0.3f, 0.5f, 20, 0, false, true);//New 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); } enemy_grobal.gameObject.GetComponent<EnemyUIManager>().UpdateUI(enemy_grobal); } //TPを消費する player.tp -= specialData.useTpValue; useSpecialMessagePanel.SetActive(false); playerUIManager.UpdateUI(PlayerManager.instance); 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; }
ついでに貫通率,魔法防御率を反映するようにしておきました。
全体攻撃の場合は、敵全てが生存しているかどうかを調べたいので、BattleManagerの敵を倒したかどうかを判定している箇所の処理を変更します。
クリックで展開
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()); break; case BATTLEACTIONTYPE.ESCAPE: //逃げるの場合 break; } //----------敵を倒した時の処理--------------- for(int i = 0; i < 3; i++) { if (enemysList.ContainsKey(i)) { if (enemysList[i].hp <= 0) { yield return StartCoroutine(EnemyDeath(i)); } } } if (CheckAllEnemyDeath()) { yield return StartCoroutine(EndBattle()); }
PlayEffect.csに全体攻撃用のアニメーション再生関数を作成します。
クリックで展開
public GameObject playAllEffectPoint; public IEnumerator IEPlaySpecialEffect(Vector3 playPos, SpecialData specialData) { GameObject effectObject = Instantiate(specialData.spAnimation, playPos, Quaternion.identity); while (!effectObject.GetComponent<ParticleSystem>().isStopped) { yield return new WaitForSeconds(0.1f); } Destroy(effectObject); }
これで全体攻撃のときは敵の真ん中らへんにエフェクトを再生するようにします。実際に全体攻撃の特技を作成して戦闘中に使ってテストします。
次回は複数回敵を攻撃できる特技を実装したいと思います。
【Unity】RPG制作 その30- 特技使用時のアニメーション再生
アニメーションを実装するにあたって、こちらのアセットを使用します。
それからぴぽや倉庫様、moyasi戦闘エフェクト館様からも戦闘エフェクトをお借りします。
SpecialData.csに再生するアニメーションを入れる公開変数を宣言します
itemDataにも作っておきます。
アニメーション再生クラスPlayEffectクラスを作成します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayEffect : MonoBehaviour { public IEnumerator IEPlaySpecialEffect(Vector3 playPos, SpecialData specialData) { GameObject effectObject = Instantiate(specialData.spAnimation, playPos, Quaternion.identity); while (!effectObject.GetComponent<ParticleSystem>().isStopped) { yield return new WaitForSeconds(0.1f); } Destroy(effectObject); } public IEnumerator IEPlayItemEffect(Vector3 playPos, ItemData itemData) { GameObject effectObject = Instantiate(itemData.itemAnimation, playPos, Quaternion.identity); while (!effectObject.GetComponent<ParticleSystem>().isStopped) { yield return new WaitForSeconds(0.1f); } Destroy(effectObject); } }
SpecialEventクラスのIEUseAttackSpecialコルーチンにアニメーション再生の処理を追加します。
クリックで展開
DialogTextManager.instance.SetScenarios(new string[] { player.pname + specialData.useMessage_Battle }); yield return new WaitForSeconds(1.5f); //SEの再生 if (specialData.UseSEID != -1) { SoundManager.instance.PlaySE(specialData.UseSEID); } //アニメーションの再生 if (specialData.spAnimation != null) //アニメーションが設定されていたら New { PlayEffect playEffect = new PlayEffect(); yield return StartCoroutine(playEffect.IEPlaySpecialEffect(enemy_grobal.transform.position,specialData)); } //-------------------------------以下省略---------------------
ItemEventクラスにも処理を追加します。
クリックで展開
DialogTextManager.instance.SetScenarios(new string[] { player.pname + "は" + itemData.itemName + "を使った!" }); yield return new WaitForSeconds(1.5f); if(itemData.UseSEID != -1) { SoundManager.instance.PlaySE(itemData.UseSEID);//アイテム使用SE } //アニメーションの再生 if (itemData.itemAnimation != null) //New { PlayEffect playEffect = new PlayEffect(); yield return StartCoroutine(playEffect.IEPlayItemEffect(enemy_grobal.transform.position, itemData)); } //--------------------------以下省略---------------------------
戦闘エフェクトをテストするUIを作成します。以下の画像のように作成しました。
この画面を制御するコードをDebugUI.csに記述します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; //New public class DebugUI : MonoBehaviour { public Text testEffectText; //New public Text spDataText; //New public Button effectPlayButton; //New public Button effectRButton; //New public Button effectLButton; //New public Transform PlayEffectPoint; //New int spID = 0; //アニメーションを再生する特技のID void Start() { gameObject.SetActive(false); UpdateSpEffectText(); //New } public void ShowDebugUI() { gameObject.SetActive(true); } public void CloseDebugUI() { gameObject.SetActive(false); } public void ProhibitEffectButtons()//New { effectPlayButton.interactable = false; effectRButton.interactable = false; effectLButton.interactable = false; } public void AllowEffectButton()//New { effectPlayButton.interactable = true; effectRButton.interactable = true; effectLButton.interactable = true; } public void PushEffectPlayButton() //New { StartCoroutine(IEPushEffectPlayButton()); } public IEnumerator IEPushEffectPlayButton() //New { ProhibitEffectButtons(); SpecialData specialData = SpecialManager.instance.specialDatas[spID]; if (specialData.spAnimation != null) //アニメーションが設定されていたら { PlayEffect playEffect = new PlayEffect(); yield return StartCoroutine(playEffect.IEPlaySpecialEffect(PlayEffectPoint.position, specialData)); } else { SoundManager.instance.PlaySE(11); } AllowEffectButton(); } public void PushEffectRButton() //New { spID++; spID %= SpecialManager.instance.specialDatas.Length; UpdateSpEffectText(); } public void PushEffectLButton() //New { spID--; if(spID <= -1) spID = SpecialManager.instance.specialDatas.Length-1; UpdateSpEffectText(); } public void UpdateSpEffectText() //New { int maxSpdata = SpecialManager.instance.specialDatas.Length - 1; string spName = SpecialManager.instance.specialDatas[spID].specialName; spDataText.text = "特技ID " + spID + "/" + maxSpdata + " " + spName; } }
これで戦闘エフェクトを再生できるようになりました。
次回は特技の全体攻撃などを実装していきたいと思います。
【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の関数設定をして実際に戦闘してみます。
探索イベント関連で少しバグがありますが動作しました。
次回は特技使用時のアニメーション再生を実装したいと思います。
【Unity】RPG制作 その28-戦闘時の能力値処理実装
今回は戦闘時の能力値周りの処理を実装していきます。PlayerManager.csに戦闘時に実際に参照される能力値を保持するDictionaryを新しく作成します。
クリックで展開
public Dictionary<GeneralEnum.STATUS, int> battleStatusValues = new Dictionary<GeneralEnum.STATUS, int>(); //戦闘で実際に参照される能力値のDictionary。//New public Dictionary<GeneralEnum.ELEMENT, int> battleResistanceOfElementValues = new Dictionary<GeneralEnum.ELEMENT, int>(); //戦闘で実際に参照される属性有効率のDictionry new public Dictionary<GeneralEnum.STATUSCONDITION, int> battleResistanceOfStatusValues = new Dictionary<GeneralEnum.STATUSCONDITION, int>(); //戦闘で実際に参照される状態異常有効率のDictionary new
これらのDictionaryの初期化関数を作成します。
クリックで展開
public void InitBattleDictionary() { foreach (GeneralEnum.STATUS value in Enum.GetValues(typeof(GeneralEnum.STATUS))) { if (value != GeneralEnum.STATUS.NONE) { battleStatusValues[value] = afterEquipStatusValue[value];//装備反映後の値で初期化 } } foreach (GeneralEnum.ELEMENT value in Enum.GetValues(typeof(GeneralEnum.ELEMENT))) { battleResistanceOfElementValues[value] = afEqResistanceOfElementValue[value]; } foreach (GeneralEnum.STATUSCONDITION value in Enum.GetValues(typeof(GeneralEnum.STATUSCONDITION))) { battleResistanceOfStatusValues[value] = afEqResistanceOfStatusValue[value]; } }
EnemyManager.csにも同様の記述をします。
クリックで展開
public Dictionary<GeneralEnum.STATUS, int> baseStatusValue = new Dictionary<GeneralEnum.STATUS, int>(); //基本能力値Dictionary。New public Dictionary<GeneralEnum.STATUS, int> battleStatusValues = new Dictionary<GeneralEnum.STATUS, int>(); //戦闘で実際に参照される能力値のDictionary。New public Dictionary<GeneralEnum.ELEMENT, int> baseResistanceOfElementValue = new Dictionary<GeneralEnum.ELEMENT, int>(); //属性耐性の数値(100が通常) New public Dictionary<GeneralEnum.ELEMENT, int> battleResistanceOfElementValues = new Dictionary<GeneralEnum.ELEMENT, int>(); //戦闘で実際に参照される属性有効率のDictionry new public Dictionary<GeneralEnum.STATUSCONDITION, int> ResistanceOfStatusValue = new Dictionary<GeneralEnum.STATUSCONDITION, int>(); //状態変化のかかりやすさ(100が通常) New public Dictionary<GeneralEnum.STATUSCONDITION, int> battleResistanceOfStatusValues = new Dictionary<GeneralEnum.STATUSCONDITION, int>(); //戦闘で実際に参照される状態異常有効率のDictionary New private void Start() { battleManager = GameObject.Find("BattleManager").GetComponent<BattleManager>(); hp = maxHp; mp = maxMp; tp = UnityEngine.Random.Range(0, 51);//敵のtpの初期値を0~50にする InitResistanceValueOfElement(); //New InitResistanceValueOfStatusCondition(); //New InitStatusCondi(); InitStatusUp(); InitStatusDown(); InitBaseStatusValue(); //New InitBattleDictionary();//New } public void InitResistanceValueOfElement() //New { foreach (GeneralEnum.ELEMENT value in Enum.GetValues(typeof(GeneralEnum.ELEMENT))) { baseResistanceOfElementValue[value] = 100; } } public void InitResistanceValueOfStatusCondition() //New { foreach (GeneralEnum.STATUSCONDITION value in Enum.GetValues(typeof(GeneralEnum.STATUSCONDITION))) { ResistanceOfStatusValue[value] = 100; } } public void InitBaseStatusValue() //New { baseStatusValue[GeneralEnum.STATUS.HP] = maxHp; baseStatusValue[GeneralEnum.STATUS.MP] = maxMp; baseStatusValue[GeneralEnum.STATUS.ATK] = at; baseStatusValue[GeneralEnum.STATUS.DEF] = def; baseStatusValue[GeneralEnum.STATUS.AGI] = agi; baseStatusValue[GeneralEnum.STATUS.LUK] = luk; baseStatusValue[GeneralEnum.STATUS.SENCE] = sence; baseStatusValue[GeneralEnum.STATUS.MAGPOW] = magPow; baseStatusValue[GeneralEnum.STATUS.MAGDEF] = magDef; baseStatusValue[GeneralEnum.STATUS.LEARNABI] = learnAbi; baseStatusValue[GeneralEnum.STATUS.TP] = maxTp; baseStatusValue[GeneralEnum.STATUS.HIT] = hitRate; baseStatusValue[GeneralEnum.STATUS.EVASION] = evasionRate; baseStatusValue[GeneralEnum.STATUS.CRITICAL] = criticalRate; } public void InitBattleDictionary() //New { foreach (GeneralEnum.STATUS value in Enum.GetValues(typeof(GeneralEnum.STATUS))) { if (value != GeneralEnum.STATUS.NONE) { battleStatusValues[value] = baseStatusValue[value];//装備反映後の値で初期化 } } foreach (GeneralEnum.ELEMENT value in Enum.GetValues(typeof(GeneralEnum.ELEMENT))) { battleResistanceOfElementValues[value] = baseResistanceOfElementValue[value]; } foreach (GeneralEnum.STATUSCONDITION value in Enum.GetValues(typeof(GeneralEnum.STATUSCONDITION))) { battleResistanceOfStatusValues[value] = ResistanceOfStatusValue[value]; } }
battleStatusValueディクショナリの値をセットする関数を作成します。
クリックで展開
public void CalcBattleStatusValues() { foreach (GeneralEnum.STATUS value in Enum.GetValues(typeof(GeneralEnum.STATUS))) { if (value != GeneralEnum.STATUS.NONE) { if(statusUpWithLastTurn[value] > 0) { battleStatusValues[value] = (int)(baseStatusValue[value] * statusUpRate[value] / 100f); } } } }
クリックで展開
public void CalcBattleStatusValues() { foreach (GeneralEnum.STATUS value in Enum.GetValues(typeof(GeneralEnum.STATUS))) { if (value != GeneralEnum.STATUS.NONE) { if (statusUpWithLastTurn[value] > 0) { battleStatusValues[value] = (int)(baseStatusValue[value] * statusUpRate[value] / 100f); } } } }
Attack関数を戦闘時能力値を参照するようにします。
クリックで展開
public int Attack(EnemyManager enemy, bool isCritical)//変更 { CalcBattleStatusValues();//戦闘時ステータスを計算する New enemy.CalcBattleStatusValues();//敵も New //プレイヤー攻撃力とエネミー防御力を取得する int atkValue = battleStatusValues[GeneralEnum.STATUS.ATK]; int defValue = enemy.battleStatusValues[GeneralEnum.STATUS.DEF]; float calcDamage = atkValue - defValue / 4f;//プレイヤーの攻撃力-(エネミーの防御力/4) calcDamage = calcDamage * UnityEngine.Random.Range(1.0f - 0.2f, 1.0f + 0.2f);//ダメージに-20%から+20%の幅をもたせる if (isCritical) calcDamage *= 2; int damage = enemy.Damage((int)calcDamage);//計算した値をenemyのダメージ関数に渡す return damage; } //魔法攻撃の場合に呼び出す攻撃関数 public int CalcAttackForMagic(EnemyManager enemy, bool isCritical)//New { CalcBattleStatusValues();//戦闘時ステータスを計算する New enemy.CalcBattleStatusValues();//敵も New //プレイヤー魔力とエネミー魔法防御力を取得する int atkValue = battleStatusValues[GeneralEnum.STATUS.MAGPOW]; int defValue = enemy.battleStatusValues[GeneralEnum.STATUS.MAGDEF]; float calcDamage = atkValue - defValue / 4f;//プレイヤーの攻撃力-(エネミーの防御力/4) calcDamage = calcDamage * UnityEngine.Random.Range(1.0f - 0.2f, 1.0f + 0.2f);//ダメージに-20%から+20%の幅をもたせる if (isCritical) calcDamage *= 2; int damage = enemy.Damage((int)calcDamage);//計算した値をenemyのダメージ関数に渡す return damage; }
クリックで展開
//攻撃する public int Attack(PlayerManager player, bool isCritical) { CalcBattleStatusValues();//戦闘時ステータスを計算する New player.CalcBattleStatusValues();//プレイヤー側も計算 New //プレイヤー魔力とエネミー魔法防御力を取得する int atkValue = battleStatusValues[GeneralEnum.STATUS.ATK];//New int defValue = player.battleStatusValues[GeneralEnum.STATUS.DEF];//New float calcDamage = atkValue - defValue / 4f;//エネミーの攻撃力-(プレイヤーの防御力/4) calcDamage = calcDamage * UnityEngine.Random.Range(1.0f - 0.2f, 1.0f + 0.2f);//ダメージに-20%から+20%の幅をもたせる if (isCritical) calcDamage *= 2; int damage = player.Damage((int)calcDamage);//計算した値をplayerのダメージ関数に渡す return damage; } //魔法攻撃の場合に呼び出す攻撃関数 public int CalcAttackForMagic(PlayerManager player, bool isCritical)//New { CalcBattleStatusValues();//戦闘時ステータスを計算する New player.CalcBattleStatusValues();//敵も New //プレイヤー魔力とエネミー魔法防御力を取得する int atkValue = battleStatusValues[GeneralEnum.STATUS.MAGPOW]; int defValue = player.battleStatusValues[GeneralEnum.STATUS.MAGDEF]; float calcDamage = atkValue - defValue / 4f;//プレイヤーの攻撃力-(エネミーの防御力/4) calcDamage = calcDamage * UnityEngine.Random.Range(1.0f - 0.2f, 1.0f + 0.2f);//ダメージに-20%から+20%の幅をもたせる if (isCritical) calcDamage *= 2; int damage = player.Damage((int)calcDamage);//計算した値をenemyのダメージ関数に渡す return damage; }
BattleManagerで能力値を参照している処理をすべて書き直します。
クリックで展開
public void CalcAttackOrder() //変更 { Debug.Log("行動順の計算"); AgiDic.Clear(); //念の為行動順を格納する前にAgiDicの要素全消去 player.CalcBattleStatusValues(); AgiDic[0] = player.battleStatusValues[GeneralEnum.STATUS.AGI]; //0番 プレイヤー for(int i = 0;i < 3; i++) { if (enemysList.ContainsKey(i)) { enemysList[i].CalcBattleStatusValues();//バトル時ステータス計算 int enemyAgiValue = enemysList[i].battleStatusValues[GeneralEnum.STATUS.AGI]; AgiDic[i + 1] = enemyAgiValue + (int)(enemyAgiValue * (UnityEngine.Random.Range(-0.3f, 0.3f)));//1番 enemysID0の敵 } } Debug.Log("速さのリストを表示"); Debug.Log("playerの速さ" + AgiDic[0]); for(int i = 0; i < 3; i++) { if (enemysList.ContainsKey(i)) { Debug.Log("enemyindex" + i + "の速さ" + AgiDic[i + 1]); } } } public bool PlayerCheckCritical(int enemyIndex) //変更 { player.CalcBattleStatusValues(); enemysList[enemyIndex].CalcBattleStatusValues(); int calcCriticalRate; int pCriticalRate = player.battleStatusValues[GeneralEnum.STATUS.CRITICAL]; int pHitRate = player.battleStatusValues[GeneralEnum.STATUS.HIT]; int pLuk = player.battleStatusValues[GeneralEnum.STATUS.LUK]; int eEvasionRate = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.EVASION]; int eLuk = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.LUK]; calcCriticalRate = (int)((pCriticalRate + (pHitRate / 10.0f) + (pLuk / 10.0f)) - ((eEvasionRate / 30.0f) + (eLuk / 20.0f))); if (calcCriticalRate >= UnityEngine.Random.Range(1, 101)) { return true; } else { return false; } } public bool EnemyCheckCritical(int enemyIndex) //変更 { player.CalcBattleStatusValues(); enemysList[enemyIndex].CalcBattleStatusValues(); int calcCriticalRate; int eCriticalRate = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.CRITICAL]; int eLuk = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.LUK]; int pEvasionRate = player.battleStatusValues[GeneralEnum.STATUS.EVASION]; int pLuk = player.battleStatusValues[GeneralEnum.STATUS.LUK]; calcCriticalRate = (int)((eCriticalRate + (eLuk / 10.0f)) - ((pEvasionRate / 30.0f) + (pLuk / 20.0f))); if (calcCriticalRate >= UnityEngine.Random.Range(1, 101)) { return true; } else { return false; } } public bool PlayerCheckHitAttack(int enemyIndex) //変更 { player.CalcBattleStatusValues(); enemysList[enemyIndex].CalcBattleStatusValues(); int calcHitRate; int pHitRate = player.battleStatusValues[GeneralEnum.STATUS.HIT]; int pSence = player.battleStatusValues[GeneralEnum.STATUS.SENCE]; int pLuk = player.battleStatusValues[GeneralEnum.STATUS.LUK]; int eEvasionRate = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.EVASION]; int eAgi = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.AGI]; int eLuk = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.LUK]; calcHitRate = (int)((pHitRate + (pSence / 10.0f) + (pLuk / 50.0f)) - (eEvasionRate + (eAgi / 10.0f) + (eLuk / 20.0f))); if (calcHitRate >= UnityEngine.Random.Range(1, 101)) { return true; } else { return false; } } public bool EnemyCheckHitAttack(int enemyIndex) //New { player.CalcBattleStatusValues(); enemysList[enemyIndex].CalcBattleStatusValues(); int calcHitRate; int eHitRate = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.HIT]; int eAgi = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.AGI]; int eLuk = enemysList[enemyIndex].battleStatusValues[GeneralEnum.STATUS.LUK]; int pEvasionRate = player.battleStatusValues[GeneralEnum.STATUS.EVASION]; int pAgi = player.battleStatusValues[GeneralEnum.STATUS.AGI]; int pLuk = player.battleStatusValues[GeneralEnum.STATUS.LUK]; calcHitRate = (int)((eHitRate + (eAgi / 10.0f) + (eLuk / 50.0f)) - (pEvasionRate + (pAgi / 10.0f) + (pLuk / 20.0f))); if (calcHitRate >= UnityEngine.Random.Range(1, 101)) { return true; } else { return false; } }
これで戦闘時に使用するディクショナリの実装ができました。次回は特技の実装をやっていきたいと思います。
【Unity】RPG制作 その27-プレイヤーの属性耐性値・状態異常のかかりやすさの値の確認画面作成
今回はプレイヤーの属性耐性値・状態異常のかかりやすさの値を確認できる画面を作成していきたいと思います。これらの画面はプレイヤーのステータス画面で表示させたいので、画面を切り替えるためのボタンをPlayerStatusUICanvas内に配置します。
属性耐性値を表示するUIを作成していきます。とりあえずテキストで属性耐性値を出力したいので以下の画像のように作成します。
今回、属性耐性値をレーダーグラフで表示させたいので、以下のサイトを参考にしながらレーダーグラフを作っていきます。
https://blog.naichilab.com/entry/radarchart
レーダーグラフを描画するのに必要なクラスを2つ作成します。クラス名はRadarChartPolygonUGUIクラスとRadarChartLineUGUIクラスです。それぞれ以下のように記述します。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System; namespace naichilab { /// <summary> /// レーダーチャートのポリゴンを描画 /// </summary> public class RadarChartPolygonUGUI : Graphic { /// <summary> /// 描画半径 /// </summary> const float RADIUS = 0.5f; [Header("General")] [SerializeField] [Range(3, 30)] private int VerticesCount = 5; [SerializeField] [Range(0f, 1f)] private float MaxVolume = 1f; [SerializeField] private float[] Volumes; private void SetVolume(int idx, float value) { if (this.Volumes.Length < idx) { Array.Resize(ref this.Volumes, idx + 1); } this.Volumes[idx] = value; } private float GetVolume(int idx) { if (Volumes.Length - 1 < idx) { return 0; } float v = this.Volumes[idx]; return v > this.MaxVolume ? this.MaxVolume : v; } protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); var v = UIVertex.simpleVert; v.color = color; Vector2 center = CreatePos(0.5f, 0.5f); v.position = center; vh.AddVert(v); //各頂点座標 for (int i = 1; i <= VerticesCount; i++) { float rad = (90f - (360f / (float)VerticesCount) * (i - 1)) * Mathf.Deg2Rad; float x = 0.5f + Mathf.Cos(rad) * RADIUS * GetVolume(i - 1); float y = 0.5f + Mathf.Sin(rad) * RADIUS * GetVolume(i - 1); Vector2 p = CreatePos(x, y); v.position = p; vh.AddVert(v); vh.AddTriangle( 0, i, i == VerticesCount ? 1 : i + 1 ); } } private Vector2 CreatePos(float x, float y) { Vector2 p = Vector2.zero; p.x -= rectTransform.pivot.x; p.y -= rectTransform.pivot.y; p.x += x; p.y += y; p.x *= rectTransform.rect.width; p.y *= rectTransform.rect.height; return p; } } }
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace naichilab { /// <summary> /// レーダーチャートの罫線を描画 /// </summary> public class RadarChartLineUGUI : Graphic { /// <summary> /// 描画半径 /// </summary> const float RADIUS = 0.5f; [Header("General")] [SerializeField] [Range(3, 30)] private int VerticesCount = 5; [SerializeField] [Range(0f, 1f)] private float MaxVolume = 1f; [SerializeField] [Tooltip("線の太さ")] [Range(0.001f, 0.03f)] private float LineWidth = 0.02f; [Header("Major Grid")] [SerializeField] [Tooltip("主罫線を表示するかどうか")] private bool DrawMajorGrid = true; [SerializeField] [Range(0.01f, 1f)] [Tooltip("主罫線の間隔")] private float MajorGridInterval = 0.2f; protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); if (this.MaxVolume == 0) return; var v = UIVertex.simpleVert; v.color = color; //Outer Frame this.DrawFrame(vh, this.MaxVolume); //Axis this.DrawAxis(vh, this.MaxVolume); //Major Grid if (this.DrawMajorGrid && this.MajorGridInterval < this.MaxVolume) { int numOfGrid = (int)(this.MaxVolume / this.MajorGridInterval); for (int i = 1; i <= numOfGrid; i++) { this.DrawFrame(vh, i * this.MajorGridInterval); } } } /// <summary> /// uGUI座標を作成 /// </summary> private Vector2 CreatePos(float x, float y) { Vector2 p = Vector2.zero; p.x -= rectTransform.pivot.x; p.y -= rectTransform.pivot.y; p.x += x; p.y += y; p.x *= rectTransform.rect.width; p.y *= rectTransform.rect.height; return p; } /// <summary> /// 外周を描画 /// </summary> private void DrawFrame(VertexHelper vh, float vol) { int currentVertCount = vh.currentVertCount; var v = UIVertex.simpleVert; v.color = color; //各頂点座標 for (int i = 0; i < VerticesCount; i++) { float deg = (360f / VerticesCount) * 0.5f; float offset = (this.LineWidth / Mathf.Cos(deg * Mathf.Deg2Rad)) / 2f; float rad = (90f - (360f / (float)VerticesCount) * i) * Mathf.Deg2Rad; float x1 = 0.5f + Mathf.Cos(rad) * (RADIUS * vol - offset); float y1 = 0.5f + Mathf.Sin(rad) * (RADIUS * vol - offset); float x2 = 0.5f + Mathf.Cos(rad) * (RADIUS * vol + offset); float y2 = 0.5f + Mathf.Sin(rad) * (RADIUS * vol + offset); Vector2 p1 = CreatePos(x1, y1); Vector2 p2 = CreatePos(x2, y2); v.position = p1; vh.AddVert(v); v.position = p2; vh.AddVert(v); vh.AddTriangle( (((i + 0) * 2) + 0) % (VerticesCount * 2) + currentVertCount, (((i + 0) * 2) + 1) % (VerticesCount * 2) + currentVertCount, (((i + 1) * 2) + 0) % (VerticesCount * 2) + currentVertCount ); vh.AddTriangle( (((i + 1) * 2) + 0) % (VerticesCount * 2) + currentVertCount, (((i + 0) * 2) + 1) % (VerticesCount * 2) + currentVertCount, (((i + 1) * 2) + 1) % (VerticesCount * 2) + currentVertCount ); } } /// <summary> /// 軸を描画 /// </summary> private void DrawAxis(VertexHelper vh, float vol) { int currentVertCount = vh.currentVertCount; var v = UIVertex.simpleVert; v.color = color; for (int i = 0; i < VerticesCount; i++) { float halfWidthDeg = 90 * this.LineWidth / (Mathf.PI * RADIUS * vol); float rad1 = (90f - halfWidthDeg - (360f / (float)VerticesCount) * i) * Mathf.Deg2Rad; float rad2 = (90f + halfWidthDeg - (360f / (float)VerticesCount) * i) * Mathf.Deg2Rad; float x3 = 0.5f + Mathf.Cos(rad1) * RADIUS * vol; float y3 = 0.5f + Mathf.Sin(rad1) * RADIUS * vol; float x4 = 0.5f + Mathf.Cos(rad2) * RADIUS * vol; float y4 = 0.5f + Mathf.Sin(rad2) * RADIUS * vol; float x1 = 0.5f + (x3 - x4) / 2f; float y1 = 0.5f + (y3 - y4) / 2f; float x2 = 0.5f + (x4 - x3) / 2f; float y2 = 0.5f + (y4 - y3) / 2f; Vector2 p1 = CreatePos(x1, y1); Vector2 p2 = CreatePos(x2, y2); Vector2 p3 = CreatePos(x3, y3); Vector2 p4 = CreatePos(x4, y4); v.position = p1; vh.AddVert(v); v.position = p2; vh.AddVert(v); v.position = p3; vh.AddVert(v); v.position = p4; vh.AddVert(v); vh.AddTriangle( ((i * 4) + 0) + currentVertCount, ((i * 4) + 3) + currentVertCount, ((i * 4) + 2) + currentVertCount ); vh.AddTriangle( ((i * 4) + 0) + currentVertCount, ((i * 4) + 1) + currentVertCount, ((i * 4) + 3) + currentVertCount ); } } } }
属性耐性値を表示するパネルRegiElementListオブジェクトの階層下にPanelを新規作成し、Panelの階層下に新規のオブジェクトを2つ作成し、名前をRadarChartPolygonUGUI,RadarChartLineUGUIにし、同名のスクリプトを貼り付けます。
グラフの値や線の太さなどを適当に調整し、アイコンを配置して外見を作ります。
同様にして状態異常有効率表も作りました。
それぞれの表を制御するコードをPlayerStatusUI.csに記述していきます。
クリックで展開
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using naichilab;//new public class PlayerStatusUI : MonoBehaviour { public GameObject StatusList;//New public GameObject RegiElementList; //New public GameObject RegiCondiList; //New public Button RButton; //New public Button LButton; //New public RadarChartPolygonUGUI elementRadarChart;//New public RadarChartPolygonUGUI condiRadarChart;//New //--------------New------------------------- //--------ステータス表で表示するテキスト--------- public Text nameText; public Text hpText; public Text mpText; public Text tpText; public Text atkText; public Text defText; public Text agiText; public Text lukText; public Text senceText; public Text magpowText; public Text magdefText; public Text learnAbiText; //-------属性有効率表で表示するテキスト----------- public Text normalText; public Text fireText; public Text windText; public Text groundText; public Text thunderText; public Text aquaText; public Text iceText; public Text lightText; public Text darkText; public Text dragonText; public Text soundText; public Text starText; public Text allText; //--------------------------------------------- //------状態異常有効率表で表示するテキスト-------- public Text poisonText; public Text blindText; public Text paralysisText; public Text sleepText; public Text confusionText; public Text burnText; public Text frozenText; public Text wetText; //------------------------------------------- //--------------------Newここまで---------------------- public enum ListType //New { STATUS,//ステータス表 REGIELEMENT,//属性有効率表 REGICONDI,//状態抵抗値表 } ListType nowList = ListType.STATUS;//現在表示しているリストのタイプ public void Start() { RegiElementList.SetActive(false); //New RegiCondiList.SetActive(false); //New this.gameObject.SetActive(false); } public void SetStatusText() { nameText.text = "名前 " + PlayerManager.instance.pname; hpText.text = "HP " + PlayerManager.instance.hp + " / " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.HP] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.HP] + ")"; mpText.text = "MP " + PlayerManager.instance.mp + " / " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.MP] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.MP] + ")"; tpText.text = "TP " + PlayerManager.instance.tp; atkText.text = "攻撃 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.ATK] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.ATK] + ")"; defText.text = "防御 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.DEF] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.DEF] + ")"; agiText.text = "速さ " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.AGI] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.AGI] + ")"; lukText.text = "運 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.LUK] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.LUK] + ")"; senceText.text = "感覚 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.SENCE] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.SENCE] + ")"; magpowText.text = "魔力 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.MAGPOW] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.MAGPOW] + ")"; magdefText.text = "魔防 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.MAGDEF] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.MAGDEF] + ")"; learnAbiText.text = "習得 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.LEARNABI] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.LEARNABI] + ")"; } public void SetElementText() //New { normalText.text = "無 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.NONE]; fireText.text = "火 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.FIRE]; windText.text = "風 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.WIND]; groundText.text = "大地 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.GROUND]; thunderText.text = "雷 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.THUNDER]; aquaText.text = "水 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.AQUA]; iceText.text = "氷 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.ICE]; lightText.text = "光 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.LIGHT]; darkText.text = "闇 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.DARK]; dragonText.text = "龍 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.DRAGON]; soundText.text = "音 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.SOUND]; starText.text = "星 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.STAR]; allText.text = "全 " + PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.ALL]; } public void SetCondiText() //New { poisonText.text = "毒 " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.POISON]; blindText.text = "盲目 " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.BLIND]; paralysisText.text = "麻痺 " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.PARALYSIS]; sleepText.text = "睡眠 " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.SLEEP]; confusionText.text = "混乱 " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.CONFUSION]; burnText.text = "燃焼 " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.BURN]; frozenText.text = "凍結 " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.FROZEN]; wetText.text = "水濡れ " + PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.WET]; } public void ShowStatusUI() //変更 { SoundManager.instance.PlaySE(22); this.gameObject.SetActive(true); switch (nowList) { case ListType.STATUS: ShowStatusList(); break; case ListType.REGIELEMENT: ShowRegiElementList(); break; default: break; } } public void HideStatuUI() { SoundManager.instance.PlaySE(7); this.gameObject.SetActive(false); } public void ShowStatusList() //New { SoundManager.instance.PlaySE(22); SetStatusText(); RegiElementList.gameObject.SetActive(false); RegiCondiList.gameObject.SetActive(false); StatusList.gameObject.SetActive(true); } public void HideStatusList() { SoundManager.instance.PlaySE(7); StatusList.gameObject.SetActive(false); } public void ShowRegiElementList()//New { SoundManager.instance.PlaySE(22); SetElementText(); SetElementRadarGraphValue(); StatusList.gameObject.SetActive(false); RegiCondiList.gameObject.SetActive(false); RegiElementList.gameObject.SetActive(true); } public void HideRegiElementList() //New { SoundManager.instance.PlaySE(7); RegiElementList.gameObject.SetActive(false); } public void ShowRegiCondiList() { SoundManager.instance.PlaySE(22); SetCondiText(); SetCondiRadarGraphValue(); StatusList.gameObject.SetActive(false); RegiElementList.gameObject.SetActive(false); RegiCondiList.gameObject.SetActive(true); } public void PushRButton() //New { switch (nowList) { case ListType.STATUS: ShowRegiElementList(); nowList = ListType.REGIELEMENT; break; case ListType.REGIELEMENT: ShowRegiCondiList(); nowList = ListType.REGICONDI; break; case ListType.REGICONDI: ShowStatusList(); nowList = ListType.STATUS; break; } } public void PushLButton() //New { switch (nowList) { case ListType.STATUS: ShowRegiCondiList(); nowList = ListType.REGICONDI; break; case ListType.REGIELEMENT: ShowStatusList(); nowList = ListType.STATUS; break; case ListType.REGICONDI: ShowRegiElementList(); nowList = ListType.REGIELEMENT; break; } } /// <summary> /// 属性耐性値のグラフの値をセットする /// </summary> public void SetElementRadarGraphValue()//New { int RegiValue; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.NONE]; RegiValue = 400 - RegiValue;//(400が耐性皆無、0が完全な耐性、-100で吸収する) elementRadarChart.Volumes[0] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.FIRE]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[1] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.WIND]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[2] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.GROUND]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[3] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.THUNDER]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[4] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.AQUA]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[5] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.ICE]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[6] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.LIGHT]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[7] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.DARK]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[8] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.DRAGON]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[9] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.SOUND]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[10] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.STAR]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[11] = RegiValue / 500f; RegiValue = PlayerManager.instance.afEqResistanceOfElementValue[GeneralEnum.ELEMENT.ALL]; RegiValue = 400 - RegiValue; elementRadarChart.Volumes[12] = RegiValue / 500f; } /// <summary> /// 状態異常有効率のグラフの値をセットする /// </summary> public void SetCondiRadarGraphValue()//New { int RegiValue; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.POISON]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[0] = RegiValue / 200f; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.BLIND]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[1] = RegiValue / 200f; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.PARALYSIS]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[2] = RegiValue / 200f; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.SLEEP]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[3] = RegiValue / 200f; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.CONFUSION]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[4] = RegiValue / 200f; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.BURN]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[5] = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.BURN] / 200f; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.FROZEN]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[6] = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.FROZEN] / 200f; RegiValue = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.WET]; RegiValue = 200 - RegiValue; condiRadarChart.Volumes[7] = PlayerManager.instance.afEqResistanceOfStatusValue[GeneralEnum.STATUSCONDITION.WET] / 200f; } }
それぞれの表自体のゲームオブジェクトとテキスト、レーダーグラフの値をセットする関数にRButton,LButtonを押した時に表を切り替える処理を記述しました。公開変数とButtonのOnclickに各々の設定をして実行すると以下の動画のようになります。
次回は戦闘中の能力値周りを実装していきます。
【Unity】RPG制作 その26-武器、防具アイテム実装その3 装備による能力値の変化実装
はじめに、PlayerManager.csで基本能力値と装備反映後の値を保持するDictionaryを宣言します。
クリックで展開
public Dictionary<GeneralEnum.STATUS, int> baseStatusValue = new Dictionary<GeneralEnum.STATUS, int>(); //基本能力値Dictionary。 public Dictionary<GeneralEnum.STATUS, int> afterEquipStatusValue = new Dictionary<GeneralEnum.STATUS, int>(); //ステータスUPと残りターンのDictionary。 public Dictionary<GeneralEnum.ELEMENT, int> baseResistanceOfElementValue = new Dictionary<GeneralEnum.ELEMENT, int>(); //属性耐性の数値(100が通常) 名前変更 public Dictionary<GeneralEnum.ELEMENT, int> afEqResistanceOfElementValue = new Dictionary<GeneralEnum.ELEMENT, int>();//装備反映後の属性耐性値 New Dictionary<GeneralEnum.STATUSCONDITION, int> ResistanceOfStatusValue = new Dictionary<GeneralEnum.STATUSCONDITION, int>(); //状態変化のかかりやすさ(100が通常) Dictionary<GeneralEnum.STATUSCONDITION, int> afEqResistanceOfStatusValue = new Dictionary<GeneralEnum.STATUSCONDITION, int>();//装備反映後の状態変化のかかりやすさの値 New
Dictionaryの初期化関数と装備による能力値の変化反映後の値(3つのDictionary)を計算する関数を作成します。
クリックで展開
public void InitBaseStatusValue()//New { baseStatusValue[GeneralEnum.STATUS.HP] = maxHp; baseStatusValue[GeneralEnum.STATUS.MP] = maxMp; baseStatusValue[GeneralEnum.STATUS.ATK] = at; baseStatusValue[GeneralEnum.STATUS.DEF] = def; baseStatusValue[GeneralEnum.STATUS.AGI] = agi; baseStatusValue[GeneralEnum.STATUS.LUK] = luk; baseStatusValue[GeneralEnum.STATUS.SENCE] = sence; baseStatusValue[GeneralEnum.STATUS.MAGPOW] = magPow; baseStatusValue[GeneralEnum.STATUS.MAGDEF] = magDef; baseStatusValue[GeneralEnum.STATUS.LEARNABI] = learnAbi; baseStatusValue[GeneralEnum.STATUS.TP] = maxTp; baseStatusValue[GeneralEnum.STATUS.HIT] = hitRate; baseStatusValue[GeneralEnum.STATUS.EVASION] = evasionRate; baseStatusValue[GeneralEnum.STATUS.CRITICAL] = criticalRate; } /// <summary> /// 装備反映後の属性値と状態異常のかかりやすさの値を初期化する /// </summary> public void InitAfterEquipDictionary() //New { foreach (GeneralEnum.STATUS value in Enum.GetValues(typeof(GeneralEnum.STATUS))) { if(value != GeneralEnum.STATUS.NONE) { afterEquipStatusValue[value] = baseStatusValue[value]; } } foreach (GeneralEnum.ELEMENT value in Enum.GetValues(typeof(GeneralEnum.ELEMENT))) { afEqResistanceOfElementValue[value] = 100;//100で初期化しておく } foreach (GeneralEnum.STATUSCONDITION value in Enum.GetValues(typeof(GeneralEnum.STATUSCONDITION))) { afEqResistanceOfStatusValue[value] = 100;//100で初期化しておく } } /// <summary> /// 能力の装備反映後の能力値を計算する /// </summary> public void CalcAllAfterEquipStatusValue()//New { foreach (GeneralEnum.STATUS value in Enum.GetValues(typeof(GeneralEnum.STATUS))) { if(value != GeneralEnum.STATUS.NONE) { //装備反映後の値 = 基本値 + 各武器の変化値+各防具の変化値 //武器の変化値の合計を計算する int weaponValue = 0; weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].changeStatusValues[value]; weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].changeStatusValues[value]; //防具の変化値の合計を計算する int armorValue = 0; armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].changeStatusValues[value]; armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.BODY].changeStatusValues[value]; armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].changeStatusValues[value]; armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.LEG].changeStatusValues[value]; armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].changeStatusValues[value]; armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].changeStatusValues[value]; afterEquipStatusValue[value] = baseStatusValue[value] + weaponValue + armorValue; if (afterEquipStatusValue[value] < 1) afterEquipStatusValue[value] = 1;//能力の最低値1 } } } public void CalcAllAfterEquipResiOfElementValue() //New { foreach (GeneralEnum.ELEMENT value in Enum.GetValues(typeof(GeneralEnum.ELEMENT))) { //装備反映後の値 = 基本値 - 各武器の属性耐性値 - 各防具の属性耐性値 //武器の属性耐性変化値の合計を計算する int weaponValue = 0; if (equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiElement1 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiValueOfElement1; if (equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiElement2 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiValueOfElement2; if (equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiElement3 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiValueOfElement3; if (equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiElement1 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiValueOfElement1; if (equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiElement2 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiValueOfElement2; if (equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiElement3 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiValueOfElement3; //防具の属性耐性変化値の合計を計算する int armorValue = 0; if (equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiElement1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiValueOfElement1; if (equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiElement2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiValueOfElement2; if (equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiElement3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiValueOfElement3; if (equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiElement1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiValueOfElement1; if (equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiElement2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiValueOfElement2; if (equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiElement3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiValueOfElement3; if (equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiElement1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiValueOfElement1; if (equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiElement2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiValueOfElement2; if (equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiElement3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiValueOfElement3; if (equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiElement1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiValueOfElement1; if (equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiElement2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiValueOfElement2; if (equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiElement3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiValueOfElement3; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiElement1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiValueOfElement1; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiElement2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiValueOfElement2; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiElement3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiValueOfElement3; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiElement1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiValueOfElement1; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiElement2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiValueOfElement2; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiElement3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiValueOfElement3; afEqResistanceOfElementValue[value] = baseResistanceOfElementValue[value] - weaponValue - armorValue; Mathf.Clamp(afEqResistanceOfElementValue[value],-100,400);//属性耐性値の範囲-100~400にする } } /// <summary> /// 装備反映後の状態変化のかかりやすさの値を計算する /// </summary> public void CalcAllAfterEquipResiOfStatusValue()//New { foreach (GeneralEnum.STATUSCONDITION value in Enum.GetValues(typeof(GeneralEnum.STATUSCONDITION))) { //装備反映後の値 = 基本値 - 各武器の値 - 各防具の値 //武器の変化値の合計を計算する int weaponValue = 0; if (equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiStatusCondi1 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiValueOfCondi1; if (equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiStatusCondi2 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiValueOfCondi2; if (equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiStatusCondi3 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].resiValueOfCondi3; if (equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiStatusCondi1 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiValueOfCondi1; if (equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiStatusCondi2 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiValueOfCondi2; if (equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiStatusCondi3 == value) weaponValue += equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].resiValueOfCondi3; //防具の属性耐性変化値の合計を計算する int armorValue = 0; if (equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiStatusCondi1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiValueOfCondi1; if (equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiStatusCondi2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiValueOfCondi2; if (equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiStatusCondi3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.HEAD].resiValueOfCondi3; if (equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiStatusCondi1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiValueOfCondi1; if (equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiStatusCondi2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiValueOfCondi2; if (equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiStatusCondi3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.BODY].resiValueOfCondi3; if (equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiStatusCondi1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiValueOfCondi1; if (equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiStatusCondi2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiValueOfCondi2; if (equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiStatusCondi3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.WEIST].resiValueOfCondi3; if (equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiStatusCondi1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiValueOfCondi1; if (equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiStatusCondi2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiValueOfCondi2; if (equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiStatusCondi3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.LEG].resiValueOfCondi3; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiStatusCondi1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiValueOfCondi1; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiStatusCondi2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiValueOfCondi2; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiStatusCondi3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES1].resiValueOfCondi3; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiStatusCondi1 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiValueOfCondi1; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiStatusCondi2 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiValueOfCondi2; if (equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiStatusCondi3 == value) armorValue += equipArmors[GeneralEnum.EQUIP_SLOT.ACCESSORIES2].resiValueOfCondi3; afEqResistanceOfStatusValue[value] = ResistanceOfStatusValue[value] - weaponValue - armorValue; Mathf.Clamp(afEqResistanceOfStatusValue[value], 0, 200);//状態異常のかかりやすさの値は0~200にする } }
それぞれ武器と防具の能力値の変化量の合計を基本値から引いたものを装備反映後の能力値を入れるDictionaryに入れています。
InitBaseStatusValue関数とInitAfterEquipDictionary関数をPlayerManager.csのStart関数で呼び出します。
クリックで展開
void Start() { InitResistanceValueOfElement(); InitResistanceValueOfStatusCondition(); InitStatusCondi(); InitStatusUp(); InitStatusDown(); InitSkillLevel(); InitSkillExp(); InitEquipWeaponsAndArmor(); InitBaseStatusValue();//New InitAfterEquipDictionary();//New //デバッグ用 SkillLevelDic[GeneralEnum.SKILL.Mining] = 4; SkillLevelDic[GeneralEnum.SKILL.Fishing] = 4; }
装備反映後の能力値の計算を行う3つの関数を装備の変更がなされた時に呼び出すようにします。EquipmentUI.csのPushRemoveEquipButton関数、ChangeWeapon関数、ChangeArmor関数のそれぞれ最後の部分に処理を追加します。
クリックで展開
public void PushRemoveEquipButton(PlayerManager playerManager, GeneralEnum.EQUIP_SLOT equipSlot) { //武器と防具両方のEntityの変数を用意する WeaponEntity tempWeapon; ArmorEntity tempArmor; if (equipSlot == GeneralEnum.EQUIP_SLOT.RIGHTHAND || equipSlot == GeneralEnum.EQUIP_SLOT.LEFTHAND)//右手か左手の場合 { //装備している武器もしくは防具を一時変数に入れる if (playerManager.equipWeapons[equipSlot].nowEquip) { tempWeapon = playerManager.equipWeapons[equipSlot]; tempArmor = new ArmorEntity(); } else if (playerManager.equipArmors[equipSlot].nowEquip) { tempWeapon = new WeaponEntity(); tempArmor = playerManager.equipArmors[equipSlot]; } else { tempWeapon = new WeaponEntity(); tempArmor = new ArmorEntity(); } //装備していた武器・防具の装備中フラグをfalseにする tempWeapon.nowEquip = false; tempArmor.nowEquip = false; //装備部位の装備を削除する playerManager.equipWeapons[equipSlot] = new WeaponEntity(); playerManager.equipArmors[equipSlot] = new ArmorEntity(); //リストに装備していた武器もしくは防具を代入する。 if(tempWeapon.isRegistry) WeaponManager.instance.RegiEntity(tempWeapon); if(tempArmor.isRegistry) ArmorManager.instance.RegiEntity(tempArmor); } else//右手左手以外の場合 { //装備していた防具を一時変数に入れる tempArmor = playerManager.equipArmors[equipSlot]; //装備していた防具の装備中フラグをfalseにする tempArmor.nowEquip = false; //装備部位の装備を削除する playerManager.equipArmors[equipSlot] = new ArmorEntity(); //リストに装備していた防具を代入する。 if (tempArmor.isRegistry) ArmorManager.instance.RegiEntity(tempArmor); } //装備反映後の能力値を再計算する playerManager.CalcAllAfterEquipStatusValue();//New playerManager.CalcAllAfterEquipResiOfElementValue();//New playerManager.CalcAllAfterEquipResiOfStatusValue();//New SoundManager.instance.PlaySE(35); } public void ChangeWeapon(GeneralEnum.EQUIP_SLOT equip_slot,WeaponEntity weaponEntity, PlayerManager playerManager, int index) { WeaponData weaponData = WeaponManager.instance.GetWeaponDataFromEntity(weaponEntity); WeaponData nowEquipRWeaponData = WeaponManager.instance.GetWeaponDataFromEntity(playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND]); WeaponData nowEquipLWeaponData = WeaponManager.instance.GetWeaponDataFromEntity(playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND]); //武器と防具の一時変数を用意する ArmorEntity tempRHandAEntity; ArmorEntity tempLHandAEntity; WeaponEntity tempREntity; WeaponEntity tempLEntity; //右手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//防具装備中なら { tempRHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; tempREntity = new WeaponEntity(); } else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//武器装備中なら { tempRHandAEntity = new ArmorEntity(); tempREntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; } else { tempRHandAEntity = new ArmorEntity(); tempREntity = new WeaponEntity(); } //左手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//防具装備中なら { tempLHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND]; tempLEntity = new WeaponEntity(); } else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//武器装備中なら { tempLHandAEntity = new ArmorEntity(); tempLEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND]; } else { tempLHandAEntity = new ArmorEntity(); tempLEntity = new WeaponEntity(); } if (weaponData.equipPart == GeneralEnum.EQUIP_SLOT.ONEHAND)//新しく装備する武器が片手用なら { if(tempREntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS || tempLEntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS) {//両手武器を装備中なら tempREntity.nowEquip = false; tempLEntity.nowEquip = false; weaponEntity.nowEquip = true; //右手左手のEntityを初期化 playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipWeapons[equip_slot] = weaponEntity;//選択した武器を装備部位に代入する WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); if (tempREntity.isRegistry) WeaponManager.instance.RegiEntity(tempREntity); if (tempLEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLEntity); //装備部位のテキストを反映する UpdateAllWeaponText(playerManager); } else//両手武器を装備していない場合 { if(equip_slot == GeneralEnum.EQUIP_SLOT.RIGHTHAND)//右手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempREntity.nowEquip = false; tempRHandAEntity.nowEquip = false; weaponEntity.nowEquip = true;//今から装備する武器の装備中フラグをtrueにする //右手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new ArmorEntity(); playerManager.equipWeapons[equip_slot] = weaponEntity;//選択した武器を装備部位に代入する。 WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); if (tempREntity.isRegistry) WeaponManager.instance.RegiEntity(tempREntity); if (tempRHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempRHandAEntity); }else if (equip_slot == GeneralEnum.EQUIP_SLOT.LEFTHAND)//左手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempLEntity.nowEquip = false; tempLHandAEntity.nowEquip = false; weaponEntity.nowEquip = true;//今から装備する武器の装備中フラグをtrueにする //左手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new ArmorEntity(); playerManager.equipWeapons[equip_slot] = weaponEntity;//選択した武器を装備部位に代入する。 WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); if (tempLEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLEntity); if (tempLHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempLHandAEntity); } UpdateWeaponText(playerManager,weaponEntity,equip_slot); } }else if (weaponData.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS) {//新しく装備する武器が両手用なら //装備中フラグをfalseに tempREntity.nowEquip = false; tempLEntity.nowEquip = false; tempRHandAEntity.nowEquip = false; tempLHandAEntity.nowEquip = false; weaponEntity.nowEquip = true;//今から装備する武器のフラグをtrueに //右手左手のEntityを削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new ArmorEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new ArmorEntity(); //選択した武器を装備部位に代入する。 playerManager.equipWeapons[equip_slot] = weaponEntity; //選択した武器をリストから削除する WeaponManager.instance.possessionWeapon[index] = new WeaponEntity(); //リストに装備していた武器もしくは防具を代入する。 if (tempREntity.isRegistry) WeaponManager.instance.RegiEntity(tempREntity); if (tempLEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLEntity); if (tempRHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempRHandAEntity); if (tempLHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempLHandAEntity); //装備部位のテキストを反映する UpdateAllWeaponText(playerManager); } //装備反映後の能力値を再計算する playerManager.CalcAllAfterEquipStatusValue();//New playerManager.CalcAllAfterEquipResiOfElementValue();//New playerManager.CalcAllAfterEquipResiOfStatusValue();//New SoundManager.instance.PlaySE(34); } public void ChangeArmor(GeneralEnum.EQUIP_SLOT equip_slot, ArmorEntity armorEntity, PlayerManager playerManager, int index) { //装備部位が右手か左手の場合 if(equip_slot==GeneralEnum.EQUIP_SLOT.RIGHTHAND || equip_slot == GeneralEnum.EQUIP_SLOT.LEFTHAND) { //右手・左手の装備をそれぞれチェックする ArmorEntity tempRHandAEntity; ArmorEntity tempLHandAEntity; WeaponEntity tempRHandWEntity; WeaponEntity tempLHandWEntity; //右手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//防具装備中なら { tempRHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; tempRHandWEntity = new WeaponEntity(); }else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND].nowEquip)//武器装備中なら { tempRHandAEntity = new ArmorEntity(); tempRHandWEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND]; } else { tempRHandAEntity = new ArmorEntity(); tempRHandWEntity = new WeaponEntity(); } //左手からチェック if (playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//防具装備中なら { tempLHandAEntity = playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND]; tempLHandWEntity = new WeaponEntity(); } else if (playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND].nowEquip)//武器装備中なら { tempLHandAEntity = new ArmorEntity(); tempLHandWEntity = playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND]; } else { tempLHandAEntity = new ArmorEntity(); tempLHandWEntity = new WeaponEntity(); } //両手武器を装備していたら if(tempRHandWEntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS || tempLHandWEntity.equipPart == GeneralEnum.EQUIP_SLOT.BOTHHANDS) { tempRHandWEntity.nowEquip = false; tempLHandWEntity.nowEquip = false; armorEntity.nowEquip = true; //右手左手の装備を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[equip_slot] = armorEntity;//選択した防具を装備部位に代入する。 UpdateArmorText(playerManager, playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND], GeneralEnum.EQUIP_SLOT.RIGHTHAND); UpdateArmorText(playerManager, playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND], GeneralEnum.EQUIP_SLOT.LEFTHAND); //選択した防具をリストから削除する ArmorManager.instance.possessionArmor[index] = new ArmorEntity(); //リストに装備していた武器を代入する。(両手武器の場合は武器だけ処理すればいい.isRegistryがfalseなら装備されてない部位) if (tempRHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempRHandWEntity); if (tempLHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLHandWEntity); } else//両手武器を装備していない場合 { if(equip_slot == GeneralEnum.EQUIP_SLOT.RIGHTHAND)//右手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempRHandWEntity.nowEquip = false; tempRHandAEntity.nowEquip = false; armorEntity.nowEquip = true;//今から装備する防具の装備中フラグをtrueにする //右手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.RIGHTHAND] = new ArmorEntity(); playerManager.equipArmors[equip_slot] = armorEntity;//選択した防具を装備部位に代入する。 UpdateArmorText(playerManager, armorEntity, equip_slot); //選択した防具をリストから削除する ArmorManager.instance.possessionArmor[index] = new ArmorEntity(); //リストに装備していた武器もしくは防具を代入する。 if (tempRHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempRHandWEntity); if (tempRHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempRHandAEntity); } else if(equip_slot == GeneralEnum.EQUIP_SLOT.LEFTHAND)//左手の場合 { //装備していた武器・防具の装備中フラグをfalseにする tempLHandWEntity.nowEquip = false; tempLHandAEntity.nowEquip = false; armorEntity.nowEquip = true;//今から装備する防具の装備中フラグをtrueにする //右手の武器・防具を削除する playerManager.equipWeapons[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new WeaponEntity(); playerManager.equipArmors[GeneralEnum.EQUIP_SLOT.LEFTHAND] = new ArmorEntity(); playerManager.equipArmors[equip_slot] = armorEntity;//選択した防具を装備部位に代入する。 UpdateArmorText(playerManager, armorEntity, equip_slot); //選択した防具をリストから削除する ArmorManager.instance.possessionArmor[index] = new ArmorEntity(); //リストに装備していた武器もしくは防具を代入する。 if (tempLHandWEntity.isRegistry) WeaponManager.instance.RegiEntity(tempLHandWEntity); if (tempLHandAEntity.isRegistry) ArmorManager.instance.RegiEntity(tempLHandAEntity); } } } else//装備部位が右手左手じゃない場合 { //現在装備中の防具を一時変数に入れる ArmorEntity tempEntity = playerManager.equipArmors[equip_slot]; //装備中フラグをfalseに tempEntity.nowEquip = false; armorEntity.nowEquip = true;//今から装備する防具のフラグをtrueに //選択した防具を装備部位に代入する。 playerManager.equipArmors[equip_slot] = armorEntity; //装備部位のテキストを反映する UpdateArmorText(playerManager, armorEntity, equip_slot); //リストに装備していた防具を代入する。 ArmorManager.instance.possessionArmor[index] = tempEntity; } //装備反映後の能力値を再計算する playerManager.CalcAllAfterEquipStatusValue();//New playerManager.CalcAllAfterEquipResiOfElementValue();//New playerManager.CalcAllAfterEquipResiOfStatusValue();//New SoundManager.instance.PlaySE(34); }
これで内部的には装備の変更によって数値が変更されるようになったのですが、見た目で確認することができないので、ステータス画面で装備を考慮した数値を確認できるようにしたいと思います。
ステータス画面の制御はPlayerStatusUIスクリプトで行っているのでこちらに処理を追加していきます。現状、PlayerManagerオブジェクトのインスペクターで設定した数値をそのまま表示しているのですが、それを装備反映後の数値とカッコ内に基本値を表示する形式に変更します。
クリックで展開
public void SetStatusText() { nameText.text = "名前 " + PlayerManager.instance.pname; hpText.text = "HP " + PlayerManager.instance.hp + " / " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.HP] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.HP] + ")"; mpText.text = "MP " + PlayerManager.instance.mp + " / " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.MP] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.MP] + ")"; tpText.text = "TP " + PlayerManager.instance.tp; atkText.text = "攻撃 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.ATK] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.ATK] + ")"; defText.text = "防御 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.DEF] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.DEF] + ")"; agiText.text = "速さ " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.AGI] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.AGI] + ")"; lukText.text = "運 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.LUK] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.LUK] + ")"; senceText.text = "感覚 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.SENCE] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.SENCE] + ")"; magpowText.text = "魔力 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.MAGPOW] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.MAGPOW] + ")"; magdefText.text = "魔防 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.MAGDEF] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.MAGDEF] + ")"; learnAbiText.text = "習得 " + PlayerManager.instance.afterEquipStatusValue[GeneralEnum.STATUS.LEARNABI] + "(" + PlayerManager.instance.baseStatusValue[GeneralEnum.STATUS.LEARNABI] + ")"; }
実行すると以下の動画のようになります。
次回は属性耐性値と状態異常のかかりやすさの値を確認できるUIを作成したいと思います。