diff --git a/Assets/Fungus/Prefabs/Game.prefab b/Assets/Fungus/Prefabs/Game.prefab index 8cd9c308..7ecb1c0b 100644 Binary files a/Assets/Fungus/Prefabs/Game.prefab and b/Assets/Fungus/Prefabs/Game.prefab differ diff --git a/Assets/Fungus/Scripts/Game.cs b/Assets/Fungus/Scripts/Game.cs index a78d81a3..d6ab3160 100644 --- a/Assets/Fungus/Scripts/Game.cs +++ b/Assets/Fungus/Scripts/Game.cs @@ -51,6 +51,11 @@ namespace Fungus */ public Dialog dialog; + /** + * Loading image displayed when loading a scene using MoveToScene() + */ + public Texture2D loadingImage; + /** * Global dictionary of integer values for storing game state. */ @@ -213,23 +218,15 @@ namespace Fungus } /** - * Loads a new scene. + * Loads a new scene and displays an optional loading image. * This is useful for splitting a large Fungus game across multiple scene files to reduce peak memory usage. - * All previously loaded assets (including textures) will be released. + * All previously loaded assets (including textures and audio) will be released. * @param sceneName The filename of the scene to load. * @param saveGame Automatically save the current game state as a checkpoint. */ public void LoadScene(string sceneName, bool saveGame) { - Application.LoadLevel(sceneName); - - if (saveGame) - { - SaveGame("Fungus.Save"); - } - - // Free up memory used by textures in previous scene - Resources.UnloadUnusedAssets(); + SceneLoader.LoadScene(sceneName, loadingImage, saveGame); } /** diff --git a/Assets/Fungus/Scripts/SceneLoader.cs b/Assets/Fungus/Scripts/SceneLoader.cs new file mode 100644 index 00000000..aa0da59e --- /dev/null +++ b/Assets/Fungus/Scripts/SceneLoader.cs @@ -0,0 +1,118 @@ +using UnityEngine; +using System.Collections; +using System; + +namespace Fungus +{ + /** + * Helper component for loading a new scene. + * A fullscreen loading image is displayed while loading the new scene. + * All Rooms are destroyed and unused assets are released from memory before loading the new scene to minimize memory footprint. + * For streaming Web Player builds, the loading image will be displayed until the requested level has finished downloading. + */ + public class SceneLoader : MonoBehaviour + { + Texture2D loadingTexture; + string sceneToLoad; + bool displayedImage; + bool saveCheckpoint; + + /** + * Asynchronously load a new scene. + * @param _sceneToLoad The name of the scene to load. Scenes must be added in project build settings. + * @param _loadingTexture Loading image to display while loading the new scene. + * @param _saveCheckpoint Automatically save a checkpoint once the new scene has loaded. + */ + static public void LoadScene(string _sceneToLoad, Texture2D _loadingTexture, bool _saveCheckpoint) + { + // Unity does not provide a way to check if the named scene actually exists in the project. + GameObject go = new GameObject(); + DontDestroyOnLoad(go); + + SceneLoader sceneLoader = go.AddComponent(); + sceneLoader.sceneToLoad = _sceneToLoad; + sceneLoader.loadingTexture = _loadingTexture; + sceneLoader.saveCheckpoint = _saveCheckpoint; + } + + void Start() + { + StartCoroutine(DoLoadSequence()); + } + + IEnumerator DoLoadSequence() + { + // Wait until loading image has been displayed in OnGUI + while (loadingTexture != null && + !displayedImage) + { + yield return new WaitForEndOfFrame(); + } + + // Destroy all Room objects to release references to most game assets + Room[] rooms = GameObject.FindObjectsOfType(); + foreach (Room room in rooms) + { + Destroy(room.gameObject); + } + + yield return new WaitForEndOfFrame(); + + // Most big assets should no longer be referenced, so unload them. + Resources.UnloadUnusedAssets(); + + // Wait until scene has finished downloading (WebPlayer only) + while (!Application.CanStreamedLevelBeLoaded(sceneToLoad)) + { + yield return new WaitForEndOfFrame(); + } + + // Load the scene (happens at end of frame) + Application.LoadLevel(sceneToLoad); + + yield return new WaitForEndOfFrame(); + + // Clean up any remaining unused assets + Resources.UnloadUnusedAssets(); + + // Save a checkpoint if required + if (saveCheckpoint) + { + Game game = Game.GetInstance(); + if (game != null) + { + game.SaveGame("Fungus.Save"); + } + } + + // We're now finished with the SceneLoader + Destroy(gameObject); + } + + void OnGUI() + { + if (loadingTexture == null) + { + return; + } + + GUI.depth = -2000; + + float h = Screen.height; + float w = (float)loadingTexture.width * (h / (float)loadingTexture.height); + + float x = Screen.width / 2 - w / 2; + float y = 0; + + Rect rect = new Rect(x, y, w, h); + + GUI.DrawTexture(rect, loadingTexture); + + if (Event.current.type == EventType.Repaint) + { + // Flag that image is now being shown + displayedImage = true; + } + } + } +} diff --git a/Assets/Fungus/Scripts/SceneLoader.cs.meta b/Assets/Fungus/Scripts/SceneLoader.cs.meta new file mode 100644 index 00000000..51696980 --- /dev/null +++ b/Assets/Fungus/Scripts/SceneLoader.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9ee7614beacb8470ea7b51740476f43c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: