using System; using System.Collections; using AibisDream.Framework; using AibisDream.Kit; using Cinemachine; using UnityEngine; using UnityEngine.Playables; using UnityEngine.ResourceManagement.AsyncOperations; using Yarn.Unity; namespace AibisDream { public class SubwayCenter : Singleton { #region 部分索引 public BubbleSlotGroup subwaySlots; public BubbleSlotGroup tvSlots; public CinemachineVirtualCamera subwayCam; public CinemachineVirtualCamera tvCam; public SpriteRenderer newsSpriteRenderer; public PlayableDirector arriveStation; public static StateMachine StateMachine { get; private set; } #endregion public override void OnSingletonInit() { CameraKit.Instance.RegisterCamera(CameraEnum.Subway, subwayCam); CameraKit.Instance.RegisterCamera(CameraEnum.SubwayTV, tvCam); StateMachine = new StateMachine(CreateState); StartCoroutine(StateMachine.Init(OutSideState.Subway)); } public override void OnSingletonDestroy() { CameraKit.Instance.UnRegisterCamera(CameraEnum.SubwayTV); CameraKit.Instance.UnRegisterCamera(CameraEnum.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; } } public struct SubwayState : IState { public OutSideState GetState => OutSideState.Subway; public IEnumerator Enter() { yield return CameraKit.Instance.SwitchCamera(CameraEnum.Subway, true); DialogUIManager.Instance.LoadBubbles(SubwayCenter.Instance.subwaySlots.CollectData()); } } public struct SubwayTVState : IState { public OutSideState GetState => OutSideState.SubwayTV; public IEnumerator Enter() { yield return CameraKit.Instance.SwitchCamera(CameraEnum.SubwayTV); // 要加载气泡吗? DialogUIManager.Instance.LoadBubbles(SubwayCenter.Instance.tvSlots.CollectData()); } } 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); } } }