42歩目 転生機能を実装! Unityで1日1ステップ!ノンフィールドRPG開発日記

1日1歩開発日記

ふりかえり

前回はセーブ機能を実装し、ゲームの進行状態を保存・復元できるようにしました!

これで安心してプレイを続けられますね!

転生機能を実装!

今回は、いよいよ「転生」機能を実装します!

敵が強くなって先に進めなくなっても、転生して再挑戦できるようになります。

転生により以下のような変化が起こります。

転生するとリセットされる内容

  • プレイヤーのレベル
  • ステージ進行度
  • 所持ゴールド
  • ゴールド強化状態
  • スキルの開放・強化状態

転生で得られるもの

  • 「マナ」(現在のステージ数に応じて獲得)
  • マナを使って 恒久的な強化(転生強化) が可能!

スクリプトの変更

PrestigeManager.cs

転生処理の中心は PrestigeManager.cs にまとめました。

プレイヤーやステージ、スキルの情報をリセットしつつ、転生ステータスは維持され、次回プレイに活かされます。

HP強化・攻撃力強化・防御力強化・会心率・会心ダメージなど、成長の方向性はプレイヤー次第!

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

public class PrestigeManager : MonoBehaviour
{
    [Header("UI References")]
    public GameObject prestigePanel; // 転生パネル
    public Button prestigeToggleButton; // 転生パネル開閉ボタン
    public TextMeshProUGUI prestigeToggleButtonText; // ボタンテキスト
    
    [Header("転生パネル内のUI")]
    public TextMeshProUGUI currentManaText; // 現在のマナ表示
    public TextMeshProUGUI prestigeRewardText; // 転生報酬表示
    public Button prestigeButton; // 転生実行ボタン
    public TextMeshProUGUI prestigeButtonText; // 転生ボタンテキスト
    
    [Header("マナ強化UI")]
    public Transform manaUpgradeContent; // マナ強化アイテムの親オブジェクト
    public GameObject manaUpgradeItemPrefab; // マナ強化アイテムのプレハブ
    
    [Header("Manager References")]
    public PlayerManager playerManager;
    public StageManager stageManager;
    public SkillManager skillManager;
    public PowerUpManager powerUpManager;
    public ArtifactManager artifactManager;
    public SaveManager saveManager;
    public EnemyManager enemyManager; // EnemyManagerの参照を追加
    
    [Header("転生設定")]
    public int manaPerStage = 1; // 1ステージあたりのマナ獲得量
    
    private bool isPrestigePanelOpen = false;
    private int currentMana = 0; // 現在のマナ
    private List<ManaUpgradeItem> manaUpgradeItems = new List<ManaUpgradeItem>();
    
    // マナ強化アイテムのデータ
    [System.Serializable]
    public class ManaUpgradeData
    {
        public string upgradeName;
        public string description;
        public int baseCost;
        public float costMultiplier;
        public int currentLevel;
        public int maxLevel;
        public StatType statType;
        public float valuePerLevel;
    }
    
    public enum StatType
    {
        HP,
        Attack,
        Defense,
        CriticalRate,
        CriticalDamage
    }
    
    private List<ManaUpgradeData> upgradeDataList = new List<ManaUpgradeData>();
    
    void Start()
    {
        InitializePrestigeSystem();
        UpdatePrestigeUI();
    }
    
    // 転生システムの初期化
    private void InitializePrestigeSystem()
    {
        // 転生パネルを初期状態で閉じる
        if (prestigePanel != null)
        {
            prestigePanel.SetActive(false);
        }
        
        // ボタンのリスナーを設定
        if (prestigeToggleButton != null)
        {
            prestigeToggleButton.onClick.AddListener(TogglePrestigePanel);
        }
        
        if (prestigeButton != null)
        {
            prestigeButton.onClick.AddListener(ExecutePrestige);
        }
        
        // マナ強化データを初期化
        InitializeManaUpgradeData();
        
        // マナ強化UIを生成
        CreateManaUpgradeItems();
    }
    
