|
|
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
-
- using UnityEngine;
- using UnityEngine.SceneManagement;
- using UnityEngine.UI;
-
- public class OVRSceneLoader : MonoBehaviour
- {
- public const string externalStoragePath = "/sdcard/Android/data";
- public const string sceneLoadDataName = "SceneLoadData.txt";
- public const string resourceBundleName = "asset_resources";
-
- public float sceneCheckIntervalSeconds = 1f;
- public float logCloseTime = 5.0f;
-
- public Canvas mainCanvas;
- public Text logTextBox;
-
- private AsyncOperation loadSceneOperation;
- private string formattedLogText;
-
- private float closeLogTimer;
- private bool closeLogDialogue;
-
- private bool canvasPosUpdated;
-
- private struct SceneInfo
- {
- public List<string> scenes;
- public long version;
-
- public SceneInfo(List<string> sceneList, long currentSceneEpochVersion)
- {
- scenes = sceneList;
- version = currentSceneEpochVersion;
- }
- }
-
- private string scenePath = "";
- private string sceneLoadDataPath = "";
- private List<AssetBundle> loadedAssetBundles = new List<AssetBundle>();
- private SceneInfo currentSceneInfo;
-
- private void Awake()
- {
- // Make it presist across scene to continue checking for changes
- DontDestroyOnLoad(this.gameObject);
- }
-
- void Start()
- {
- string applicationPath = Path.Combine(externalStoragePath, Application.identifier);
- scenePath = Path.Combine(applicationPath, "cache/scenes");
- sceneLoadDataPath = Path.Combine(scenePath, sceneLoadDataName);
-
- closeLogDialogue = false;
- StartCoroutine(DelayCanvasPosUpdate());
-
- currentSceneInfo = GetSceneInfo();
- // Check valid scene info has been fetched, and load the scenes
- if (currentSceneInfo.version != 0 && !string.IsNullOrEmpty(currentSceneInfo.scenes[0]))
- {
- LoadScene(currentSceneInfo);
- }
- }
-
- private void LoadScene(SceneInfo sceneInfo)
- {
- AssetBundle mainSceneBundle = null;
- Debug.Log("[OVRSceneLoader] Loading main scene: " + sceneInfo.scenes[0] + " with version " + sceneInfo.version.ToString());
-
- logTextBox.text += "Target Scene: " + sceneInfo.scenes[0] + "\n";
- logTextBox.text += "Version: " + sceneInfo.version.ToString() + "\n";
-
- // Load main scene and dependent additive scenes (if any)
- Debug.Log("[OVRSceneLoader] Loading scene bundle files.");
- // Fetch all files under scene cache path, excluding unnecessary files such as scene metadata file
- string[] bundles = Directory.GetFiles(scenePath, "*_*");
- logTextBox.text += "Loading " + bundles.Length + " bundle(s) . . . ";
- string mainSceneBundleFileName = "scene_" + sceneInfo.scenes[0].ToLower();
- try
- {
- foreach (string b in bundles)
- {
- var assetBundle = AssetBundle.LoadFromFile(b);
- if (assetBundle != null)
- {
- Debug.Log("[OVRSceneLoader] Loading file bundle: " + assetBundle.name == null ? "null" : assetBundle.name);
- loadedAssetBundles.Add(assetBundle);
- }
- else
- {
- Debug.LogError("[OVRSceneLoader] Loading file bundle failed");
- }
-
- if (assetBundle.name == mainSceneBundleFileName)
- {
- mainSceneBundle = assetBundle;
- }
-
- if (assetBundle.name == resourceBundleName)
- {
- OVRResources.SetResourceBundle(assetBundle);
- }
- }
- }
- catch(Exception e)
- {
- logTextBox.text += "<color=red>" + e.Message + "</color>";
- return;
- }
- logTextBox.text += "<color=green>DONE\n</color>";
-
- if (mainSceneBundle != null)
- {
- logTextBox.text += "Loading Scene: {0:P0}\n";
- formattedLogText = logTextBox.text;
- string[] scenePaths = mainSceneBundle.GetAllScenePaths();
- string sceneName = Path.GetFileNameWithoutExtension(scenePaths[0]);
-
- loadSceneOperation = SceneManager.LoadSceneAsync(sceneName);
- loadSceneOperation.completed += LoadSceneOperation_completed;
- }
- else
- {
- logTextBox.text += "<color=red>Failed to get main scene bundle.\n</color>";
- }
- }
-
- private void LoadSceneOperation_completed(AsyncOperation obj)
- {
- StartCoroutine(onCheckSceneCoroutine());
- StartCoroutine(DelayCanvasPosUpdate());
-
- closeLogTimer = 0;
- closeLogDialogue = true;
-
- logTextBox.text += "Log closing in {0} seconds.\n";
- formattedLogText = logTextBox.text;
- }
-
- public void Update()
- {
- // Display scene load percentage
- if (loadSceneOperation != null)
- {
- if (!loadSceneOperation.isDone)
- {
- logTextBox.text = string.Format(formattedLogText, loadSceneOperation.progress + 0.1f);
- if (loadSceneOperation.progress >= 0.9f)
- {
- logTextBox.text = formattedLogText.Replace("{0:P0}", "<color=green>DONE</color>");
- logTextBox.text += "Transitioning to new scene.\nLoad times will vary depending on scene complexity.\n";
-
- }
- }
- }
-
- UpdateCanvasPosition();
-
- // Wait a certain time before closing the log dialogue after the scene has transitioned
- if (closeLogDialogue)
- {
- if (closeLogTimer < logCloseTime)
- {
- closeLogTimer += Time.deltaTime;
- logTextBox.text = string.Format(formattedLogText, (int)(logCloseTime - closeLogTimer));
- }
- else
- {
- mainCanvas.gameObject.SetActive(false);
- closeLogDialogue = false;
- }
- }
- }
-
- private void UpdateCanvasPosition()
- {
- // Update canvas camera reference and position if the main camera has changed
- if (mainCanvas.worldCamera != Camera.main)
- {
- mainCanvas.worldCamera = Camera.main;
- if (Camera.main != null)
- {
- Vector3 newPosition = Camera.main.transform.position + Camera.main.transform.forward * 0.3f;
- gameObject.transform.position = newPosition;
- gameObject.transform.rotation = Camera.main.transform.rotation;
- }
- }
- }
-
- private SceneInfo GetSceneInfo()
- {
- SceneInfo sceneInfo = new SceneInfo();
- try
- {
- StreamReader reader = new StreamReader(sceneLoadDataPath);
- sceneInfo.version = System.Convert.ToInt64(reader.ReadLine());
- List<string> sceneList = new List<string>();
- while (!reader.EndOfStream)
- {
- sceneList.Add(reader.ReadLine());
- }
- sceneInfo.scenes = sceneList;
- }
- catch
- {
- logTextBox.text += "<color=red>Failed to get scene info data.\n</color>";
- }
- return sceneInfo;
- }
-
- // Update canvas position after a slight delay to get accurate headset position after scene transitions
- IEnumerator DelayCanvasPosUpdate()
- {
- yield return new WaitForSeconds(0.1f);
- UpdateCanvasPosition();
- }
-
- IEnumerator onCheckSceneCoroutine()
- {
- SceneInfo newSceneInfo;
- while (true)
- {
- newSceneInfo = GetSceneInfo();
- if (newSceneInfo.version != currentSceneInfo.version)
- {
- Debug.Log("[OVRSceneLoader] Scene change detected.");
-
- // Unload all asset bundles
- foreach (var b in loadedAssetBundles)
- {
- if (b != null)
- {
- b.Unload(true);
- }
- }
- loadedAssetBundles.Clear();
-
- // Unload all scenes in the hierarchy including main scene and
- // its dependent additive scenes.
- int activeScenes = SceneManager.sceneCount;
- for (int i = 0; i < activeScenes; i++)
- {
- SceneManager.UnloadSceneAsync(SceneManager.GetSceneAt(i));
- }
- DestroyAllGameObjects();
- SceneManager.LoadSceneAsync("OVRTransitionScene");
- break;
- }
- yield return new WaitForSeconds(sceneCheckIntervalSeconds);
- }
- }
-
- void DestroyAllGameObjects()
- {
- foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof(GameObject)) as GameObject[])
- {
- Destroy(go);
- }
- }
- }
|