using System; using System.Collections; using AibisDream.Framework; using AibisDream.Kit; using AibisDream.SaveSystem; using UnityEngine; using UnityEngine.Playables; using UnityEngine.ResourceManagement.AsyncOperations; using Yarn.Unity; namespace AibisDream { public class SubwayCenter : Singleton { #region 部分索引 public SpriteRenderer newsSpriteRenderer; public PlayableDirector arriveStation; public static StateMachine StateMachine { get; private set; } private string _currentNewsSpriteId; #endregion public override void OnSingletonInit() { StateMachine = new StateMachine(CreateState); StartCoroutine(StateMachine.Init(OutSideState.Subway)); } private static IState CreateState(OutSideState nextState, string arg = "") { IState res = nextState switch { OutSideState.Subway => new SubwayState(), OutSideState.SubwayTV => new SubwayTVState(), _ => throw new ArgumentOutOfRangeException(nameof(nextState), nextState, null) }; res.SetArgs(arg); return res; } public IEnumerator ArriveAtStation() { arriveStation.Play(); yield return new WaitForSeconds((float) arriveStation.playableAsset.duration); } public IEnumerator SwitchNews(string spriteId) { if (string.IsNullOrWhiteSpace(spriteId)) { Debug.LogWarning("[SubwayCenter] spriteId 为空,无法切换新闻图片。"); yield break; } string addressableKey = $"Sprite/News[{spriteId}]"; var handle = ResourceSystem.LoadAsync(addressableKey); yield return handle; if (handle.Status != AsyncOperationStatus.Succeeded || handle.Result == null) { Debug.LogError($"[SubwayCenter] 加载新闻图片失败: {addressableKey}"); yield break; } if (newsSpriteRenderer == null) { Debug.LogWarning("[SubwayCenter] newsSpriteRenderer 未赋值,无法切换新闻图片。"); yield break; } newsSpriteRenderer.sprite = handle.Result; _currentNewsSpriteId = spriteId; } /// Captures the macro subway scene snapshot. public SubwaySnapshotDto CaptureSnapshot() { if (StateMachine == null || !StateMachine.HasState) { return null; } return new SubwaySnapshotDto { state = StateMachine.CurState.ToString(), args = "", newsSpriteId = _currentNewsSpriteId }; } /// Restores the macro subway scene snapshot by jumping directly to the target state. public IEnumerator RestoreSnapshot(SubwaySnapshotDto dto) { if (dto == null || string.IsNullOrEmpty(dto.state)) { yield break; } if (!Enum.TryParse(dto.state, out var state)) { Debug.LogWarning($"[SubwayCenter] Could not parse OutSideState: {dto.state}"); yield break; } yield return StateMachine.SwitchStateImmediate(state, dto.args ?? ""); if (!string.IsNullOrEmpty(dto.newsSpriteId)) { yield return SwitchNews(dto.newsSpriteId); } } } public struct SubwayState : IState { public OutSideState GetState => OutSideState.Subway; public IEnumerator Enter() { yield return CameraKit.Instance.SwitchCamera(CameraEnum.Subway); DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.Subway)); } public IEnumerator EnterImmediate() { yield return CameraKit.Instance.SwitchCamera(CameraEnum.Subway, true); DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.Subway)); } } public struct SubwayTVState : IState { public OutSideState GetState => OutSideState.SubwayTV; public IEnumerator Enter() { yield return CameraKit.Instance.SwitchCamera(CameraEnum.SubwayTV); // 要加载气泡吗? DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.SubwayTV)); } public IEnumerator EnterImmediate() { yield return CameraKit.Instance.SwitchCamera(CameraEnum.SubwayTV, true); DialogUIManager.Instance.LoadBubbles(BubbleSlotKit.Instance.CollectData(BubbleSlotEnum.SubwayTV)); } } public enum OutSideState { Subway, SubwayTV } public static class SubwayYarnCommand { [YarnCommand("switch_outside_to")] public static IEnumerator SwitchOutsideTo(string targetStateStr) { if (!Enum.TryParse(targetStateStr, out OutSideState targetState)) { Debug.Log($"{targetStateStr}不在OutSideState枚举中"); yield break; } yield return SubwayCenter.StateMachine.SwitchState(targetState); } [YarnCommand("arrive_at_station")] public static IEnumerator ArriveAtStation() { return SubwayCenter.Instance.ArriveAtStation(); } [YarnCommand("switch_news")] public static IEnumerator SwitchNews(string spriteId) { if (SubwayCenter.Instance == null) { Debug.LogError("[SubwayYarnCommand] SubwayCenter 实例不存在。"); yield break; } yield return SubwayCenter.Instance.SwitchNews(spriteId); } } }