    // マナ強化データの初期化
    private void InitializeManaUpgradeData()
    {
        upgradeDataList.Clear();
        
        // HP強化
        upgradeDataList.Add(new ManaUpgradeData
        {
            upgradeName = "HP強化",
            description = "転生時の基礎HPを増加させる",
            baseCost = 1,
            costMultiplier = 1.2f,
            currentLevel = 0,
            maxLevel = 100,
            statType = StatType.HP,
            valuePerLevel = 10
        });
        
        // 攻撃力強化
        upgradeDataList.Add(new ManaUpgradeData
        {
            upgradeName = "攻撃力強化",
            description = "転生時の基礎攻撃力を増加させる",
            baseCost = 1,
            costMultiplier = 1.3f,
            currentLevel = 0,
            maxLevel = 100,
            statType = StatType.Attack,
            valuePerLevel = 2
        });
        
        // 防御力強化
        upgradeDataList.Add(new ManaUpgradeData
        {
            upgradeName = "防御力強化",
            description = "転生時の基礎防御力を増加させる",
            baseCost = 1,
            costMultiplier = 1.25f,
            currentLevel = 0,
            maxLevel = 100,
            statType = StatType.Defense,
            valuePerLevel = 1
        });
        
        // 会心率強化
        upgradeDataList.Add(new ManaUpgradeData
        {
            upgradeName = "会心率強化",
            description = "転生時の基礎会心率を増加させる",
            baseCost = 2,
            costMultiplier = 1.4f,
            currentLevel = 0,
            maxLevel = 50,
            statType = StatType.CriticalRate,
            valuePerLevel = 0.01f
        });
        
        // 会心ダメージ強化
        upgradeDataList.Add(new ManaUpgradeData
        {
            upgradeName = "会心ダメージ強化",
            description = "転生時の基礎会心ダメージ倍率を増加させる",
            baseCost = 3,
            costMultiplier = 1.5f,
            currentLevel = 0,
            maxLevel = 30,
            statType = StatType.CriticalDamage,
            valuePerLevel = 0.1f
        });
    }
    
    // マナ強化アイテムUIを生成
    private void CreateManaUpgradeItems()
    {
        if (manaUpgradeContent == null || manaUpgradeItemPrefab == null) return;
        
        // 既存のアイテムをクリア
        foreach (Transform child in manaUpgradeContent)
        {
            Destroy(child.gameObject);
        }
        manaUpgradeItems.Clear();
        
        // 新しいアイテムを生成
        for (int i = 0; i < upgradeDataList.Count; i++)
        {
            GameObject itemObj = Instantiate(manaUpgradeItemPrefab, manaUpgradeContent);
            ManaUpgradeItem item = itemObj.GetComponent<ManaUpgradeItem>();
            
            if (item != null)
            {
                item.Initialize(upgradeDataList[i], this);
                manaUpgradeItems.Add(item);
            }
        }
    }
    
    // 転生パネルの開閉
    public void TogglePrestigePanel()
    {
        isPrestigePanelOpen = !isPrestigePanelOpen;
        
        if (prestigePanel != null)
        {
            prestigePanel.SetActive(isPrestigePanelOpen);
        }
        
        if (prestigeToggleButtonText != null)
        {
            prestigeToggleButtonText.text = isPrestigePanelOpen ? "転生パネルを閉じる" : "転生パネルを開く";
        }
        
        if (isPrestigePanelOpen)
        {
            UpdatePrestigeUI();
        }
    }
    
    // 転生UIの更新
    private void UpdatePrestigeUI()
    {
        if (currentManaText != null)
        {
            currentManaText.text = $"現在のマナ: {currentMana}";
        }
        
        if (prestigeRewardText != null && stageManager != null)
        {
            int currentStage = stageManager.GetCurrentStage();
            int manaReward = currentStage * manaPerStage;
            prestigeRewardText.text = $"転生報酬: {manaReward}マナ (ステージ{currentStage})";
        }
        
        // マナ強化アイテムの更新
        foreach (var item in manaUpgradeItems)
        {
            item.UpdateDisplay();
        }
    }
    
    // 転生を実行
    public void ExecutePrestige()
    {
        if (stageManager == null || playerManager == null) return;
        
        int currentStage = stageManager.GetCurrentStage();
        int manaReward = currentStage * manaPerStage;
        
        // マナを獲得
        currentMana += manaReward;
        
        // 転生による初期化
        ResetForPrestige();
        
        // 転生ステータスを適用
        ApplyPrestigeStats();
        
        // セーブデータを更新
        if (saveManager != null)
        {
            saveManager.SaveGameData();
        }
        
        // UIを更新
        UpdatePrestigeUI();
        
        // 転生パネルを閉じる
        TogglePrestigePanel();
        
        Debug.Log($"転生完了!{manaReward}マナを獲得しました。");
    }
    
