Пример #1
0
        private IEnumerator AppendCore(IObserver <SceneInstance> observer, Scenes?identifier, bool activeOnLoad)
        {
            if (!identifier.HasValue)
            {
                yield break;
            }

            SceneInstance sceneInstance = null;

            var diagnostics = new TimeDiagnostics();

            diagnostics.Begin(TimeDiagnostics.Measure.Append);

            var loadYield = LoadScene(identifier.Value, LoadSceneMode.Additive).ToYieldInstruction(false);

            while (!loadYield.IsDone)
            {
                yield return(null);
            }

            if (loadYield.HasError)
            {
                OnLoadError(loadYield.Error, identifier);
            }

            if (loadYield.HasResult)
            {
                sceneInstance = loadYield.Result;

                appendSceneInstances.Add(sceneInstance);

                diagnostics.Finish(TimeDiagnostics.Measure.Append);

                var additiveTime = diagnostics.GetTime(TimeDiagnostics.Measure.Append);

                var message = string.Format("{0} ({1:F2}ms)(Additive)", identifier.Value, additiveTime);

                UnityConsole.Event(ConsoleEventName, ConsoleEventColor, message);

                if (activeOnLoad)
                {
                    sceneInstance.Enable();
                }
            }

            observer.OnNext(sceneInstance);
            observer.OnCompleted();
        }
Пример #2
0
        private IEnumerator AppendCore(IObserver <SceneInstance> observer, Scenes?identifier, bool activeOnLoad)
        {
            if (!identifier.HasValue)
            {
                yield break;
            }

            SceneInstance sceneInstance = null;

            var diagnostics = new TimeDiagnostics();

            diagnostics.Begin(TimeDiagnostics.Measure.Append);

            var loadYield = LoadScene(identifier.Value, LoadSceneMode.Additive).ToYieldInstruction();

            yield return(loadYield);

            if (loadYield.HasResult)
            {
                sceneInstance = loadYield.Result;

                diagnostics.Finish(TimeDiagnostics.Measure.Append);

                var additiveTime = diagnostics.GetTime(TimeDiagnostics.Measure.Append);

                UnityConsole.Event(ConsoleEventName, ConsoleEventColor, "{0} ({1}ms)(Additive)", identifier.Value, additiveTime);
            }

            if (activeOnLoad)
            {
                sceneInstance.Enable();
            }

            observer.OnNext(sceneInstance);
            observer.OnCompleted();
        }
