ふりかえり
前回は、装備を集めるための新しい挑戦場所「遺跡」を実装しました!
遺跡では特別なモンスターが出現し、防具がドロップする仕組みを導入しました。
これによりゲームの進行に新たな目標が生まれ、プレイに深みが増したと思います。
ステータス保存機能を実装!
今回は、遺跡挑戦をより快適にするためのキーフィーチャー「ステータス保存機能」を実装します。
このゲームには「転生」システムがあり、転生を行うと一度レベルや強化値がリセットされ、一時的に弱体化します。
その状態で遺跡に挑むと、敵に歯が立たない場合があります。
そこで登場するのが、この「ステータス保存」システムです。
ステータス保存機能とは?
要点は以下の通りです。
① 自分の最強だと思うタイミングでステータスを保存できる
・レベル
・基礎ステータス(HP / 攻撃 / 防御 / 会心系)
・ゴールド強化、アーティファクト強化、マナ強化
・装備している防具
・装備しているオーブ
これらを「スナップショット」として記録します。
② 保存したステータスで遺跡に挑戦できる
転生直後でも、記録しておいた全盛期のステータスで遺跡に出撃可能になります。
ステータス保存がもたらすメリット
● 遺跡挑戦のストレスが激減!
「鍵が回復してるのに転生直後だから弱くて行けない…」
という悩みを完全解消。
● SNSシェアで広がりやすくなる!
ステータス保存画面には
保存時のステータス+装備一覧(オーブ・防具) が表示されます。
スクショ映えするため、Xで自慢しやすく、
口コミでの拡散効果も狙えるようになります。
スクリプト
主に2つのスクリプトを使って実装しました。
- PlayerManager
- RegisterPlayerStats() → 「今のプレイヤーのステータス+強化値+装備」を登録用スナップショットとして保存
- GetRegisteredStats() → 登録済みステータスから最終的なHP/攻撃/防御/会心を計算して返す
- SavePreDungeonStats() / RestorePreDungeonStats() → 遺跡に入る前の状態を保存/遺跡から帰ってきたら元に戻す
- ApplyRegisteredStats() → 登録ステータスを実際の player に適用(遺跡挑戦用)
- DungeonUIManager
- 「ステータス登録」ボタンで PlayerManager.RegisterPlayerStats() を呼ぶ
- 遺跡ボタンを押したときに GetRegisteredStats() で 「登録済みか?」をチェック → 未登録なら警告パネルを出して遺跡に入れない
PlayerManager:ステータス登録のコアコード
登録用のデータとメインメソッド
public class PlayerManager : MonoBehaviour
{
public PlayerData player;
public PlayerUIManager playerUIManager;
public BattleLogManager battleLogManager;
public SaveManager saveManager;
// --- 遺跡用に登録するステータス(スナップショット) ---
private int registeredLevel;
// 基礎ステータス
private int registeredBaseMaxHP;
private int registeredBaseAttack;
private int registeredBaseDefense;
private float registeredBaseCriticalRate;
private float registeredBaseCriticalDamageMultiplier;
// G強化
private int registeredGPowerUpHP;
private int registeredGPowerUpAttack;
private int registeredGPowerUpDefense;
private float registeredGPowerUpCriticalRate;
private float registeredGPowerUpCriticalDamage;
private float registeredGPowerUpHPPercentage;
private float registeredGPowerUpAttackPercentage;
private float registeredGPowerUpDefensePercentage;
// AF強化
private int registeredArtifactPowerUpHP;
private int registeredArtifactPowerUpAttack;
private int registeredArtifactPowerUpDefense;
private float registeredArtifactPowerUpCriticalRate;
private float registeredArtifactPowerUpCriticalDamage;
private float registeredArtifactPowerUpHPPercentage;
private float registeredArtifactPowerUpAttackPercentage;
private float registeredArtifactPowerUpDefensePercentage;
// マナ強化
private int registeredPrestigePowerUpHP;
private int registeredPrestigePowerUpAttack;
private int registeredPrestigePowerUpDefense;
private float registeredPrestigePowerUpCriticalRate;
private float registeredPrestigePowerUpCriticalDamage;
private float registeredPrestigePowerUpHPPercentage;
private float registeredPrestigePowerUpAttackPercentage;
private float registeredPrestigePowerUpDefensePercentage;
// オーブ効果
private float registeredOrbPowerUpHPPercentage;
private float registeredOrbPowerUpAttackPercentage;
private float registeredOrbPowerUpDefensePercentage;
private float registeredOrbPowerUpCriticalRate;
private float registeredOrbPowerUpCriticalDamage;
// 防具効果
private float registeredArmorPowerUpHPPercentage;
private float registeredArmorPowerUpAttackPercentage;
private float registeredArmorPowerUpDefensePercentage;
private float registeredArmorPowerUpCriticalRate;
private float registeredArmorPowerUpCriticalDamage;
// 登録時の装備スナップショット
private int registeredEquippedOrbIndex = -1;
private Dictionary<ArmorSlotType, int> registeredEquippedArmorIndices
= new Dictionary<ArmorSlotType, int>();
private OrbData registeredEquippedOrb = null;
private Dictionary<ArmorSlotType, ArmorData> registeredEquippedArmors
= new Dictionary<ArmorSlotType, ArmorData>();
// --- ステータス登録(現在のビルドをスナップショット) ---
public void RegisterPlayerStats()
{
if (player == null) return;
// レベル
registeredLevel = player.level;
// 基礎ステータス
registeredBaseMaxHP = player.baseMaxHP;
registeredBaseAttack = player.baseAttack;
registeredBaseDefense = player.baseDefense;
registeredBaseCriticalRate = player.baseCriticalRate;
registeredBaseCriticalDamageMultiplier = player.baseCriticalDamageMultiplier;
// G強化
registeredGPowerUpHP = player.gPowerUpHP;
registeredGPowerUpAttack = player.gPowerUpAttack;
registeredGPowerUpDefense = player.gPowerUpDefense;
registeredGPowerUpCriticalRate = player.gPowerUpCriticalRate;
registeredGPowerUpCriticalDamage = player.gPowerUpCriticalDamage;
registeredGPowerUpHPPercentage = player.gPowerUpHPPercentage;
registeredGPowerUpAttackPercentage= player.gPowerUpAttackPercentage;
registeredGPowerUpDefensePercentage= player.gPowerUpDefensePercentage;
// AF強化
registeredArtifactPowerUpHP = player.artifactPowerUpHP;
registeredArtifactPowerUpAttack = player.artifactPowerUpAttack;
registeredArtifactPowerUpDefense = player.artifactPowerUpDefense;
registeredArtifactPowerUpCriticalRate = player.artifactPowerUpCriticalRate;
registeredArtifactPowerUpCriticalDamage = player.artifactPowerUpCriticalDamage;
registeredArtifactPowerUpHPPercentage = player.artifactPowerUpHPPercentage;
registeredArtifactPowerUpAttackPercentage= player.artifactPowerUpAttackPercentage;
registeredArtifactPowerUpDefensePercentage= player.artifactPowerUpDefensePercentage;
// マナ強化
registeredPrestigePowerUpHP = player.prestigePowerUpHP;
registeredPrestigePowerUpAttack = player.prestigePowerUpAttack;
registeredPrestigePowerUpDefense = player.prestigePowerUpDefense;
registeredPrestigePowerUpCriticalRate = player.prestigePowerUpCriticalRate;
registeredPrestigePowerUpCriticalDamage = player.prestigePowerUpCriticalDamage;
registeredPrestigePowerUpHPPercentage = player.prestigePowerUpHPPercentage;
registeredPrestigePowerUpAttackPercentage= player.prestigePowerUpAttackPercentage;
registeredPrestigePowerUpDefensePercentage= player.prestigePowerUpDefensePercentage;
// オーブ効果
registeredOrbPowerUpHPPercentage = player.orbPowerUpHPPercentage;
registeredOrbPowerUpAttackPercentage = player.orbPowerUpAttackPercentage;
registeredOrbPowerUpDefensePercentage = player.orbPowerUpDefensePercentage;
registeredOrbPowerUpCriticalRate = player.orbPowerUpCriticalRate;
registeredOrbPowerUpCriticalDamage= player.orbPowerUpCriticalDamage;
// 防具効果
registeredArmorPowerUpHPPercentage = player.armorPowerUpHPPercentage;
registeredArmorPowerUpAttackPercentage= player.armorPowerUpAttackPercentage;
registeredArmorPowerUpDefensePercentage= player.armorPowerUpDefensePercentage;
registeredArmorPowerUpCriticalRate = player.armorPowerUpCriticalRate;
registeredArmorPowerUpCriticalDamage = player.armorPowerUpCriticalDamage;
// 装備中のオーブをスナップショット
registeredEquippedOrb = null;
registeredEquippedOrbIndex = -1;
if (OrbManager.Instance != null && OrbManager.Instance.equippedOrb != null)
{
registeredEquippedOrb = OrbManager.Instance.equippedOrb.Clone();
registeredEquippedOrbIndex = OrbManager.Instance.ownedOrbs
.IndexOf(OrbManager.Instance.equippedOrb);
}
// 装備中の防具をスナップショット
registeredEquippedArmors.Clear();
registeredEquippedArmorIndices.Clear();
if (ArmorManager.Instance != null)
{
foreach (ArmorSlotType slot in System.Enum.GetValues(typeof(ArmorSlotType)))
{
if (ArmorManager.Instance.equippedArmors.ContainsKey(slot) &&
ArmorManager.Instance.equippedArmors[slot] != null)
{
var armor = ArmorManager.Instance.equippedArmors[slot];
registeredEquippedArmors[slot] = armor.Clone();
int idx = ArmorManager.Instance.ownedArmors[slot].IndexOf(armor);
registeredEquippedArmorIndices[slot] = idx;
}
else
{
registeredEquippedArmors[slot] = null;
registeredEquippedArmorIndices[slot] = -1;
}
}
}
// セーブ
if (saveManager != null)
{
saveManager.SaveRegisteredStatsImmediate();
}
// ログ
if (battleLogManager != null)
{
battleLogManager.AddLog(
$"<color=cyan>ステータスを登録しました(Lv.{registeredLevel})</color>",
Color.cyan
);
}
}
DungeonUIManager:UIからの登録&チェック部分
ステータス登録 UI
public class DungeonUIManager : MonoBehaviour
{
[Header("ステータス登録")]
public Button statusRegistrationPanelButton;
public GameObject statusRegistrationPanel;
public Button statusRegistrationCloseButton;
public Button statusRegistrationButton;
public TextMeshProUGUI registeredStatusText;
[Header("ステータス未登録警告")]
public GameObject statusNotRegisteredPanel;
public TextMeshProUGUI statusNotRegisteredText;
public Button statusNotRegisteredCloseButton;
public PlayerManager playerManager;
private DungeonType selectedDungeonType;
private void Start()
{
// パネル開閉
statusRegistrationPanelButton.onClick.AddListener(OpenStatusRegistrationPanel);
statusRegistrationCloseButton.onClick.AddListener(CloseStatusRegistrationPanel);
// 「ステータス登録」ボタン
statusRegistrationButton.onClick.AddListener(RegisterPlayerStats);
// 警告パネル
statusNotRegisteredCloseButton.onClick.AddListener(CloseStatusNotRegisteredPanel);
statusRegistrationPanel.SetActive(false);
statusNotRegisteredPanel.SetActive(false);
}
// パネルを開く
public void OpenStatusRegistrationPanel()
{
statusRegistrationPanel.SetActive(true);
UpdateRegisteredStatusDisplay();
}
// パネルを閉じる
public void CloseStatusRegistrationPanel()
{
statusRegistrationPanel.SetActive(false);
}
// ボタンから呼ばれる「ステータス登録」
private void RegisterPlayerStats()
{
if (playerManager == null) return;
playerManager.RegisterPlayerStats();
UpdateRegisteredStatusDisplay();
}
// 登録済みステータスの表示更新
private void UpdateRegisteredStatusDisplay()
{
if (playerManager == null || registeredStatusText == null) return;
var stats = playerManager.GetRegisteredStats();
string name = playerManager.player != null &&
!string.IsNullOrWhiteSpace(playerManager.player.name)
? playerManager.player.name
: "勇者";
if (stats.level > 0)
{
registeredStatusText.text =
$"【登録ステータス】\n{name}\n" +
$"Lv.{stats.level}\n" +
$"HP: {stats.maxHP}\n" +
$"攻撃: {stats.attack}\n" +
$"防御: {stats.defense}\n" +
$"会心率: {stats.criticalRate * 100f:F1}%\n" +
$"会心ダメージ: {stats.criticalDamage * 100f:F1}%";
}
else
{
registeredStatusText.text =
$"【登録ステータス】\n{name}\nステータス未登録";
}
}
// ステータス未登録警告
private void ShowStatusNotRegisteredPanel()
{
if (statusNotRegisteredPanel == null) return;
statusNotRegisteredPanel.SetActive(true);
if (statusNotRegisteredText != null)
{
statusNotRegisteredText.text = "ステータス保存してください。";
}
}
private void CloseStatusNotRegisteredPanel()
{
if (statusNotRegisteredPanel == null) return;
statusNotRegisteredPanel.SetActive(false);
}
}
遺跡挑戦時の一連の流れ
- ステータス登録
- プレイヤーは「ステータス登録」パネルから 現在のレベル・基礎ステータス・各種強化値・オーブ・防具構成を PlayerManager.RegisterPlayerStats() によってスナップショット保存する。
- 登録された内容は GetRegisteredStats() で最終ステータスとして復元でき、 UI 上にも表示される。
- 遺跡入場前チェック
- 遺跡の種類ボタンを押して難易度選択に進む前に、 GetRegisteredStats() の level を見て 登録済みかどうか を判定する。
- 未登録なら警告パネルを表示し、遺跡には入れない。
- 遺跡に入るとき(DungeonManager側連携)
- PlayerManager.SavePreDungeonStats() で現在の状態を保存。
- その直後 PlayerManager.ApplyRegisteredStats() で 登録ビルドを実際の player に適用し、遺跡専用のステータスで挑戦する。
- 遺跡から戻るとき
- クリア/敗北に関わらず、最後に PlayerManager.RestorePreDungeonStats() を呼び出し、 遺跡入場前のステータス・強化値・お金などを元通りに復元する。
Unityで動作確認
左上のステータス登録ボタンを押すと、保存された
- ステータス
- オーブ
- 防具一覧
が見やすく表示されます。
この画面が“強さの証明”になるので、
スクショしてSNSに投稿するユーザー体験を想定しています。

まとめ
今回は装備機能のコアとなるステータス保存機能を実装しました!
遺跡挑戦がスムーズになるだけでなく、
SNSシェアにつながる魅力的な要素にもなったと思います。
次回予告
次はいよいよ、
実際の防具システムそのものを実装していきます!
自分だけの最強装備を揃えるワクワク感を
形にしていきますので、ぜひお楽しみに!
