using UnityEngine; using UnityEngine.SceneManagement; using BaseGames.Core; using BaseGames.Core.Events; using BaseGames.Core.Save; namespace BaseGames.World { /// /// 管理死亡遗骸(Death Shade)的生命周期与持久化。 /// /// 挂载位置:Persistent 场景的根 GameObject(DontDestroyOnLoad)。 /// /// 流程: /// 玩家死亡 → OnPlayerDied:记录死亡位置与灵珠量,在当前场景生成遗骸。 /// 切换场景 → OnSceneLoaded:若新场景即遗骸所在场景,自动生成遗骸。 /// 回收遗骸 → OnShadeCollected:清除待存储的遗骸数据。 /// 存档 → OnSave:将遗骸数据(null = 无遗骸)写入 SaveData.Player.DeathShade。 /// 读档 → OnLoad:从 SaveData 恢复遗骸数据;实际 GameObject 在下次进入该场景时生成。 /// 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()?.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 中按需生成 } } }