【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); }
これで全体攻撃のときは敵の真ん中らへんにエフェクトを再生するようにします。実際に全体攻撃の特技を作成して戦闘中に使ってテストします。
次回は複数回敵を攻撃できる特技を実装したいと思います。