/// <summary> /// 實際Load Scene. /// </summary> /// <param name="sceneRealData"></param> void LoadSceneInternal(LoadSceneRealData sceneRealData) { if (sceneRealData.async) { asyncOP.Clear(); toBeUnloadScene.Clear(); for (int i = 0; i < SceneManager.sceneCount; i++) { toBeUnloadScene.Add(SceneManager.GetSceneAt(i)); } LoadChildScene(sceneRealData, false); //parent scene 最後 load 才抓得到 child scene 的東西. StartCoroutine(LoadSceneAsync(sceneRealData.parentSceneName, LoadSceneMode.Additive)); if (sceneRealData.asyncSceneAutoActive) { LoadSceneAsyncStartAutoActive(0); } } else { //! Parent Scene. SceneManager.LoadScene(sceneRealData.parentSceneName); //! Child Scene. LoadChildScene(sceneRealData, false); #if ASSETBUNDLE UnloadSceneAssetbundle(false, false); #endif //! ASSETBUNDLE. } }
/// <summary> /// Load子場景. /// </summary> /// <param name="sceneRealData"></param> /// <param name="checkLoad"></param> void LoadChildScene(LoadSceneRealData sceneRealData, bool checkLoad) { List <string> childSceneList = sceneRealData.childSceneNameList; for (int i = 0; i < childSceneList.Count; i++) { //! 檢查是否load過. if (checkLoad) { Scene scene = SceneManager.GetSceneByName(childSceneList[i]); if (scene.IsValid()) { continue; } } //! Load場景. if (sceneRealData.async) { //SceneManager.LoadSceneAsync(childSceneFullName, LoadSceneMode.Additive); StartCoroutine(LoadSceneAsync(childSceneList[i], LoadSceneMode.Additive)); } else { SceneManager.LoadScene(childSceneList[i], LoadSceneMode.Additive); } } }
/// <summary> /// 載入場景(使用AssetBundle). /// </summary> /// <param name="sceneRealData"></param> void LoadSceneFromAssetBundleAsync(LoadSceneRealData sceneRealData) { //! 未載入場景或已載入中,不做處理. if (sceneRealData == null || sceneRealData.isLoading) { return; } //! 檢查是否下載完成. //! 檢查主場景. if (!LoadAssetBundleMgr.Singleton.IsAssetbundleLoaded(sceneRealData.parentSceneName)) { return; } //! 檢查子場景. for (int i = 0; i < sceneRealData.childSceneNameList.Count; i++) { if (!LoadAssetBundleMgr.Singleton.IsAssetbundleLoaded(sceneRealData.childSceneNameList[i])) { return; } } //! 全部AssetBundle下載完成. //! 開始載入場景. LoadSceneInternal(sceneRealData); sceneRealData.isLoading = true; }
/// <summary> /// 下載 AssetBundle. /// </summary> /// <param name="sceneRealData"></param> /// <param name="isAsync">是否非同步</param> void DownloadAssetBundle(LoadSceneRealData sceneRealData, bool isAsync) { //! 設定AssetBundle下載路徑. LoadAssetBundleMgr.Singleton.SetDownloadDirectory(FileDirectory.GetStageAssetBundlePath()); if (isAsync) { //! 下載AssetBundle. LoadAssetBundleMgr.Singleton.LoadAssetbundleAsync(sceneRealData.parentSceneName); for (int i = 0; i < sceneRealData.childSceneNameList.Count; i++) { LoadAssetBundleMgr.Singleton.LoadAssetbundleAsync(sceneRealData.childSceneNameList[i]); } } else { //! 下載AssetBundle. LoadAssetBundleMgr.Singleton.LoadAssetbundle(sceneRealData.parentSceneName); for (int i = 0; i < sceneRealData.childSceneNameList.Count; i++) { LoadAssetBundleMgr.Singleton.LoadAssetbundle(sceneRealData.childSceneNameList[i]); } } }
/// <summary> /// Unload場景的Aseetbundle. /// </summary> /// <param name="unloadAll">Assetbundle unload 參數(連建出來的物件都刪掉)</param> /// <param name="forceUnload">就算被reference多次也強制刪除</param> void UnloadSceneAssetbundle(bool unloadAll = false, bool forceUnload = false) { //! 釋放場景的assetbundle. while (loadSceneRealDataList.Count > 0) { LoadSceneRealData sceneRealData = loadSceneRealDataList[0]; //! 釋放場景AssetBundle. LoadAssetBundleMgr.Singleton.UnloadAssetbundle(sceneRealData.parentSceneName, unloadAll, forceUnload); for (int j = 0; j < sceneRealData.childSceneNameList.Count; j++) { LoadAssetBundleMgr.Singleton.UnloadAssetbundle(sceneRealData.childSceneNameList[j], unloadAll, forceUnload); } loadSceneRealDataList.RemoveAt(0); } Debug.LogWarning("loadSceneRealDataList Count: " + loadSceneRealDataList.Count.ToString()); }
/// <summary> /// 子場景如果沒Load進來就load子場景 /// (在流程中的Awake加這個檢查,就能在Editor模式下,開場景時,就把子場景一起load進來). /// </summary> /// <param name="sceneName"></param> public void LoadChildScenesIfNotLoad(string sceneName) { //! Editor模式直接從特定場景開始跑,才需要. #if UNITY_EDITOR Initialize(); if (IsLoadSceneRealDataExist(sceneName) == false) { LoadSceneRealData sceneRealData = GetLoadSceneRealData(sceneName, false, false); #if ASSETBUNDLE //! 使用AssetBundle先載入AssetBundle. LoadAssetBundleMgr.Singleton.SetDownloadDirectory(FileDirectory.GetStageAssetBundlePath()); List <string> loadSceneList = new List <string>(); for (int i = 0; i < sceneRealData.childSceneNameList.Count; i++) { string childSceneName = sceneRealData.childSceneNameList[i]; AssetbundleData assetbundleData = LoadAssetBundleMgr.Singleton.GetAssetbundleData(childSceneName); //! 沒Load過就Load. if (assetbundleData == null) { LoadAssetBundleMgr.Singleton.LoadAssetbundle(childSceneName); loadSceneList.Add(childSceneName); } } LoadChildScene(sceneRealData, true); //! 場景Load完就unload assetbundle. for (int i = 0; i < loadSceneList.Count; i++) { LoadAssetBundleMgr.Singleton.UnloadAssetbundle(loadSceneList[i]); } #else LoadChildScene(sceneRealData, true); #endif //! ASSETBUNDLE. sceneRealData = null; } #endif //! UNITY_EDITOR. }
/// <summary> /// 取得要Load場景的全部實際資料. /// </summary> /// <param name="sceneName"></param> /// <param name="async"></param> /// <param name="asyncSceneAutoActive"></param> /// <returns></returns> LoadSceneRealData GetLoadSceneRealData(string sceneName, bool async, bool asyncSceneAutoActive) { LoadSceneRealData sceneRealData = new LoadSceneRealData(); sceneRealData.async = async; sceneRealData.asyncSceneAutoActive = asyncSceneAutoActive; LoadSceneData sceneData = FindSceneData(sceneName); //! 取得Parent SceneName. string parentName = sceneData.parentScene.name; //! 如果有idType,就取得遊戲中對應id. if (sceneData.parentScene.idType != "") { int id = GetIdByIdType(sceneData.parentScene.idType); parentName += id.ToString(); } sceneRealData.parentSceneName = parentName; //! 取得Child SceneName. for (int i = 0; i < sceneData.childSceneList.Count; i++) { ScenePathData childPathData = sceneData.childSceneList[i]; string childName = childPathData.name; //! 如果有idType,就取得遊戲中對應id. if (childPathData.idType != "") { int id = GetIdByIdType(childPathData.idType); childName += id.ToString(); } sceneRealData.childSceneNameList.Add(childName); } return(sceneRealData); }
/// <summary> /// 載入場景 /// </summary> /// <param name="sceneName">場景名稱</param> /// <param name="async">是否非同步</param> /// <param name="asyncSceneAutoActive">非同步時, 是否自動 Active Scene, 否則手動檢查 IsLoadSceneAsyncApproximatelyDone() 再呼叫 LoadSceneAsyncStartAutoActive() </param> public void LoadScene(string sceneName, bool async, bool asyncSceneAutoActive = true) { Initialize(); //! 取得要Load場景的全部真實名稱. LoadSceneRealData sceneRealData = GetLoadSceneRealData(sceneName, async, asyncSceneAutoActive); //! 不使用下面code ////! 同步載入則count++ ////! 非同步前,則先檢查是否已有同步的載入 ////! bug出現在,同個frame先同步再非同步載入,會發生兩個場景都是呈現同步載入狀態,同時出現兩個場景,可能是unity的SceneManager不允許同時使用同步和非同步。 //if (sceneRealData.async) //{ // if (count != 0) // { // sceneRealData = null; // return; // } //} //else //{ // count++; //} loadSceneRealDataList.Add(sceneRealData); #if ASSETBUNDLE DownloadAssetBundle(sceneRealData, async); //! 同步載入,直接開始Load. if (!async) { LoadSceneInternal(sceneRealData); } #else //! ASSETBUNDLE. LoadSceneInternal(sceneRealData); #endif //! ASSETBUNDLE. }