using System.Collections ;

using System.Collections.Generic ;

using System.Linq ;

using UnityEngine ;

using UnityEngine.Networking.Match ;

using UnityEngine.SceneManagement ;

//

// Created by Cratesmith Game Assembly Pty Ltd; 14/05/2016

// Feel free to use it however you damn well please.

//

//

// This helper provides Async loading of the currently "Active" scene.

// Eg, moving from one level to another without removing UI/background scenes.

//

// Usage: LoadSceneHelper.LoadScene(nextScene, sceneToUseAsLoadingScreen);

//

// Apologies it's crazy, but it's the only way to do it I've found with how broken unity's scenemanager is.

//

// Note this code has 2 dependencies:

// - CoroutineUtil.WaitForRealSeconds(float):

// this is just so that timescale doesn't affect fading into/out from loading

// which you can get from http://answers.unity3d.com/questions/301868/yield-waitforseconds-outside-of-timescale.html#answer-form

//

// - FadeManager.FadeIn(float) and FadeManager.FadeOut(float)

// which you need to provide yourself.

// fading out is important as there will be some frames wheren no scene is loaded

[ AddComponentMenu ( "" ) ]

[ ScriptExecutionOrderAttribute ( 0 ) ]

public class LoadSceneHelper : MonoBehaviour

{

private string m_scene ;

private string m_loaderScene ;

public static void LoadScene ( string scene, string loaderScene )

{

var go = new GameObject ( "LoadSceneHelper" ) ;

DontDestroyOnLoad ( go ) ;

var loadSceneHelper = go . AddComponent < LoadSceneHelper > ( ) ;

loadSceneHelper . m_scene = scene ;

loadSceneHelper . m_loaderScene = loaderScene ;

}

void Start ( )

{

StartCoroutine ( LoadCoroutine ( ) ) ;

}

IEnumerator LoadCoroutine ( )

{

yield return LoadCoroutine_Phase ( m_loaderScene ) ;

yield return LoadCoroutine_Phase ( m_scene ) ;

Destroy ( gameObject ) ;

}

IEnumerator LoadCoroutine_Phase ( string scene )

{

if ( ! string . IsNullOrEmpty ( scene ) )

{

var prevScene = SceneManager . GetActiveScene ( ) . name ;

// Fade out to hide the scene change.

// this is needed as there'll be some frames where we don't have a scene loaded

FadeManager . FadeOut ( 1 ) ;

yield return CoroutineUtil . WaitForRealSeconds ( 1 ) ; //

var async = SceneManager . LoadSceneAsync ( scene, LoadSceneMode . Additive ) ;

async . allowSceneActivation = false ;

do

{

yield return 0 ;

} while ( async . progress < 0 . 9f ) ; ;

SceneManager . UnloadScene ( prevScene ) ;

yield return 0 ;

// We have no way to set our new scene as the "active" scene when it loads,

// so we'll create a temp scene and make it active instead. Any objects created

// by start or awake calls in our new scene will end up here.

var tempScene = SceneManager . CreateScene ( "tempLoading_" + scene ) ;

SceneManager . SetActiveScene ( tempScene ) ;

// now do the load, note that we can't interact with the scene itself until next frame

async . allowSceneActivation = true ;

yield return 0 ;

// Now we set our new scene as active an repair the damage that unity has done.

// Move all objects to the correct scene by parenting then unparenting them to a temp object

SceneManager . SetActiveScene ( SceneManager . GetSceneByName ( scene ) ) ;

var tempParentGO = new GameObject ( ) ;

var tempParentTransform = tempParentGO . transform ;

var objectsUnityHasScrewed = tempScene . GetRootGameObjects ( ) ;

for ( int i = 0 ; i < objectsUnityHasScrewed . Length ;++ i )

{

// NB: don't use scene.rootcount as it's wrong, newly created objects or inactive ones aren't included

// fortunately scene.GetRootGameObjects gives the full list

var obj = objectsUnityHasScrewed [ i ] ;

if ( obj != tempParentGO )

{

obj . transform . parent = tempParentTransform ;

obj . transform . parent = null ;

}

}

// It seems that object to scene associations take a frame to take effect

// so we drop another frame before clearing the temp scene

yield return 0 ;

Destroy ( tempParentGO ) ;

SceneManager . UnloadScene ( tempScene . name ) ;

// OK! we're ACTUALLY done. Fade in the new scene.

// Thankfully the player has no idea of the horrors that happened behind the curtain.

FadeManager . FadeIn ( 1 ) ;

yield return CoroutineUtil . WaitForRealSeconds ( 1 ) ;

}

}