public LoadSceneWaitHandle LoadScene(string sceneName, LoadSceneMode mode = LoadSceneMode.Single, LoadSceneBehaviour behaviour = LoadSceneBehaviour.Async)
        {
            switch (behaviour)
            {
            case LoadSceneBehaviour.Standard:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                this.OnBeforeSceneLoaded(handle);
                SceneManager.LoadScene(sceneName, mode);
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), null);
                return(handle);
            }

            case LoadSceneBehaviour.Async:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                this.OnBeforeSceneLoaded(handle);
                var op = SceneManager.LoadSceneAsync(sceneName, mode);
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), op);
                return(handle);
            }

            case LoadSceneBehaviour.AsyncAndWait:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                this.OnBeforeSceneLoaded(handle);
                var op = SceneManager.LoadSceneAsync(sceneName, mode);
                op.allowSceneActivation = false;
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), op);
                return(handle);
            }
            }

            throw new System.InvalidOperationException("Unsupported LoadSceneBehaviour.");
        }
        protected virtual void OnBeforeSceneLoaded(LoadSceneWaitHandle handle)
        {
            var d = this.BeforeSceneLoaded;

            if (d == null)
            {
                return;
            }

            d(this, handle);
        }
        public LoadSceneWaitHandle LoadScene(int sceneBuildIndex, LoadSceneMode mode = LoadSceneMode.Single, LoadSceneBehaviour behaviour = LoadSceneBehaviour.Async)
        {
            if (sceneBuildIndex < 0 || sceneBuildIndex >= SceneManager.sceneCountInBuildSettings)
            {
                throw new System.IndexOutOfRangeException("sceneBuildIndex");
            }

            //string sceneName = "#" + sceneBuildIndex.ToString();
            string sceneName = SceneUtility.GetScenePathByBuildIndex(sceneBuildIndex);

            switch (behaviour)
            {
            case LoadSceneBehaviour.Standard:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                this.OnBeforeSceneLoaded(handle);
                SceneManager.LoadScene(sceneBuildIndex, mode);
                var scene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
                _table[scene] = handle;
                handle.Init(scene, null);
                return(handle);
            }

            case LoadSceneBehaviour.Async:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                this.OnBeforeSceneLoaded(handle);
                var op    = SceneManager.LoadSceneAsync(sceneBuildIndex, mode);
                var scene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
                _table[scene] = handle;
                handle.Init(scene, op);
                return(handle);
            }

            case LoadSceneBehaviour.AsyncAndWait:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                this.OnBeforeSceneLoaded(handle);
                var op = SceneManager.LoadSceneAsync(sceneBuildIndex, mode);
                op.allowSceneActivation = false;
                var scene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);
                _table[scene] = handle;
                handle.Init(scene, op);
                return(handle);
            }
            }

            throw new System.InvalidOperationException("Unsupported LoadSceneBehaviour.");
        }
        public static LoadSceneWaitHandle LoadScene(int sceneBuildIndex, LoadSceneMode mode, LoadSceneBehaviour behaviour)
        {
            if (sceneBuildIndex < 0 || sceneBuildIndex >= SceneManager.sceneCountInBuildSettings)
            {
                throw new System.IndexOutOfRangeException("sceneBuildIndex");
            }

            var manager = Services.Get <ISceneManager>();

            if (manager != null)
            {
                return(manager.LoadScene(sceneBuildIndex, mode, behaviour));
            }

            //string sceneName = "#" + sceneBuildIndex.ToString();
            string sceneName = SceneUtility.GetScenePathByBuildIndex(sceneBuildIndex);

            switch (behaviour)
            {
            case LoadSceneBehaviour.Standard:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                SceneManager.LoadScene(sceneBuildIndex, mode);
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), null);
                return(handle);
            }

            case LoadSceneBehaviour.Async:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                var op     = SceneManager.LoadSceneAsync(sceneBuildIndex, mode);
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), op);
                return(handle);
            }

            case LoadSceneBehaviour.AsyncAndWait:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                var op     = SceneManager.LoadSceneAsync(sceneBuildIndex, mode);
                op.allowSceneActivation = false;
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), op);
                return(handle);
            }
            }

            throw new System.InvalidOperationException("Unsupported LoadSceneBehaviour.");
        }
        public static LoadSceneWaitHandle LoadScene(string sceneName, LoadSceneMode mode, LoadSceneBehaviour behaviour)
        {
            var manager = Services.Get <ISceneManager>();

            if (manager != null)
            {
                return(manager.LoadScene(sceneName, mode, behaviour));
            }

            switch (behaviour)
            {
            case LoadSceneBehaviour.Standard:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                SceneManager.LoadScene(sceneName, mode);
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), null);
                return(handle);
            }

            case LoadSceneBehaviour.Async:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                var op     = SceneManager.LoadSceneAsync(sceneName, mode);
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), op);
                return(handle);
            }

            case LoadSceneBehaviour.AsyncAndWait:
            {
                var handle = new LoadSceneWaitHandle(sceneName, mode, behaviour);
                var op     = SceneManager.LoadSceneAsync(sceneName, mode);
                op.allowSceneActivation = false;
                handle.Init(SceneManager.GetSceneAt(SceneManager.sceneCount - 1), op);
                return(handle);
            }
            }

            throw new System.InvalidOperationException("Unsupported LoadSceneBehaviour.");
        }
        protected virtual void OnSceneLoaded(Scene scene, LoadSceneMode mode)
        {
            LoadSceneWaitHandle handle;

            if (_table.TryGetValue(scene, out handle))
            {
                _table.Remove(scene);
            }
            var d = this.SceneLoaded;

            if (d == null)
            {
                return;
            }

            if (handle == null)
            {
                handle = new LoadSceneWaitHandle(scene.name, mode, LoadSceneBehaviour.Standard);
                handle.Init(scene, null);
            }

            d(this, handle);
        }