    // 転生による初期化
    private void ResetForPrestige()
    {
        // ステージ進行度をリセット
        if (stageManager != null)
        {
            stageManager.SetStageProgress(1, 0);
        }
        
        // 敵をリセット(新しい敵を生成)
        if (enemyManager != null)
        {
            enemyManager.SetupNewEnemyForStage(1);
        }
        
        // プレイヤーのレベルをリセット
        if (playerManager != null && playerManager.player != null)
        {
            playerManager.player.level = 1;
            playerManager.player.exp = 0;
            playerManager.player.expToNextLevel = 10;
            playerManager.player.currentHP = playerManager.player.maxHP;
        }
        
        // スキルをリセット
        if (skillManager != null)
        {
            foreach (var skill in skillManager.skills)
            {
                skill.skillLevel = 0;
                skill.isUnlocked = false;
                skill.currentCooldown = 0;
            }
        }
        
        // G強化をリセット
        if (playerManager != null && playerManager.player != null)
        {
            playerManager.player.gPowerUpHP = 0;
            playerManager.player.gPowerUpAttack = 0;
            playerManager.player.gPowerUpDefense = 0;
            playerManager.player.gPowerUpCriticalRate = 0f;
            playerManager.player.gPowerUpCriticalDamage = 0f;
        }
        
        // 転生ステータスをリセット
        if (playerManager != null && playerManager.player != null)
        {
            playerManager.player.prestigePowerUpHP = 0;
            playerManager.player.prestigePowerUpAttack = 0;
            playerManager.player.prestigePowerUpDefense = 0;
            playerManager.player.prestigePowerUpCriticalRate = 0f;
            playerManager.player.prestigePowerUpCriticalDamage = 0f;
        }
        
        // Gをリセット(ダイヤは保持)
        if (playerManager != null && playerManager.player != null)
        {
            playerManager.player.gold = 0;
        }
        
        // アーティファクトは保持(転生ステータスとして)
        // アーティファクトの効果は引き続き適用される
    }
    
    // 転生ステータスを適用
    private void ApplyPrestigeStats()
    {
        if (playerManager == null || playerManager.player == null) return;
        
        // 転生ステータスを計算
        int prestigeHP = 0;
        int prestigeAttack = 0;
        int prestigeDefense = 0;
        float prestigeCriticalRate = 0f;
        float prestigeCriticalDamage = 0f;
        
        foreach (var upgradeData in upgradeDataList)
        {
            switch (upgradeData.statType)
            {
                case StatType.HP:
                    prestigeHP += (int)(upgradeData.currentLevel * upgradeData.valuePerLevel);
                    break;
                case StatType.Attack:
                    prestigeAttack += (int)(upgradeData.currentLevel * upgradeData.valuePerLevel);
                    break;
                case StatType.Defense:
                    prestigeDefense += (int)(upgradeData.currentLevel * upgradeData.valuePerLevel);
                    break;
                case StatType.CriticalRate:
                    prestigeCriticalRate += upgradeData.currentLevel * upgradeData.valuePerLevel;
                    break;
                case StatType.CriticalDamage:
                    prestigeCriticalDamage += upgradeData.currentLevel * upgradeData.valuePerLevel;
                    break;
            }
        }
        
        // 基礎ステータスを初期値に戻す
        playerManager.player.baseMaxHP = 100;
        playerManager.player.baseAttack = 10;
        playerManager.player.baseDefense = 0;
        playerManager.player.baseCriticalRate = 0.1f;
        playerManager.player.baseCriticalDamageMultiplier = 2.0f;
        
        // 転生ステータスをPlayerDataに適用
        playerManager.player.prestigePowerUpHP = prestigeHP;
        playerManager.player.prestigePowerUpAttack = prestigeAttack;
        playerManager.player.prestigePowerUpDefense = prestigeDefense;
        playerManager.player.prestigePowerUpCriticalRate = prestigeCriticalRate;
        playerManager.player.prestigePowerUpCriticalDamage = prestigeCriticalDamage;
        
        // 現在HPを最大値に設定
        playerManager.player.currentHP = playerManager.player.maxHP;
    }
    
    // マナ強化を実行
    public bool TryUpgradeWithMana(ManaUpgradeData upgradeData)
    {
        int cost = CalculateUpgradeCost(upgradeData);
        
        if (currentMana >= cost && upgradeData.currentLevel < upgradeData.maxLevel)
        {
            currentMana -= cost;
            upgradeData.currentLevel++;
            
            // 転生ステータスを再適用
            ApplyPrestigeStats();
            
            // UIを更新
            UpdatePrestigeUI();
            
            // セーブデータを更新
            if (saveManager != null)
            {
                saveManager.SaveGameData();
            }
            
            Debug.Log($"{upgradeData.upgradeName}をレベル{upgradeData.currentLevel}に強化しました。");
            return true;
        }
        
        return false;
    }
    
