diff --git a/Assets/Scripts/FixSystemNew/FixSceneDirector.cs b/Assets/Scripts/FixSystemNew/FixSceneDirector.cs index c666f521d..2b052e274 100644 --- a/Assets/Scripts/FixSystemNew/FixSceneDirector.cs +++ b/Assets/Scripts/FixSystemNew/FixSceneDirector.cs @@ -19,7 +19,7 @@ namespace AibisDream.FixSystem public IEnumerator Init(FixSceneMode initMode) { - yield return TransitionInternal(initMode, "", FixTransitionMode.Animated); + yield return TransitionInternal(initMode, "", FixTransitionMode.Immediate); } public IEnumerator TransitionTo(FixSceneMode nextMode, string args = "") diff --git a/Assets/Scripts/FixSystemNew/FixSystemCenter.cs b/Assets/Scripts/FixSystemNew/FixSystemCenter.cs index 00b37dfe1..484005444 100644 --- a/Assets/Scripts/FixSystemNew/FixSystemCenter.cs +++ b/Assets/Scripts/FixSystemNew/FixSystemCenter.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using AibisDream; using AibisDream.Framework; using AibisDream.Kit; using AibisDream.SaveSystem; @@ -7,12 +8,16 @@ using UnityEngine; namespace AibisDream.FixSystem { - public class FixSystemCenter : Singleton + public class FixSystemCenter : Singleton, ISceneDialogueGate { public FixSceneMode CurrentMode => Director.CurrentMode; public FixSceneMode defaultMode = FixSceneMode.Default; + public bool IsDirectorReady { get; private set; } + + public bool IsDialogueReady => IsDirectorReady; + public static IOCContainer SystemDic = new(); public static FixSceneContext Context; public static FixSceneDirector Director; @@ -22,6 +27,7 @@ namespace AibisDream.FixSystem SystemDic ??= new IOCContainer(); Context = new FixSceneContext(SystemDic); Director = new FixSceneDirector(); + IsDirectorReady = false; } private void Start() @@ -31,11 +37,19 @@ namespace AibisDream.FixSystem return; } - StartCoroutine(Director.Init(defaultMode)); + StartCoroutine(InitDirectorRoutine()); + } + + private IEnumerator InitDirectorRoutine() + { + IsDirectorReady = false; + yield return Director.Init(defaultMode); + IsDirectorReady = true; } public override void OnSingletonDestroy() { + IsDirectorReady = false; CameraKit.Instance.RemoveAllCam(); BubbleSlotKit.Instance.RemoveAll(); GameManager.Instance.StartCoroutine(Director.QuitCurrentMode()); @@ -77,6 +91,7 @@ namespace AibisDream.FixSystem } yield return Director.TransitionToImmediate(mode, dto.args ?? ""); + IsDirectorReady = true; } } } diff --git a/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs b/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs index f90048f9e..327117e57 100644 --- a/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs +++ b/Assets/Scripts/FixSystemNew/States/CoreFixCues.cs @@ -153,9 +153,9 @@ namespace AibisDream.FixSystem if (!CameraKit.Instance.EqualToCameraState(CameraEnum.DreamCamera)) { yield return CameraKit.Instance.SwitchCamera(CameraEnum.DreamCamera); - - BubbleSlotKit.Instance.LoadBubbles(BubbleSlotEnum.Open); } + + BubbleSlotKit.Instance.LoadBubbles(BubbleSlotEnum.Open); } public IEnumerator EnterImmediate(FixTransition transition) diff --git a/Assets/Scripts/Game Loop/GameManager.cs b/Assets/Scripts/Game Loop/GameManager.cs index 6d42371e8..951947f3b 100644 --- a/Assets/Scripts/Game Loop/GameManager.cs +++ b/Assets/Scripts/Game Loop/GameManager.cs @@ -110,9 +110,57 @@ namespace AibisDream ChapterController.Instance.UnlockChapter(_currentTalkSceneSo.Value); yield return UIManager.Instance.GetPanel().FadeInAsync(0.5f); yield return SceneLoader.Instance.LoadSceneAsync(_currentTalkSceneSo.Value.firstSceneName); + yield return WaitForSceneDialogueReady(); DialogController.Instance.StartDialog(_currentTalkSceneSo.Value.yarnProject); } + /// + /// 等待新场景 Awake/Start 完成,并等待场景协调器(Fix / Subway / Outside 等)就绪后再开对话。 + /// + private static IEnumerator WaitForSceneDialogueReady() + { + yield return null; + + if (SceneHasDialogueGate()) + { + while (HasPendingDialogueGate()) + { + yield return null; + } + } + else + { + yield return null; + } + } + + private static bool SceneHasDialogueGate() + { + return FixSystemCenter.Instance != null + || SubwayCenter.Instance != null + || OutsideCenter.Instance != null; + } + + private static bool HasPendingDialogueGate() + { + if (FixSystemCenter.Instance is ISceneDialogueGate { IsDialogueReady: false }) + { + return true; + } + + if (SubwayCenter.Instance is ISceneDialogueGate { IsDialogueReady: false }) + { + return true; + } + + if (OutsideCenter.Instance is ISceneDialogueGate { IsDialogueReady: false }) + { + return true; + } + + return false; + } + public void PauseGame() { // 系统暂停 @@ -234,6 +282,7 @@ namespace AibisDream ChapterController.Instance.UnlockChapter(_currentTalkSceneSo.Value); yield return UIManager.Instance.GetPanel().FadeInAsync(); yield return SceneLoader.Instance.LoadSceneAsync(_currentTalkSceneSo.Value.firstSceneName); + yield return WaitForSceneDialogueReady(); DialogController.Instance.StartDialog(_currentTalkSceneSo.Value.yarnProject); } else diff --git a/Assets/Scripts/SceneManagement/ISceneDialogueGate.cs b/Assets/Scripts/SceneManagement/ISceneDialogueGate.cs new file mode 100644 index 000000000..4ad0daad5 --- /dev/null +++ b/Assets/Scripts/SceneManagement/ISceneDialogueGate.cs @@ -0,0 +1,10 @@ +namespace AibisDream +{ + /// + /// 场景级协调器:在 StartDialog 之前完成相机、Bubble 等初始化。 + /// + public interface ISceneDialogueGate + { + bool IsDialogueReady { get; } + } +} diff --git a/Assets/Scripts/SceneManagement/ISceneDialogueGate.cs.meta b/Assets/Scripts/SceneManagement/ISceneDialogueGate.cs.meta new file mode 100644 index 000000000..5d13b834a --- /dev/null +++ b/Assets/Scripts/SceneManagement/ISceneDialogueGate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fec846dedd21efd4eafc0f3fc6ff6f82 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/SceneManagement/SceneCenter/OutsideCenter.cs b/Assets/Scripts/SceneManagement/SceneCenter/OutsideCenter.cs index 46ebaa393..909534473 100644 --- a/Assets/Scripts/SceneManagement/SceneCenter/OutsideCenter.cs +++ b/Assets/Scripts/SceneManagement/SceneCenter/OutsideCenter.cs @@ -3,11 +3,20 @@ using AibisDream.Kit; namespace AibisDream { - public class OutsideCenter : Singleton + public class OutsideCenter : Singleton, ISceneDialogueGate { + public bool IsDialogueReady { get; private set; } + public override void OnSingletonInit() { + IsDialogueReady = false; BubbleSlotKit.Instance.LoadBubbles(BubbleSlotEnum.Outside); + IsDialogueReady = true; + } + + public override void OnSingletonDestroy() + { + IsDialogueReady = false; } } } diff --git a/Assets/Scripts/SceneManagement/SceneCenter/SubwayCenter.cs b/Assets/Scripts/SceneManagement/SceneCenter/SubwayCenter.cs index fcaa4c76c..1aaf11636 100644 --- a/Assets/Scripts/SceneManagement/SceneCenter/SubwayCenter.cs +++ b/Assets/Scripts/SceneManagement/SceneCenter/SubwayCenter.cs @@ -10,7 +10,7 @@ using Yarn.Unity; namespace AibisDream { - public class SubwayCenter : Singleton + public class SubwayCenter : Singleton, ISceneDialogueGate { #region 部分索引 @@ -20,6 +20,8 @@ namespace AibisDream public static StateMachine StateMachine { get; private set; } + public bool IsDialogueReady { get; private set; } + private string _currentNewsSpriteId; #endregion @@ -27,7 +29,20 @@ namespace AibisDream public override void OnSingletonInit() { StateMachine = new StateMachine(CreateState); - StartCoroutine(StateMachine.Init(OutSideState.Subway)); + IsDialogueReady = false; + StartCoroutine(InitStateMachineRoutine()); + } + + private IEnumerator InitStateMachineRoutine() + { + IsDialogueReady = false; + yield return StateMachine.Init(OutSideState.Subway); + IsDialogueReady = true; + } + + public override void OnSingletonDestroy() + { + IsDialogueReady = false; } private static IState CreateState(OutSideState nextState, string arg = "")