現場レベルのゲーム制作が、すべてここで学べます。
この講座は世界樹の迷宮やウィザードリィのような3DダンジョンRPGの作り方について説明しています。今回はその第18回目になります。
前回はダンジョン内のイベントをEntityという形で実装し、ダンジョン探索のシステムを一通り用意しました。
前回の記事:

今回は手つかずだった戦闘時の各種コマンド(スキル発動・アイテム使用・防御する・逃げる)やダメージ以外のスキル効果の実装を完了させます。またゲームを繰り返し遊ぶ上で必須となるセーブ&ロード機能も実装していきます。
全スキル効果を実装する(回復・状態異常・バフ・デバフ)
まずは戦闘ダメージ効果(DamageEffect)以外のスキル効果を実装していきます。追加実装するのは以下の効果です。
- HealEffect(回復効果):対象のHPを回復する
- StateEffect(状態異常効果):対象に特定の状態異常を確率で付与する
- RemoveStateEffect(状態異常解除効果):対象の特定の状態異常を解除する
- SpecialEffect(特殊効果):上記のどの効果にも属さない特殊な処理を行う(今回は実装しないが拡張枠として用意)
状態異常の付与に成功する確率は、使用者と対象差のLuc(運)パラメータの差で決定されます。
では、いくつかのC#スクリプトを修正していきましょう。
SkillEffect.cs
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; /// <summary> /// スキル効果の基底クラス /// </summary> [Serializable] public class SkillEffect { /// <summary> /// スキル使用時の対象への効果 /// </summary> /// <param name="battleManager">バトルマネージャークラスへの参照(Battleシーン以外から呼出ならnull)</param> /// <param name="casterData">スキル使用者のCharacterData</param> /// <param name="targetData">スキル使用対象のCharacterData</param> /// <param name="effectValue">スキル効果量倍率</param> public virtual void ApplyEffectToTarget (BattleManager battleManager, CharacterData casterData, CharacterData targetData, float effectValue) { } } /// <summary> /// スキル効果:ダメージ /// </summary> [Serializable] public class DamageEffect : SkillEffect { [Header ("攻撃スキル設定")] public DamageType damageType; // 攻撃の種類 public float damagePower; // ダメージ倍率 public ElementType elementType; // 属性 public bool isRanged; // 遠距離フラグ // 攻撃の種類定義 public enum DamageType { Physical, // 物理ダメージ Magical, // 魔法ダメージ Physical_True, // 物理貫通ダメージ Magical_True, // 物理貫通ダメージ Fixed, // 固定ダメージ } /// <summary> /// スキル使用時の効果(戦闘スキル) /// </summary> public override void ApplyEffectToTarget (BattleManager battleManager, CharacterData casterData, CharacterData targetData, float effectValue) { float skillPower = damagePower * effectValue; // スキル効果量 float attackPoint = 0.0f; // 計算時caster攻撃力 float defensePoint = 0.0f; // 計算時target防御力 int damageValue = 0; // ダメージ量 // ダメージ計算に使用するパラメータ取得 switch (damageType) { case DamageType.Physical: // 物理ダメージ attackPoint = casterData.GetCalculatedAtk (); defensePoint = targetData.GetCalculatedDef (); break; case DamageType.Magical: // 魔法ダメージ attackPoint = casterData.GetCalculatedMAtk (); defensePoint = targetData.GetCalculatedMDef (); break; case DamageType.Physical_True: // 物理貫通ダメージ attackPoint = casterData.GetCalculatedAtk (); break; case DamageType.Magical_True: // 物理貫通ダメージ attackPoint = casterData.GetCalculatedMAtk (); break; } // (アクター攻撃時)武器攻撃力適用 if (casterData is ActorData casterActorData && casterActorData.equipItem_Weapon != null) { attackPoint += ((WeaponItemData)casterActorData.equipItem_Weapon).weaponPower; } // (アクター防御時)防具防御力適用 if (targetData is ActorData targetActorData) { defensePoint += targetActorData.GetArmorParamators ().armorPower; } // スキル効果倍率適用 attackPoint *= skillPower; // ダメージ計算 damageValue = (int)((attackPoint * attackPoint) / (attackPoint + defensePoint)); // 属性耐性値をダメージに適用 damageValue = (int)(damageValue * targetData.GetElementDamage (elementType)); // 乱数 damageValue = (int)(damageValue * UnityEngine.Random.Range (0.85f, 1.15f)); // 固定ダメージ処理 if (damageType == DamageType.Fixed) damageValue = (int)skillPower; // 状態異常「標的」処理(ダメージ量増加) if (targetData.currentStates.ContainsKey (CharacterState.Mark)) { damageValue = (int)(damageValue * 1.3f); } // 状態異常「ガード」処理(ダメージ量減少) if (targetData.currentStates.ContainsKey (CharacterState.Guard)) { damageValue = (int)(damageValue * 0.7f); } // 状態異常「魔法壁」処理(魔法ダメージ半減・「魔法壁」消失) if (targetData.currentStates.ContainsKey (CharacterState.MagicWall) && damageType == DamageType.Magical) { damageValue = (int)(damageValue * 0.5f); targetData.RemoveState (CharacterState.MagicWall); } // ダメージ量の最低値 if (damageValue <= 0) damageValue = 1; // ダメージ量計算結果をログ出力 Debug.Log ("(スキルダメージ) Atk:" + (attackPoint) + " Def:" + (defensePoint) + " Dmg:" + damageValue); // ダメージを対象に適用 if (battleManager != null) { battleManager.ChangeCharacterHP (targetData, -damageValue); // ダメージポップアップ表示 battleManager.SpawnDamagePopupByData (targetData, damageValue, DamagePopupSpawner.DamagePopupType.HP_Damage); } } } /// <summary> /// スキル効果:回復 /// </summary> [Serializable] public class HealEffect : SkillEffect { [Header ("回復スキル設定")] public int healPower; /// <summary> /// スキル使用時の効果(戦闘スキル) /// </summary> public override void ApplyEffectToTarget (BattleManager battleManager, CharacterData casterData, CharacterData targetData, float effectValue) { float skillPower = healPower * effectValue; int healValue = 0; // ヒール量計算 healValue = (int)skillPower; // ヒール量の最低値 if (healValue <= 0) healValue = 1; // ヒールを対象に適用 if (battleManager != null) { battleManager.ChangeCharacterHP (targetData, healValue); battleManager.SpawnDamagePopupByData (targetData, healValue, DamagePopupSpawner.DamagePopupType.HP_Heal); } } } /// <summary> /// スキル効果:状態異常 /// </summary> [Serializable] public class StateEffect : SkillEffect { [Header ("付与する状態異常")] public CharacterState stateType; [Header ("状態異常の持続ターン(0ならターン終了時消去)")] public int stateTurn; [Header ("基礎付与確率")] public float hitPower; [Header ("必中モード")] public bool isCertainty; [Header ("自身に適用モード")] public bool isEffectToSelf; /// <summary> /// スキル使用時の効果(戦闘スキル) /// </summary> public override void ApplyEffectToTarget (BattleManager battleManager, CharacterData casterData, CharacterData targetData, float effectValue) { float skillPower = hitPower * effectValue; CharacterData effectTargetCharacter = isEffectToSelf ? casterData : targetData; // 実効命中率(effectThreshold)を計算 float effectThreshold = skillPower * Mathf.Pow ((float)casterData.GetCalculatedLuc () / effectTargetCharacter.GetCalculatedLuc (), 0.4f); Debug.Log ("状態異常命中率 : (基礎)" + (hitPower * effectValue).ToString ("P0") + " (実効)" + effectThreshold.ToString ("P0")); Debug.Log ("使用者Luck:" + casterData.GetCalculatedLuc () + " 対象Luck:" + effectTargetCharacter.GetCalculatedLuc ()); // 乱数が実効命中率以下または必中モードなら状態異常適用 if (UnityEngine.Random.Range (0.0f, 1.0f) < effectThreshold || isCertainty) { // 状態異常を対象に適用 if (battleManager != null) battleManager.ChangeCharacterState (effectTargetCharacter, stateType, stateTurn); } } } /// <summary> /// スキル効果:状態異常解除 /// </summary> [Serializable] public class RemoveStateEffect : SkillEffect { [Header ("解除する状態異常")] public List<CharacterState> stateTypes; /// <summary> /// スキル使用時の効果(戦闘スキル) /// </summary> public override void ApplyEffectToTarget (BattleManager battleManager, CharacterData casterData, CharacterData targetData, float effectValue) { foreach (var state in stateTypes) { // 対象の状態異常を解除 if (battleManager != null) battleManager.RemoveCharacterState (targetData, state); } } } /// <summary> /// スキル効果:特殊 /// </summary> [Serializable] public class SpecialEffect : SkillEffect { [Header ("特殊効果ID")] public string specialEffectID; /// <summary> /// スキル使用時の効果(戦闘スキル) /// </summary> public override void ApplyEffectToTarget (BattleManager battleManager, CharacterData casterData, CharacterData targetData, float effectValue) { } } |
- 回復スキル
- 状態異常付与(運の値を考慮した確率計算付き)
- 状態異常解除
- 将来の拡張用フレームワーク
が追加されています。これにより、ダメージだけでなく多様なスキル効果を実装できるようになっています。
状態異常命中率はLucの差を反映させるために、設定されたスキル命中率をもとに実効命中率を計算して判定を行っています。
(54行目の変更はただコメントをまとめただけです)
SkillDataEditor.cs
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
using UnityEngine; using UnityEditor; [CustomEditor (typeof (SkillData))] public class SkillDataEditor : Editor { SerializedProperty skillEffectsProperty; void OnEnable () { // SerializedPropertyの取得 skillEffectsProperty = serializedObject.FindProperty ("skillEffects"); } public override void OnInspectorGUI () { serializedObject.Update (); // skillEffects以外のプロパティを表示 DrawPropertiesExcluding (serializedObject, "skillEffects"); // Inspector画面上の空白 EditorGUILayout.Space (5); // skillEffectsプロパティを手動で表示 EditorGUILayout.PropertyField (skillEffectsProperty, true); // Inspector画面上の空白 EditorGUILayout.Space (5); // 効果追加用のボタン群 SkillData skillData = (SkillData)target; // (上段・ダメージ効果と回復効果) EditorGUILayout.BeginHorizontal (); if (GUILayout.Button ("Add Damage Effect")) {// ダメージ効果追加ボタン skillData.skillEffects.Add (new DamageEffect ()); } if (GUILayout.Button ("Add Heal Effect")) {// 回復効果追加ボタン skillData.skillEffects.Add (new HealEffect ()); } EditorGUILayout.EndHorizontal (); // (下段・状態異常効果と状態異常解除効果と特殊効果) EditorGUILayout.BeginHorizontal (); if (GUILayout.Button ("Add State Effect")) {// 状態異常効果追加ボタン skillData.skillEffects.Add (new StateEffect ()); } if (GUILayout.Button ("Add RemoveState Effect")) {// 状態異常解除効果追加ボタン skillData.skillEffects.Add (new RemoveStateEffect ()); } if (GUILayout.Button ("Add Special Effect")) {// 特殊効果追加ボタン skillData.skillEffects.Add (new SpecialEffect ()); } EditorGUILayout.EndHorizontal (); serializedObject.ApplyModifiedProperties (); } } |
SkillDataのScriptableObjectをInspectorから編集するときの拡張クラスで、ダメージ効果以外の追加にもボタン1つで対応できるようにしました。
SkillData.cs (一部省略)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System; using System.Collections.Generic; using UnityEngine; /// <summary> /// (ScriptableObject) /// スキルデータ定義 /// </summary> [CreateAssetMenu (fileName = "Skill", menuName = "Dungeon/SkillSO")] [Serializable] public class SkillData : ScriptableObject { [Header ("基本データ")] public string skillName_JP; // スキル名(JP) public string skillName_EN; // スキル名(EN) [Multiline (2)] public string description_JP; // スキル説明(JP) [Multiline (2)] public string description_EN; // スキル説明(EN) [Header ("スキルレベル別データ\n(各リストは同じ要素数にする)")] public List<int> costTP_Levels = new List<int> () { 0 }; // レベルごとの消費TP public List<float> effectValue_Levels = new List<float> () { 1.0f };// レベルごとの効果量倍率(1.0fが等倍) [Header ("スキル特性")] public SkillType skillType; // スキルの種類 public TargetType targetType; // スキル使用対象設定 public int hitNum = 1; // ヒット回数(それぞれの効果が発動する回数) [SerializeReference] [Header ("スキル発動時効果")] public List<SkillEffect> skillEffects = new List<SkillEffect> (); [Header ("パッシブ効果種別・効果量")] public string passiveEffectType; public float passiveEffectPower; (以降省略) |
SkillDataのScriptableObjectにおいて、パッシブ効果を設定できるように拡張しました。
passiveEffectTypeに文字列を入力しておけば、「そのスキルを習得しているキャラは常時〇〇の効果を得る」といった処理に利用可能です。
今回はパッシブスキル自体は作成しませんが、後ほど用意する逃走コマンドにおいてこのpassiveEffectTypeパラメータを使用します。
ActorData.cs
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
using System.Collections.Generic; using UnityEngine; /// <summary> /// アクターデータクラス(CharacterDataから派生) /// </summary> public class ActorData : CharacterData { // 職業データ public int jobID; // 立ち絵ID public int pictureID; // 習得済みスキル・スキルレベル public Dictionary<SkillData, int> ownedSkillLevels; // 残りスキルポイント public int remainSkillPoint; // 現在レベル public int nowLevel; // 現在経験値 public int nowEXP; // 最大経験値 public int maxEXP; // 内部処理用 [HideInInspector] public int displayNowExp; // 表示用現在経験値 [HideInInspector] public int displayMaxExp; // 表示用最大経験値 // 装備中アイテム public ItemData equipItem_Weapon; // 武器 public ItemData equipItem_Armor_Head; // 頭防具 public ItemData equipItem_Armor_Torso; // 胴体防具 public ItemData equipItem_Armor_Legs; // 脚防具 public ItemData equipItem_Armor_LeftHand; // 左手防具 /// <summary> /// 職業を取得する /// </summary> public JobData GetNowJob () { return Data.instance.jobDatas[jobID]; } /// <summary> /// 経験値を加算する /// </summary> public void GainExp (int value) { // 経験値加算 nowEXP += value; displayNowExp += value; // 現在経験値が最大値以上ならレベルアップ処理 if (nowEXP >= maxEXP) CheckLevelUp (); } /// <summary> /// レベルを1つ上昇させる /// </summary> public void CheckLevelUp () { // 表示に用いる現在経験値量をもとの値に戻す displayNowExp -= displayMaxExp; // レベル増加 nowLevel++; // 次の最大経験値を適用 maxEXP = GetMaxExp (nowLevel); displayMaxExp = maxEXP - GetMaxExp (nowLevel - 1); // スキルポイント取得 remainSkillPoint++; // ステータス上昇 baseMaxHP += GetNowJob ().st_HP; baseMaxTP += GetNowJob ().st_TP; baseAtk += GetNowJob ().st_Atk; baseDef += GetNowJob ().st_Def; baseMAtk += GetNowJob ().st_MAtk; baseMDef += GetNowJob ().st_MDef; baseLuc += GetNowJob ().st_Luc; } /// <summary> /// 指定レベルにおける最大Exp(次のレベルまでに必要なExp)を返す /// </summary> public int GetMaxExp (int targetLevel) { // 必要経験値の基礎量 int baseNeedExp = targetLevel * 100; // 高いレベルほど追加の経験値を必要とする計算 int additionalNeedExp = (targetLevel - 1) * (targetLevel - 1) * 10; return baseNeedExp + additionalNeedExp; } /// <summary> /// 装備中の全防具の防御力・重量合計を返す(武器は含めない) /// </summary> public (int armorPower, int weight) GetArmorParamators () { int armorPower = 0; int weight = 0; if (equipItem_Armor_Head != null) { armorPower += ((ArmorItemData)equipItem_Armor_Head).armorPower; weight += ((ArmorItemData)equipItem_Armor_Head).weight; } if (equipItem_Armor_Torso != null) { armorPower += ((ArmorItemData)equipItem_Armor_Torso).armorPower; weight += ((ArmorItemData)equipItem_Armor_Torso).weight; } if (equipItem_Armor_Legs != null) { armorPower += ((ArmorItemData)equipItem_Armor_Legs).armorPower; weight += ((ArmorItemData)equipItem_Armor_Legs).weight; } if (equipItem_Armor_LeftHand != null) { armorPower += ((ArmorItemData)equipItem_Armor_LeftHand).armorPower; weight += ((ArmorItemData)equipItem_Armor_LeftHand).weight; } return (armorPower, weight); } /// <summary> /// 指定された防具アイテムを装備した場合の防御力を返す /// </summary> public (int armorPower, int weight) GetArmorParamatorsAtSelectItem (ArmorItemData selectedArmorData) { int armorPower = 0; int weight = 0; // 各部位ごとの計算(指定された防具が該当部位であればそちらを優先して用いて計算) if (selectedArmorData.armorType == ArmorType.Head) { armorPower += selectedArmorData.armorPower; weight += selectedArmorData.weight; } else if (equipItem_Armor_Head != null) { armorPower += ((ArmorItemData)equipItem_Armor_Head).armorPower; weight += ((ArmorItemData)equipItem_Armor_Head).weight; } if (selectedArmorData.armorType == ArmorType.Torso) { armorPower += selectedArmorData.armorPower; weight += selectedArmorData.weight; } else if (equipItem_Armor_Torso != null) { armorPower += ((ArmorItemData)equipItem_Armor_Torso).armorPower; weight += ((ArmorItemData)equipItem_Armor_Torso).weight; } if (selectedArmorData.armorType == ArmorType.Legs) { armorPower += selectedArmorData.armorPower; weight += selectedArmorData.weight; } else if (equipItem_Armor_Legs != null) { armorPower += ((ArmorItemData)equipItem_Armor_Legs).armorPower; weight += ((ArmorItemData)equipItem_Armor_Legs).weight; } if (selectedArmorData.armorType == ArmorType.LeftHand) { armorPower += selectedArmorData.armorPower; weight += selectedArmorData.weight; } else if (equipItem_Armor_LeftHand != null) { armorPower += ((ArmorItemData)equipItem_Armor_LeftHand).armorPower; weight += ((ArmorItemData)equipItem_Armor_LeftHand).weight; } return (armorPower, weight); } /// <summary> /// 指定された防具アイテムを装備した場合の耐性値を返す /// </summary> public float GetCalcedResistAtSelectItem (ElementType elementType, ArmorItemData selectedArmorData) { // 指定なしなら通常の値を返す if (selectedArmorData == null) return GetCalculatedResist (elementType); // 現在値を取得 float value = base.GetCalculatedResist (elementType); // 各部位ごとの計算(指定された防具が該当部位であればそちらを優先して用いて計算) if (selectedArmorData.armorType == ArmorType.Head) { value += selectedArmorData.GetResistValue (elementType); } else if (equipItem_Armor_Head != null) { value += ((ArmorItemData)equipItem_Armor_Head).GetResistValue (elementType); } if (selectedArmorData.armorType == ArmorType.Torso) { value += selectedArmorData.GetResistValue (elementType); } else if (equipItem_Armor_Torso != null) { value += ((ArmorItemData)equipItem_Armor_Torso).GetResistValue (elementType); } if (selectedArmorData.armorType == ArmorType.Legs) { value += selectedArmorData.GetResistValue (elementType); } else if (equipItem_Armor_Legs != null) { value += ((ArmorItemData)equipItem_Armor_Legs).GetResistValue (elementType); } if (selectedArmorData.armorType == ArmorType.LeftHand) { value += selectedArmorData.GetResistValue (elementType); } else if (equipItem_Armor_LeftHand != null) { value += ((ArmorItemData)equipItem_Armor_LeftHand).GetResistValue (elementType); } return value; } /// <summary> /// 指定のパッシブ効果を持つスキルを所持しているかを検索し、所持していればその効果量を含めて返す /// </summary> public (bool isOwned, float skillPower) GetPassiveSkillPower (string passiveEffectType) { foreach (var ownedSkillLevel in ownedSkillLevels) { if (ownedSkillLevel.Key.passiveEffectType == passiveEffectType) {// 指定のパッシブスキルが有る float effectValue = (ownedSkillLevel.Key.passiveEffectPower * ownedSkillLevel.Key.effectValue_Levels[ownedSkillLevel.Value]); return (true, effectValue); } } // 指定のパッシブスキルが無ければfalseを返す return (false, 0.0f); } #region 現在パラメータ取得(override) // Speed public override int GetCalculatedSpeed () { // 現在値を取得 int value = base.GetCalculatedSpeed (); // 重量補正を適用 if (equipItem_Weapon != null) value -= ((WeaponItemData)equipItem_Weapon).weight; value -= GetArmorParamators ().weight; if (value < 1) value = 1; return value; } // 各種耐性値 public override float GetCalculatedResist (ElementType elementType) { // 現在値を取得 float value = base.GetCalculatedResist (elementType); // 防具による耐性値補正を適用 if (equipItem_Armor_Head != null) { value += ((ArmorItemData)equipItem_Armor_Head).GetResistValue (elementType); } if (equipItem_Armor_Torso != null) { value += ((ArmorItemData)equipItem_Armor_Torso).GetResistValue (elementType); } if (equipItem_Armor_Legs != null) { value += ((ArmorItemData)equipItem_Armor_Legs).GetResistValue (elementType); } if (equipItem_Armor_LeftHand != null) { value += ((ArmorItemData)equipItem_Armor_LeftHand).GetResistValue (elementType); } return value; } #endregion } |
パッシブスキルを作成する場合に利用できるメソッドを追加しておきました。
そのアクターの指定のパッシブスキルの有無と効果量を返します。
回復スキルの実装例

アクター1人のHPを15回復します。スキルレベルにより効果量が上昇します。
状態異常スキルの実装例

スキルを使用した自分自身に確定で”Protection”の状態異常を付与します。(2ターン持続)
他の状態異常スキルを付与する際も同様です。また、これらの状態異常の定義はCharacterData.csの238-245行目、実際の処理はBattleManagerで既に実装済みです。例えば毒効果であればBattleManager.csの713行目に存在しています(最大HPの10%のダメージを与えるなど)。
状態異常解除スキルの実装例

アクター1人の”Poison”、”Stun”、”Mark”の状態異常をそれぞれ解除します。
各ジョブのスキルツリーにスキルを登録する(復習)
新しくスキルを作成したらジョブのスキルツリーにセットしてみましょう。既に作ったScriptable Objectに設定するだけですね。

どんなスキルを用意するか。どんなスキルツリーを作るかはあなた次第。
戦闘コマンド実装:スキル
それでは用意したスキルを戦闘で使用可能にしていきます。
まだアクタースキルを戦闘中に使用することができないので、戦闘シーンを拡張し、コマンドボタンの[SKILL]を押下することでスキル使用できるようにしていきます。
まとめ

これで戦闘のシステムが一通り完成し、ゲームのセーブ&ロード機能によって繰り返し遊ぶことも可能になりました。
次回の記事ではダンジョン探索中にメニュー画面を開き、アイテムやスキルを使用できるようにします。次回で3DダンジョンRPGの基本機能が完成します。
次の記事:

現場レベルのゲーム制作が、すべてここで学べます。






コメント