Files
zeling_v2/Assets/_Game/Scripts/World/DeathShadeManager.cs
2026-05-20 15:10:35 +08:00

114 lines
3.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 中按需生成
}
}
}