    // 強化コストを計算
    private int CalculateUpgradeCost(ManaUpgradeData upgradeData)
    {
        return Mathf.RoundToInt(upgradeData.baseCost * Mathf.Pow(upgradeData.costMultiplier, upgradeData.currentLevel));
    }
    
    // 現在のマナを取得
    public int GetCurrentMana()
    {
        return currentMana;
    }
    
    // マナを設定(セーブデータロード用)
    public void SetCurrentMana(int mana)
    {
        currentMana = mana;
        UpdatePrestigeUI();
    }
    
    // マナ強化データを取得
    public List<ManaUpgradeData> GetUpgradeDataList()
    {
        return upgradeDataList;
    }
    
    // マナ強化データを設定(セーブデータロード用)
    public void SetUpgradeDataList(List<ManaUpgradeData> dataList)
    {
        upgradeDataList = dataList;
        CreateManaUpgradeItems();
    }
} 

ManaUpgradeItem.cs

ManaUpgradeItem.cs では、マナを使った強化のUI処理を実装。

using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class ManaUpgradeItem : MonoBehaviour
{
    [Header("UI References")]
    public TextMeshProUGUI upgradeNameText;
    public TextMeshProUGUI descriptionText;
    public TextMeshProUGUI levelText;
    public TextMeshProUGUI costText;
    public Button upgradeButton;
    public TextMeshProUGUI upgradeButtonText;
    
    private PrestigeManager.ManaUpgradeData upgradeData;
    private PrestigeManager prestigeManager;
    
    public void Initialize(PrestigeManager.ManaUpgradeData data, PrestigeManager manager)
    {
        upgradeData = data;
        prestigeManager = manager;
        
        UpdateDisplay();
        
        // ボタンのリスナーを設定
        if (upgradeButton != null)
        {
            upgradeButton.onClick.AddListener(OnUpgradeButtonClicked);
        }
    }
    
    public void UpdateDisplay()
    {
        if (upgradeData == null) return;
        
        // 名前と説明を設定
        if (upgradeNameText != null)
        {
            upgradeNameText.text = upgradeData.upgradeName;
        }
        
        if (descriptionText != null)
        {
            descriptionText.text = upgradeData.description;
        }
        
        // レベルを表示
        if (levelText != null)
        {
            levelText.text = $"レベル: {upgradeData.currentLevel}/{upgradeData.maxLevel}";
        }
        
        // コストを計算して表示
        int cost = CalculateUpgradeCost();
        if (costText != null)
        {
            costText.text = $"コスト: {cost}マナ";
        }
        
        // ボタンの状態を更新
        UpdateButtonState(cost);
    }
    
    private int CalculateUpgradeCost()
    {
        return Mathf.RoundToInt(upgradeData.baseCost * Mathf.Pow(upgradeData.costMultiplier, upgradeData.currentLevel));
    }
    
    private void UpdateButtonState(int cost)
    {
        if (upgradeButton == null || upgradeButtonText == null) return;
        
        bool canUpgrade = prestigeManager.GetCurrentMana() >= cost && upgradeData.currentLevel < upgradeData.maxLevel;
        
        upgradeButton.interactable = canUpgrade;
        
        if (upgradeData.currentLevel >= upgradeData.maxLevel)
        {
            upgradeButtonText.text = "最大レベル";
        }
        else if (canUpgrade)
        {
            upgradeButtonText.text = "強化";
        }
        else
        {
            upgradeButtonText.text = "マナ不足";
        }
    }
    
    private void OnUpgradeButtonClicked()
    {
        if (prestigeManager != null)
        {
            bool success = prestigeManager.TryUpgradeWithMana(upgradeData);
            if (success)
            {
                UpdateDisplay();
            }
        }
    }
} 

Unityでの設定

1. PrestigeManagerの設定

1-1. PrestigeManagerスクリプトをGameObjectにアタッチ

1-2. PrestigeManagerの参照設定

InspectorのPrestigeManagerコンポーネントで以下を設定:

Manager References

  • Player Manager: 既存のPlayerManagerオブジェクトをドラッグ&ドロップ
  • Stage Manager: 既存のStageManagerオブジェクトをドラッグ&ドロップ
  • Skill Manager: 既存のSkillManagerオブジェクトをドラッグ&ドロップ
  • Power Up Manager: 既存のPowerUpManagerオブジェクトをドラッグ&ドロップ
  • Artifact Manager: 既存のArtifactManagerオブジェクトをドラッグ&ドロップ
  • Save Manager: 既存のSaveManagerオブジェクトをドラッグ&ドロップ

