27歩目 回復スキルを実装! Unityで1日1ステップ!ノンフィールドRPG開発日記

1日1歩開発日記

ふりかえり

前回は、1.5倍のダメージを与える強撃スキルを実装しました。

これにより、バトルに戦略性が生まれました!

回復スキルを実装!

今回はスキルをさらに拡充!

以下の2つを新たに実装しました:

  • 全力攻撃スキル:2倍ダメージを与える強力な一撃
  • ヒーリングスキル:HPを50回復!

これで攻守のバランスが整い、戦略に深みが出ます!

スクリプトの変更

SkillDataに新要素を追加:

  • damageMultiplier:攻撃スキル用の倍率
  • healAmount:回復スキル用の回復量
  • SkillType:攻撃 or 回復 を判別するための列挙型
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections.Generic;

[System.Serializable]
public class SkillData
{
    public string skillName;
    public int cooldown;
    public int currentCooldown;
    public SkillType skillType;
    public float damageMultiplier; // ダメージ倍率(攻撃スキル用)
    public int healAmount; // 回復量(ヒーリングスキル用)
}

public enum SkillType
{
    Attack,     // 攻撃スキル
    Healing     // 回復スキル
}

public class SkillManager : MonoBehaviour
{
    [Header("スキル設定")]
    public List<SkillData> skills = new List<SkillData>();

    [Header("UI設定")]
    [SerializeField] private Button skillButton;
    [SerializeField] private Image skillButtonImage;
    [SerializeField] private Image cooldownOverlay;

    // クールタイム更新イベント
    public event Action<float> OnCooldownChanged;

    void Start()
    {
        InitializeSkills();
        UpdateCooldownDisplay();
    }

    // スキルの初期化
    private void InitializeSkills()
    {
        if (skills.Count == 0)
        {
            // デフォルトスキルを追加
            skills.Add(new SkillData
            {
                skillName = "強撃",
                cooldown = 5,
                currentCooldown = 0,
                skillType = SkillType.Attack,
                damageMultiplier = 1.5f,
                healAmount = 0
            });

            skills.Add(new SkillData
            {
                skillName = "全力攻撃",
                cooldown = 10,
                currentCooldown = 0,
                skillType = SkillType.Attack,
                damageMultiplier = 2.0f,
                healAmount = 0
            });

            skills.Add(new SkillData
            {
                skillName = "ヒーリング",
                cooldown = 20,
                currentCooldown = 0,
                skillType = SkillType.Healing,
                damageMultiplier = 0f,
                healAmount = 50
            });
        }
    }

    // UI参照を設定するメソッド(PlayerUIManagerから呼ばれる)
    public void SetUIReferences(Button button, Image buttonImage, Image overlay)
    {
        // 既にInspectorで設定されている場合は上書きしない
        if (skillButton == null) skillButton = button;
        if (skillButtonImage == null) skillButtonImage = buttonImage;
        if (cooldownOverlay == null) cooldownOverlay = overlay;
        
        // 設定後にクールタイム表示を更新
        UpdateCooldownDisplay();
    }

    // 指定したスキルが使用可能かどうか
    public bool CanUseSkill(int skillIndex)
    {
        if (skillIndex < 0 || skillIndex >= skills.Count) return false;
        return skills[skillIndex].currentCooldown <= 0;
    }

    // 指定したスキルを使用
    public void UseSkill(int skillIndex)
    {
        if (skillIndex < 0 || skillIndex >= skills.Count) return;
        
        skills[skillIndex].currentCooldown = skills[skillIndex].cooldown;
        UpdateCooldownDisplay();
    }

    // ターン終了時に呼ぶ(1ターン経過)
    public void OnTurnEnd()
    {
        bool cooldownChanged = false;
        
        foreach (var skill in skills)
        {
            if (skill.currentCooldown > 0)
            {
                skill.currentCooldown--;
                cooldownChanged = true;
            }
        }
        
        if (cooldownChanged)
        {
            UpdateCooldownDisplay();
        }
    }

