45歩目 オート戦闘を実装! Unityで1日1ステップ!ノンフィールドRPG開発日記

1日1歩開発日記

ふりかえり

前回は、今まで実装した機能を振り返りつつ、今後実装したい機能のロードマップをまとめました。

やるべきことが整理され、開発の見通しがぐっとクリアになりました!

オート戦闘を実装!

今回は「オート戦闘機能」を実装しました!

これまでは手動でタップして攻撃やスキルを使っていましたが、それだと放置ゲームらしさがありません。今後は「放っておいても戦ってくれる」「気づいたら強くなっている」というサイクルを目指します!

そこで、自動で通常攻撃やスキルを発動してくれる仕組みを作りました。

実装のポイント

2種類のオート機能

  • オート攻撃:一定間隔で通常攻撃を自動実行
  • オートスキル:HPやクールタイムなどの条件に応じて自動でスキル発動

ON/OFFボタンで切り替え可能

それぞれボタンでON/OFFが切り替えられ、ONにすると緑色に変わるようにUIも工夫しました。

スクリプトの変更

AutoBattleManager.cs という新しいスクリプトを用意し、以下のような処理を行います。

  • ボタンを押すとON/OFFが切り替わる
  • コルーチンで一定時間ごとに攻撃やスキルを試みる
  • アニメーション中や敵がいない場合などは何もしないようチェック
  • スキルはヒーリング → 強撃 → 全力攻撃の順に優先して使用
  • HPが50%以下の時だけヒーリングを使うよう条件分岐も追加

こういった条件を細かく設定することで、無駄撃ちしない賢いオート戦闘を目指しています!

AutoBattleManager.cs

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;

public class AutoBattleManager : MonoBehaviour
{
    [Header("UI References")]
    public Button autoAttackButton; // オート攻撃ボタン
    public Button autoSkillButton; // オートスキルボタン
    public TextMeshProUGUI autoAttackButtonText; // オート攻撃ボタンテキスト
    public TextMeshProUGUI autoSkillButtonText; // オートスキルボタンテキスト
    
    [Header("Manager References")]
    public BattleManager battleManager;
    public SkillManager skillManager;
    public AnimationManager animationManager;
    public PlayerManager playerManager;
    public EnemyManager enemyManager;
    
    [Header("オート設定")]
    public float autoAttackInterval = 1.0f; // オート攻撃間隔(秒)
    public float autoSkillCheckInterval = 0.5f; // オートスキルチェック間隔(秒)
    
    private bool isAutoAttackEnabled = false;
    private bool isAutoSkillEnabled = false;
    private Coroutine autoAttackCoroutine;
    private Coroutine autoSkillCoroutine;
    
    void Start()
    {
        // ボタンのイベントリスナーを設定
        if (autoAttackButton != null)
        {
            autoAttackButton.onClick.AddListener(ToggleAutoAttack);
        }
        
        if (autoSkillButton != null)
        {
            autoSkillButton.onClick.AddListener(ToggleAutoSkill);
        }
        
        // 初期状態を設定
        UpdateButtonTexts();
    }
    
    void OnDestroy()
    {
        // コルーチンを停止
        StopAutoAttack();
        StopAutoSkill();
    }
    
    // オート攻撃の切り替え
    public void ToggleAutoAttack()
    {
        isAutoAttackEnabled = !isAutoAttackEnabled;
        
        if (isAutoAttackEnabled)
        {
            StartAutoAttack();
        }
        else
        {
            StopAutoAttack();
        }
        
        UpdateButtonTexts();
    }
    
    // オートスキルの切り替え
    public void ToggleAutoSkill()
    {
        isAutoSkillEnabled = !isAutoSkillEnabled;
        
        if (isAutoSkillEnabled)
        {
            StartAutoSkill();
        }
        else
        {
            StopAutoSkill();
        }
        
        UpdateButtonTexts();
    }
    
    // オート攻撃を開始
    private void StartAutoAttack()
    {
        if (autoAttackCoroutine != null)
        {
            StopCoroutine(autoAttackCoroutine);
        }
        autoAttackCoroutine = StartCoroutine(AutoAttackCoroutine());
    }
    
    // オート攻撃を停止
    private void StopAutoAttack()
    {
        if (autoAttackCoroutine != null)
        {
            StopCoroutine(autoAttackCoroutine);
            autoAttackCoroutine = null;
        }
    }
    
    // オートスキルを開始
    private void StartAutoSkill()
    {
        if (autoSkillCoroutine != null)
        {
            StopCoroutine(autoSkillCoroutine);
        }
        autoSkillCoroutine = StartCoroutine(AutoSkillCoroutine());
    }
    
    // オートスキルを停止
    private void StopAutoSkill()
    {
        if (autoSkillCoroutine != null)
        {
            StopCoroutine(autoSkillCoroutine);
            autoSkillCoroutine = null;
        }
    }
    