転生設定

  • Mana Per Stage: 1(デフォルト値)

2. 転生パネルのUI作成

2-1. ScrollViewの設定

  1. ManaUpgradeScrollViewを選択
  2. Scroll Rectの設定:
  • Content: Viewport/Contentをドラッグ&ドロップ
  • Horizontal: チェックを外す
  • Vertical: チェック済み
  • Movement Type: Elastic
  • Elasticity: 0.1

2-2. Viewportの設定

  1. Viewportを選択
  2. Rect Transformの設定:
  • Anchor: Stretch-Stretch
  • Left, Right, Top, Bottom: 0
  1. Maskコンポーネントの設定:
  • Show Mask Graphic: チェックを外す

2-3. Contentの設定

  1. Contentを選択
  2. Rect Transformの設定:
  1. Content Size Fitterを追加:
  • Vertical Fit: Preferred Size
  1. Vertical Layout Groupを追加:
  • Padding: Top=10, Bottom=10
  • Spacing: 10
  • Child Force Expand Width: チェック済み
  • Child Force Expand Height: チェックを外す

3. ManaUpgradeItemPrefabの作成

3-1. プレハブの基本構造

  1. Hierarchyで右クリック → UIPanel
  2. 名前を「ManaUpgradeItemPrefab」に変更

3-2. プレハブ内のUI要素を作成

3-3. ManaUpgradeItemスクリプトのアタッチ

  1. ManaUpgradeItemPrefabを選択
  2. Add ComponentScriptsManaUpgradeItemを選択

3-4. ManaUpgradeItemの参照設定

InspectorのManaUpgradeItemコンポーネントで以下を設定:

  • Upgrade Name Text: UpgradeNameTextをドラッグ&ドロップ
  • Description Text: DescriptionTextをドラッグ&ドロップ
  • Level Text: LevelTextをドラッグ&ドロップ
  • Cost Text: CostTextをドラッグ&ドロップ
  • Upgrade Button: UpgradeButtonをドラッグ&ドロップ
  • Upgrade Button Text: UpgradeButtonのTextMeshProUGUIをドラッグ&ドロップ

3-5. プレハブの作成

  1. ManaUpgradeItemPrefabProjectウィンドウのPrefabsフォルダにドラッグ&ドロップ
  2. HierarchyのManaUpgradeItemPrefabを削除

4. SaveManagerの設定

4-1. PrestigeManagerの参照追加

  1. SaveManagerオブジェクトを選択
  2. InspectorのSaveManagerコンポーネントでPrestige ManagerにPrestigeManagerをドラッグ&ドロップ

5. SettingsManagerの設定

5-1. PrestigeManagerの参照追加

  1. SettingsManagerオブジェクトを選択
  2. InspectorのSettingsManagerコンポーネントでPrestige ManagerにPrestigeManagerをドラッグ&ドロップ

5-2. 転生ステータス表示用UIの作成

SettingsManagerのパネル内に転生ステータス表示用のTextMeshProUGUI要素を追加:

5-3. SettingsManagerの参照設定

InspectorのSettingsManagerコンポーネントで以下を設定:

転生ステータス

  • Prestige HP Text: PrestigeHPTextをドラッグ&ドロップ
  • Prestige Attack Text: PrestigeAttackTextをドラッグ&ドロップ
  • Prestige Defense Text: PrestigeDefenseTextをドラッグ&ドロップ
  • Prestige Critical Rate Text: PrestigeCriticalRateTextをドラッグ&ドロップ
  • Prestige Critical Damage Text: PrestigeCriticalDamageTextをドラッグ&ドロップ

動作確認

Playボタンを押してゲームを開始します。

転生パネル開閉ボタンをクリックしてパネルが開くことを確認

転生パネル内のマナ強化アイテムが表示されることを確認

現在ステージ4なので転生したらマナを4獲得できます!

転生後、ステージが1に戻り、レベルやGがリセットされています!

G強化やスキルの解放などもリセットされています。

転生を実行してマナを4獲得しました!

そのマナを使用し、強化もできました!

まとめ

今回はゲームにとって重要な「転生(Prestige)」システムを実装しました!

これにより、進行が詰まっても「マナ強化」によって確実に成長できます。

どんどん転生して、限界を突破していきましょう!

次回予告

次回からは、ゲームバランスやUIの調整などを行っていよいよ完成形に近づけていきます!

お楽しみに!

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