    // 指定したスキルの残りクールタイムを取得
    public int GetCurrentCooldown(int skillIndex)
    {
        if (skillIndex < 0 || skillIndex >= skills.Count) return 0;
        return skills[skillIndex].currentCooldown;
    }

    // 指定したスキルのダメージ計算
    public int CalculateSkillDamage(int skillIndex, int playerAttack)
    {
        if (skillIndex < 0 || skillIndex >= skills.Count) return 0;
        if (skills[skillIndex].skillType != SkillType.Attack) return 0;
        
        return Mathf.CeilToInt(playerAttack * skills[skillIndex].damageMultiplier);
    }

    // 指定したスキルの回復量を取得
    public int GetHealAmount(int skillIndex)
    {
        if (skillIndex < 0 || skillIndex >= skills.Count) return 0;
        if (skills[skillIndex].skillType != SkillType.Healing) return 0;
        
        return skills[skillIndex].healAmount;
    }

    // 指定したスキルの情報を取得
    public SkillData GetSkillData(int skillIndex)
    {
        if (skillIndex < 0 || skillIndex >= skills.Count) return null;
        return skills[skillIndex];
    }

    // スキル数を取得
    public int GetSkillCount()
    {
        return skills.Count;
    }

    // クールタイム表示の更新(現在は最初のスキルのみ表示)
    private void UpdateCooldownDisplay()
    {
        if (skills.Count == 0) return;

        var firstSkill = skills[0];
        float cooldownProgress = 0f;
        
        if (firstSkill.cooldown > 0)
        {
            cooldownProgress = (float)firstSkill.currentCooldown / firstSkill.cooldown;
        }

        // ボタンの有効/無効を設定(最初のスキルが使用可能かどうか)
        if (skillButton != null)
        {
            skillButton.interactable = firstSkill.currentCooldown <= 0;
        }

        // オーバーレイの表示を更新
        if (cooldownOverlay != null)
        {
            cooldownOverlay.fillAmount = cooldownProgress;
            cooldownOverlay.gameObject.SetActive(firstSkill.currentCooldown > 0);
        }

        // イベントを発火
        OnCooldownChanged?.Invoke(cooldownProgress);
    }
} 

BattleManagerでスキル発動の処理を分岐

public void PlayerUseSkill(int skillIndex = 0)
    {
        if (!isPlayerTurn)
        {
            Debug.Log("プレイヤーのターンではありません。");
            return;
        }

        if (!CanPerformAction("スキル"))
        {
            return;
        }

        if (skillManager == null || !skillManager.CanUseSkill(skillIndex))
        {
            Debug.Log("スキルは現在クールタイム中です。");
            return;
        }

        var skillData = skillManager.GetSkillData(skillIndex);
        if (skillData == null)
        {
            Debug.Log("スキルが見つかりません。");
            return;
        }

        // スキル発動
        if (skillData.skillType == SkillType.Attack)
        {
            // 攻撃スキル
            int skillDamage = skillManager.CalculateSkillDamage(skillIndex, playerManager.player.attack);
            enemyManager.TakeDamage(skillDamage);
            
            if (battleLogManager != null)
            {
                battleLogManager.AddLog($"{playerManager.player.name}の{skillData.skillName}!{enemyManager.enemy.name}に{skillDamage}ダメージ!", Color.yellow);
            }
        }
        else if (skillData.skillType == SkillType.Healing)
        {
            // ヒーリングスキル
            int healAmount = skillManager.GetHealAmount(skillIndex);
            int oldHP = playerManager.player.currentHP;
            playerManager.player.currentHP = Mathf.Min(playerManager.player.currentHP + healAmount, playerManager.player.maxHP);
            int actualHeal = playerManager.player.currentHP - oldHP;
            
            if (battleLogManager != null)
            {
                battleLogManager.AddLog($"{playerManager.player.name}の{skillData.skillName}!HPを{actualHeal}回復!", Color.green);
            }
        }

        skillManager.UseSkill(skillIndex);

        // ターン管理(ヒーリングスキルの場合はターンを消費しない)
        if (skillData.skillType == SkillType.Attack)
        {
            if (enemyManager != null && !enemyManager.IsEnemyDead())
            {
                isPlayerTurn = false;
                Invoke("EnemyAttack", 1.0f);
            }
            else
            {
                StartPlayerTurn();
            }
            
            EndPlayerTurn();
        }
        else
        {
            // ヒーリングスキルはターンを消費しない
            StartPlayerTurn();
        }
    }
  • PlayerUIManagerで各スキルボタンとクールダウンオーバーレイを個別に設定。
  • UpdateSkillCooldownDisplay()でスキルごとのボタン状態とオーバーレイを更新。