Пример #3
0
        private IEnumerator TransitionCore <TArgument>(TArgument sceneArgument, LoadSceneMode mode, bool isSceneBack, bool registerHistory) where TArgument : ISceneArgument
        {
            if (!sceneArgument.Identifier.HasValue)
            {
                yield break;
            }

            // プリロード停止.
            if (preLoadDisposable != null)
            {
                preLoadDisposable.Dispose();
                preLoadDisposable = null;
            }

            TransitionTarget = sceneArgument.Identifier;

            var prevSceneArgument = currentSceneArgument;

            currentSceneArgument = sceneArgument;

            var diagnostics = new TimeDiagnostics();

            var prev = current;

            // 現在のシーンを履歴に残さない場合は、既に登録済みの現在のシーン(history[要素数 - 1])を外す.
            if (!registerHistory && history.Any())
            {
                history.RemoveAt(history.Count - 1);
            }

            //====== Begin Transition ======

            diagnostics.Begin(TimeDiagnostics.Measure.Total);

            yield return(TransitionStart(currentSceneArgument).ToYieldInstruction());

            if (prev != null)
            {
                //====== Scene Leave ======

                diagnostics.Begin(TimeDiagnostics.Measure.Leave);

                // Leave通知.
                if (onLeave != null)
                {
                    onLeave.OnNext(prevSceneArgument);
                }

                // 現在のシーンの終了処理を実行.
                yield return(prev.Instance.LeaveAsync().ToYieldInstruction());

                // PlayerPrefsを保存.
                PlayerPrefs.Save();

                // Leave終了通知.
                if (onLeaveComplete != null)
                {
                    onLeaveComplete.OnNext(prevSceneArgument);
                }

                prev.Disable();

                diagnostics.Finish(TimeDiagnostics.Measure.Leave);
            }

            //====== Scene Unload ======

            // 不要なシーンをアンロード.
            var unloadScenes = loadedscenes.Values
                               // 遷移先のシーンではない.
                               .Where(x => x.Identifier != TransitionTarget)
                               // SceneBaseクラスが存在しない.
                               .Where(x => UnityUtility.IsNull(x.Instance))
                               // キャッシュ対象でない.
                               .Where(x => cacheScenes.All(y => y != x))
                               // 次のシーンのPreload対象ではない.
                               .Where(x => currentSceneArgument.PreLoadScenes.All(y => y != x.Identifier))
                               .ToArray();

            foreach (var unloadScene in unloadScenes)
            {
                yield return(UnloadScene(unloadScene).ToYieldInstruction());

                if (unloadScene.Identifier.HasValue)
                {
                    loadedscenes.Remove(unloadScene.Identifier.Value);
                }
            }

            //====== Load Next Scene ======

            diagnostics.Begin(TimeDiagnostics.Measure.Load);

            // 次のシーンを読み込み.
            var identifier = sceneArgument.Identifier.Value;

            var sceneInfo = loadedscenes.GetValueOrDefault(identifier);

            if (sceneInfo == null)
            {
                var loadYield = LoadScene(identifier, mode).ToYieldInstruction();

                yield return(loadYield);

                if (!loadYield.HasResult)
                {
                    yield break;
                }

                sceneInfo = loadYield.Result;

                if (sceneArgument.Cache)
                {
                    cacheScenes.Enqueue(sceneInfo);
                }
            }

            var scene = sceneInfo.GetScene();

            if (!scene.HasValue)
            {
                Debug.LogErrorFormat("[ {0} ] : Scene情報の取得に失敗しました.", identifier);

                yield break;
            }

            if (sceneInfo.Instance == null)
            {
                Debug.LogErrorFormat("[ {0} ] : SceneBase継承クラスが存在しません.", scene.Value.path);

                yield break;
            }

            SetSceneActive(scene);

            // 前のシーンからの引数を設定.
            sceneInfo.Instance.SetArgument(sceneArgument);

            // 現在のシーンとして登録.
            current = sceneInfo;

            // 次のシーンを履歴に登録.
            // シーン引数を保存する為遷移時に引数と一緒に履歴登録する為、履歴の最後尾は現在のシーンになる.
            if (current.Instance != null)
            {
                history.Add(currentSceneArgument);
            }

            // シーン読み込み後にAwake、Startが終わるのを待つ為1フレーム後に処理を再開.
            yield return(null);

            diagnostics.Finish(TimeDiagnostics.Measure.Load);

            //====== Scene Prepare ======

            diagnostics.Begin(TimeDiagnostics.Measure.Prepare);

            // Prepar通知.
            if (onPrepare != null)
            {
                onPrepare.OnNext(currentSceneArgument);
            }

            // 次のシーンの準備処理実行.
            if (current.Instance != null)
            {
                yield return(current.Instance.Prepare(isSceneBack).ToYieldInstruction());
            }

            // Prepar終了通知.
            if (onPrepareComplete != null)
            {
                onPrepareComplete.OnNext(currentSceneArgument);
            }

            diagnostics.Finish(TimeDiagnostics.Measure.Prepare);

            //====== Unload PrevScene ======

            // キャッシュ対象でない場合はアンロード.
            if (prevSceneArgument == null || !prevSceneArgument.Cache)
            {
                yield return(UnloadScene(prev).ToYieldInstruction());
            }

            //====== Scene Wait ======

            // メモリ解放.
            yield return(CleanUp().ToYieldInstruction());

            // 外部処理待機.
            yield return(Observable.FromMicroCoroutine(() => TransitionWait()).ToYieldInstruction());

            // シーンを有効化.
            sceneInfo.Enable();

            // シーン遷移完了.
            TransitionTarget = null;

            // シーン遷移終了.
            yield return(TransitionFinish(currentSceneArgument).ToYieldInstruction());

            //====== Scene Enter ======

            // Enter通知.
            if (onEnter != null)
            {
                onEnter.OnNext(currentSceneArgument);
            }

            // 次のシーンの開始処理実行.
            if (current.Instance != null)
            {
                current.Instance.Enter(isSceneBack);
            }

            // Enter終了通知.
            if (onEnterComplete != null)
            {
                onEnterComplete.OnNext(currentSceneArgument);
            }

            //====== Report ======

            diagnostics.Finish(TimeDiagnostics.Measure.Total);

            var prevScene = prev.Identifier;
            var nextScene = current.Identifier;

            var total  = diagnostics.GetTime(TimeDiagnostics.Measure.Total);
            var detail = diagnostics.BuildDetailText();

            UnityConsole.Event(ConsoleEventName, ConsoleEventColor, "{0} → {1} ({2:F2}ms)\n\n{3}", prevScene, nextScene, total, detail);

            //====== PreLoad ======

            preLoadDisposable = PreLoadScene(sceneArgument.PreLoadScenes)
                                .Subscribe(_ => preLoadDisposable = null)
                                .AddTo(Disposable);
        }