存档完善和修复

This commit is contained in:
2026-05-20 15:10:35 +08:00
parent 84528403ec
commit ec633d9b79
17 changed files with 254 additions and 67 deletions

View File

@@ -0,0 +1,113 @@
using UnityEngine;
using UnityEngine.SceneManagement;
using BaseGames.Core;
using BaseGames.Core.Events;
using BaseGames.Core.Save;
namespace BaseGames.World
{
/// <summary>
/// 管理死亡遗骸Death Shade的生命周期与持久化。
///
/// 挂载位置Persistent 场景的根 GameObjectDontDestroyOnLoad
///
/// 流程:
/// 玩家死亡 → OnPlayerDied记录死亡位置与灵珠量在当前场景生成遗骸。
/// 切换场景 → OnSceneLoaded若新场景即遗骸所在场景自动生成遗骸。
/// 回收遗骸 → OnShadeCollected清除待存储的遗骸数据。
/// 存档 → OnSave将遗骸数据null = 无遗骸)写入 SaveData.Player.DeathShade。
/// 读档 → OnLoad从 SaveData 恢复遗骸数据;实际 GameObject 在下次进入该场景时生成。
/// </summary>
public class DeathShadeManager : SaveableMonoBehaviour
{
[SerializeField] private DeathShade _shadePrefab;
[SerializeField] private VoidEventChannelSO _onPlayerDied;
[SerializeField] private StringEventChannelSO _onShadeCollected;
private DeathShadeSaveData _pendingSave;
private DeathShade _activeShade;
private readonly CompositeDisposable _subs = new();
protected override void OnEnable()
{
base.OnEnable();
_onPlayerDied? .Subscribe(OnPlayerDied) .AddTo(_subs);
_onShadeCollected?.Subscribe(OnShadeCollected).AddTo(_subs);
SceneManager.sceneLoaded += OnSceneLoaded;
}
protected override void OnDisable()
{
base.OnDisable();
_subs.Clear();
SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void OnPlayerDied()
{
var playerGo = GameObject.FindWithTag("Player");
if (playerGo == null) return;
int lingZhu = playerGo.GetComponent<ILingZhuProvider>()?.CurrentLingZhu ?? 0;
var pos = (Vector2)playerGo.transform.position;
string sceneId = SceneManager.GetActiveScene().name;
if (_activeShade != null)
{
Destroy(_activeShade.gameObject);
_activeShade = null;
}
_pendingSave = new DeathShadeSaveData
{
PosX = pos.x,
PosY = pos.y,
SceneId = sceneId,
LingZhuAmount = lingZhu,
};
TrySpawnShade(sceneId);
}
private void OnSceneLoaded(Scene scene, LoadSceneMode _)
{
_activeShade = null; // 前一场景的 GameObject 已被 Unity 卸载
TrySpawnShade(scene.name);
}
private void TrySpawnShade(string sceneName)
{
if (_shadePrefab == null || _pendingSave == null) return;
if (_pendingSave.SceneId != sceneName) return;
_activeShade = Instantiate(_shadePrefab);
_activeShade.Initialize(
_pendingSave.LingZhuAmount,
_pendingSave.SceneId,
new Vector2(_pendingSave.PosX, _pendingSave.PosY));
}
private void OnShadeCollected(string _)
{
_pendingSave = null;
_activeShade = null;
}
public override void OnSave(SaveData data)
{
data.Player.DeathShade = _pendingSave;
}
public override void OnLoad(SaveData data)
{
if (_activeShade != null)
{
Destroy(_activeShade.gameObject);
_activeShade = null;
}
_pendingSave = data.Player.DeathShade;
// 遗骸 GameObject 将在 OnSceneLoaded 中按需生成
}
}
}