    // オート攻撃のコルーチン
    private IEnumerator AutoAttackCoroutine()
    {
        while (isAutoAttackEnabled)
        {
            // アニメーション中でない場合のみ攻撃を実行
            if (animationManager == null || !animationManager.IsAnyAnimationPlaying())
            {
                // プレイヤーと敵が存在し、敵が生きている場合のみ攻撃
                if (playerManager != null && enemyManager != null && 
                    playerManager.player != null && enemyManager.enemy != null &&
                    enemyManager.enemy.currentHP > 0)
                {
                    // プレイヤーのターンの時のみ攻撃を実行
                    if (battleManager != null && battleManager.IsPlayerTurn())
                    {
                        // 通常攻撃を実行
                        battleManager.PlayerAttack();
                    }
                }
            }
            
            yield return new WaitForSeconds(autoAttackInterval);
        }
    }
    
    // オートスキルのコルーチン
    private IEnumerator AutoSkillCoroutine()
    {
        while (isAutoSkillEnabled)
        {
            // アニメーション中でない場合のみスキルチェックを実行
            if (animationManager == null || !animationManager.IsAnyAnimationPlaying())
            {
                // プレイヤーと敵が存在し、敵が生きている場合のみスキルチェック
                if (playerManager != null && enemyManager != null && 
                    playerManager.player != null && enemyManager.enemy != null &&
                    enemyManager.enemy.currentHP > 0)
                {
                    // プレイヤーのターンの時のみスキルを実行
                    if (battleManager != null && battleManager.IsPlayerTurn())
                    {
                        // 使用可能なスキルをチェックして実行
                        CheckAndUseSkill();
                    }
                }
            }
            
            yield return new WaitForSeconds(autoSkillCheckInterval);
        }
    }
    
    // 使用可能なスキルをチェックして実行
    private void CheckAndUseSkill()
    {
        if (skillManager == null || battleManager == null) return;
        
        // スキルの優先順位を定義(ヒーリング → 強撃 → 全力攻撃)
        int[] skillPriority = { 2, 0, 1 }; // ヒーリング、強撃、全力攻撃の順
        
        foreach (int skillIndex in skillPriority)
        {
            var skillData = skillManager.GetSkillData(skillIndex);
            if (skillData == null) continue;
            
            // スキルが解放されているかチェック
            if (!skillManager.IsSkillUnlocked(skillIndex)) continue;
            
            // クールタイムが0かチェック
            if (skillData.currentCooldown > 0) continue;
            
            // ヒーリングスキルの場合、HPが低い時のみ使用
            if (skillIndex == 2) // ヒーリングスキル
            {
                if (playerManager.player.currentHP >= playerManager.player.maxHP * 0.5f)
                {
                    continue; // HPが50%以上ならヒーリングは使用しない
                }
            }
            
            // スキルを使用
            battleManager.PlayerUseSkill(skillIndex);
            break; // 1つのスキルを使用したら終了
        }
    }
    
    // ボタンテキストを更新
    private void UpdateButtonTexts()
    {
        if (autoAttackButtonText != null)
        {
            autoAttackButtonText.text = isAutoAttackEnabled ? "オート攻撃: ON" : "オート攻撃: OFF";
        }
        
        if (autoSkillButtonText != null)
        {
            autoSkillButtonText.text = isAutoSkillEnabled ? "オートスキル: ON" : "オートスキル: OFF";
        }
        
        // ボタンの色も変更
        if (autoAttackButton != null)
        {
            var colors = autoAttackButton.colors;
            colors.normalColor = isAutoAttackEnabled ? Color.green : Color.white;
            autoAttackButton.colors = colors;
        }
        
        if (autoSkillButton != null)
        {
            var colors = autoSkillButton.colors;
            colors.normalColor = isAutoSkillEnabled ? Color.green : Color.white;
            autoSkillButton.colors = colors;
        }
    }
    
    // オート攻撃が有効かどうかを取得
    public bool IsAutoAttackEnabled()
    {
        return isAutoAttackEnabled;
    }
    
    // オートスキルが有効かどうかを取得
    public bool IsAutoSkillEnabled()
    {
        return isAutoSkillEnabled;
    }
    
    // オート攻撃を強制停止
    public void ForceStopAutoAttack()
    {
        isAutoAttackEnabled = false;
        StopAutoAttack();
        UpdateButtonTexts();
    }
    
    // オートスキルを強制停止
    public void ForceStopAutoSkill()
    {
        isAutoSkillEnabled = false;
        StopAutoSkill();
        UpdateButtonTexts();
    }
    
    // 全てのオート機能を停止
    public void StopAllAuto()
    {
        ForceStopAutoAttack();
        ForceStopAutoSkill();
    }
} 

Unityでの設定

  • オート用のボタン2つ(攻撃・スキル)をUIに配置
  • AutoBattleManager.cs をGameObjectにアタッチ
  • 各種Manager(BattleManagerやSkillManagerなど)をInspectorで紐付け
  • 攻撃やスキルの間隔もInspector上で調整できるようにしました

動作確認

  • オートスキル: スキルが使えると自動で発動!
  • オート攻撃: スキルが使えない時に通常攻撃!

プレイヤーが何もしなくてもどんどん戦ってくれて、ようやく「放置RPG」としての第一歩を踏み出せました!

まとめ

今回は「オート戦闘」機能を実装しました!

プレイヤーが画面に張り付かずともキャラが自動で戦ってくれるので、快適さが一気にアップしました。戦闘のテンポもよくなり、いよいよゲームの完成が近づいてきました!

次回予告

次回はステージ数をどんどん追加して、バトルに変化をもたせていきたいと思います!

お楽しみに!

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