// スキルクールタイム表示の初期設定
    private void SetupSkillCooldownDisplay()
    {
        SetupCooldownOverlay(skillCooldownOverlay);
        SetupCooldownOverlay(powerAttackCooldownOverlay);
        SetupCooldownOverlay(healingCooldownOverlay);
    }

    // 個別のオーバーレイ設定
    private void SetupCooldownOverlay(Image overlay)
    {
        if (overlay != null)
        {
            overlay.type = Image.Type.Filled;
            overlay.fillMethod = Image.FillMethod.Vertical;
            overlay.fillOrigin = (int)Image.OriginVertical.Bottom;
            overlay.color = new Color(0, 0, 0, 0.7f); // 半透明の黒
            overlay.fillAmount = 0f;
            overlay.gameObject.SetActive(false);
        }
    }

    // 全スキルのクールタイム表示を更新
    private void UpdateSkillCooldownDisplays()
    {
        if (skillManager == null) return;

        // 強撃スキル(インデックス0)
        UpdateSkillCooldownDisplay(0, skillButton, skillCooldownOverlay);
        
        // 全力攻撃スキル(インデックス1)
        UpdateSkillCooldownDisplay(1, powerAttackButton, powerAttackCooldownOverlay);
        
        // ヒーリングスキル(インデックス2)
        UpdateSkillCooldownDisplay(2, healingButton, healingCooldownOverlay);
    }

    // 個別スキルのクールタイム表示を更新
    private void UpdateSkillCooldownDisplay(int skillIndex, Button button, Image overlay)
    {
        if (skillManager == null || button == null || overlay == null) return;

        var skillData = skillManager.GetSkillData(skillIndex);
        if (skillData == null) return;

        float cooldownProgress = 0f;
        if (skillData.cooldown > 0)
        {
            cooldownProgress = (float)skillData.currentCooldown / skillData.cooldown;
        }

        // ボタンの有効/無効を設定
        button.interactable = skillData.currentCooldown <= 0;

        // オーバーレイの表示を更新
        overlay.fillAmount = cooldownProgress;
        overlay.gameObject.SetActive(skillData.currentCooldown > 0);
    }

    // スキルクールタイム変更時の処理(現在は使用していない)
    private void OnSkillCooldownChanged(float cooldownProgress)
    {
        // 個別更新に変更したため、このメソッドは使用しない
    }

Unityの設定

SkillManagerのInspectorでそれぞれのスキルを設定します。

PlayerUIManagerでそれぞれのスキル発動ボタンとクールダウンオーバーレイをアタッチします。

動作確認

  • 「全力攻撃」と「ヒーリング」のボタンをUIに配置
  • 使用ごとに個別クールタイムが表示され、正常に機能!

まとめ

今回は2倍攻撃スキル回復スキルを追加しました!

これにより、バトルに選択肢と戦略性が加わり、より面白くなりました!

次回予告

次回は…

デスペナルティ(戦闘不能時のペナルティ)を実装します!

タイトルとURLをコピーしました