Insanely huge initial commit

This commit is contained in:
2026-02-21 17:04:05 -08:00
parent 9cdd36191a
commit 613d75914a
22525 changed files with 4035207 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2057e93508d0e0b45b4e394f23a82191
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using MoreMountains.Tools;
using UnityEngine.SceneManagement;
namespace MoreMountains.Tools
{
/// <summary>
/// Add this component on an object, specify a scene name in its inspector, and call LoadScene() to load the desired scene.
/// </summary>
public class MMLoadScene : MonoBehaviour
{
/// the possible modes to load scenes. Either Unity's native API, or MoreMountains' LoadingSceneManager
public enum LoadingSceneModes { UnityNative, MMSceneLoadingManager, MMAdditiveSceneLoadingManager }
/// the name of the scene that needs to be loaded when LoadScene gets called
[Tooltip("the name of the scene that needs to be loaded when LoadScene gets called")]
public string SceneName;
/// defines whether the scene will be loaded using Unity's native API or MoreMountains' way
[Tooltip("defines whether the scene will be loaded using Unity's native API or MoreMountains' way")]
public LoadingSceneModes LoadingSceneMode = LoadingSceneModes.UnityNative;
/// <summary>
/// Loads the scene specified in the inspector
/// </summary>
public virtual void LoadScene()
{
switch (LoadingSceneMode)
{
case LoadingSceneModes.UnityNative:
SceneManager.LoadScene (SceneName);
break;
case LoadingSceneModes.MMSceneLoadingManager:
MMSceneLoadingManager.LoadScene (SceneName);
break;
case LoadingSceneModes.MMAdditiveSceneLoadingManager:
MMAdditiveSceneLoadingManager.LoadScene(SceneName);
break;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: d9251a9f35d2c384a9e26195e0c63ee9
timeCreated: 1523971212
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace MoreMountains.Tools
{
/// <summary>
/// A very simple class, meant to be used within a MMSceneLoading screen, to update the fill amount of an Image
/// based on loading progress
/// </summary>
public class MMSceneLoadingImageProgress : MonoBehaviour
{
protected Image _image;
/// <summary>
/// On Awake we store our Image
/// </summary>
protected virtual void Awake()
{
_image = this.gameObject.GetComponent<Image>();
}
/// <summary>
/// Meant to be called by the MMSceneLoadingManager, turns the progress of a load into fill amount
/// </summary>
/// <param name="newValue"></param>
public virtual void SetProgress(float newValue)
{
_image.fillAmount = newValue;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 32002db2f9b16ed45ac2cfd0f37f96e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
namespace MoreMountains.Tools
{
/// <summary>
/// A very simple class, meant to be used within a MMSceneLoading screen, to update a Text
/// based on loading progress
/// </summary>
public class MMSceneLoadingTextProgress : MonoBehaviour
{
/// the value to which the progress' zero value should be remapped to
[Tooltip("the value to which the progress' zero value should be remapped to")]
public float RemapMin = 0f;
/// the value to which the progress' one value should be remapped to
[Tooltip("the value to which the progress' one value should be remapped to")]
public float RemapMax = 100f;
/// the amount of decimals to display
[Tooltip("the amount of decimals to display")]
public int NumberOfDecimals = 0;
protected Text _text;
/// <summary>
/// On Awake we grab our Text and store it
/// </summary>
protected virtual void Awake()
{
_text = this.gameObject.GetComponent<Text>();
}
/// <summary>
/// Updates the Text with the progress value
/// </summary>
/// <param name="newValue"></param>
public virtual void SetProgress(float newValue)
{
float remappedValue = MMMaths.Remap(newValue, 0f, 1f, RemapMin, RemapMax);
float displayValue = MMMaths.RoundToDecimal(remappedValue, NumberOfDecimals);
_text.text = displayValue.ToString(CultureInfo.InvariantCulture);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a6b4439955a5ebf4eaa4285bc875fcc6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6878951bb6bf5594caabe18357ee3a9e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,613 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Tools;
using UnityEngine.SceneManagement;
using UnityEngine.Events;
namespace MoreMountains.Tools
{
[System.Serializable]
public class ProgressEvent : UnityEvent<float>{}
/// <summary>
/// A simple class used to store additive loading settings
/// </summary>
[Serializable]
public class MMAdditiveSceneLoadingManagerSettings
{
/// the possible ways to unload scenes
public enum UnloadMethods { None, ActiveScene, AllScenes };
/// the name of the MMSceneLoadingManager scene you want to use when in additive mode
[Tooltip("the name of the MMSceneLoadingManager scene you want to use when in additive mode")]
public string LoadingSceneName = "MMAdditiveLoadingScreen";
/// when in additive loading mode, the thread priority to apply to the loading
[Tooltip("when in additive loading mode, the thread priority to apply to the loading")]
public ThreadPriority ThreadPriority = ThreadPriority.High;
/// whether or not to make additional sanity checks (better leave this to true)
[Tooltip("whether or not to make additional sanity checks (better leave this to true)")]
public bool SecureLoad = true;
/// when in additive loading mode, whether or not to interpolate the progress bar's progress
[Tooltip("when in additive loading mode, whether or not to interpolate the progress bar's progress")]
public bool InterpolateProgress = true;
/// when in additive loading mode, when in additive loading mode, the duration (in seconds) of the delay before the entry fade
[Tooltip("when in additive loading mode, when in additive loading mode, the duration (in seconds) of the delay before the entry fade")]
public float BeforeEntryFadeDelay = 0f;
/// when in additive loading mode, the duration (in seconds) of the entry fade
[Tooltip("when in additive loading mode, the duration (in seconds) of the entry fade")]
public float EntryFadeDuration = 0.25f;
/// when in additive loading mode, the duration (in seconds) of the delay before the entry fade
[Tooltip("when in additive loading mode, the duration (in seconds) of the delay before the entry fade")]
public float AfterEntryFadeDelay = 0.1f;
/// when in additive loading mode, the duration (in seconds) of the delay before the exit fade
[Tooltip("when in additive loading mode, the duration (in seconds) of the delay before the exit fade")]
public float BeforeExitFadeDelay = 0.25f;
/// when in additive loading mode, the duration (in seconds) of the exit fade
[Tooltip("when in additive loading mode, the duration (in seconds) of the exit fade")]
public float ExitFadeDuration = 0.2f;
/// when in additive loading mode, when in additive loading mode, the tween to use to fade on entry
[Tooltip("when in additive loading mode, when in additive loading mode, the tween to use to fade on entry")]
public MMTweenType EntryFadeTween = null;
/// when in additive loading mode, the tween to use to fade on exit
[Tooltip("when in additive loading mode, the tween to use to fade on exit")]
public MMTweenType ExitFadeTween = null;
/// when in additive loading mode, the speed at which the loader's progress bar should move
[Tooltip("when in additive loading mode, the speed at which the loader's progress bar should move")]
public float ProgressBarSpeed = 5f;
/// when in additive loading mode, the selective additive fade mode
[Tooltip("when in additive loading mode, the selective additive fade mode")]
public MMAdditiveSceneLoadingManager.FadeModes FadeMode = MMAdditiveSceneLoadingManager.FadeModes.FadeInThenOut;
/// the chosen way to unload scenes (none, only the active scene, all loaded scenes)
[Tooltip("the chosen way to unload scenes (none, only the active scene, all loaded scenes)")]
public UnloadMethods UnloadMethod = UnloadMethods.AllScenes;
}
/// <summary>
/// A class to load scenes using a loading screen instead of just the default API
/// This is a new version of the classic LoadingSceneManager (now renamed to MMSceneLoadingManager for consistency)
/// </summary>
public class MMAdditiveSceneLoadingManager : MonoBehaviour
{
/// The possible orders in which to play fades (depends on the fade you've set in your loading screen
public enum FadeModes { FadeInThenOut, FadeOutThenIn }
[Header("Audio Listener")]
public AudioListener LoadingAudioListener;
[Header("Settings")]
/// the ID on which to trigger a fade, has to match the ID on the fader in your scene
[Tooltip("the ID on which to trigger a fade, has to match the ID on the fader in your scene")]
public int FaderID = 500;
/// whether or not to output debug messages to the console
[Tooltip("whether or not to output debug messages to the console")]
public bool DebugMode = false;
[Header("Progress Events")]
/// an event used to update progress
[Tooltip("an event used to update progress")]
public ProgressEvent SetRealtimeProgressValue;
/// an event used to update progress with interpolation
[Tooltip("an event used to update progress with interpolation")]
public ProgressEvent SetInterpolatedProgressValue;
[Header("State Events")]
/// an event that will be invoked when the load starts
[Tooltip("an event that will be invoked when the load starts")]
public UnityEvent OnLoadStarted;
/// an event that will be invoked when the delay before the entry fade starts
[Tooltip("an event that will be invoked when the delay before the entry fade starts")]
public UnityEvent OnBeforeEntryFade;
/// an event that will be invoked when the entry fade starts
[Tooltip("an event that will be invoked when the entry fade starts")]
public UnityEvent OnEntryFade;
/// an event that will be invoked when the delay after the entry fade starts
[Tooltip("an event that will be invoked when the delay after the entry fade starts")]
public UnityEvent OnAfterEntryFade;
/// an event that will be invoked when the origin scene gets unloaded
[Tooltip("an event that will be invoked when the origin scene gets unloaded")]
public UnityEvent OnUnloadOriginScene;
/// an event that will be invoked when the destination scene starts loading
[Tooltip("an event that will be invoked when the destination scene starts loading")]
public UnityEvent OnLoadDestinationScene;
/// an event that will be invoked when the load of the destination scene is complete
[Tooltip("an event that will be invoked when the load of the destination scene is complete")]
public UnityEvent OnLoadProgressComplete;
/// an event that will be invoked when the interpolated load of the destination scene is complete
[Tooltip("an event that will be invoked when the interpolated load of the destination scene is complete")]
public UnityEvent OnInterpolatedLoadProgressComplete;
/// an event that will be invoked when the delay before the exit fade starts
[Tooltip("an event that will be invoked when the delay before the exit fade starts")]
public UnityEvent OnBeforeExitFade;
/// an event that will be invoked when the exit fade starts
[Tooltip("an event that will be invoked when the exit fade starts")]
public UnityEvent OnExitFade;
/// an event that will be invoked when the destination scene gets activated
[Tooltip("an event that will be invoked when the destination scene gets activated")]
public UnityEvent OnDestinationSceneActivation;
/// an event that will be invoked when the scene loader gets unloaded
[Tooltip("an event that will be invoked when the scene loader gets unloaded")]
public UnityEvent OnUnloadSceneLoader;
protected static bool _interpolateProgress;
protected static float _progressInterpolationSpeed;
protected static float _beforeEntryFadeDelay;
protected static MMTweenType _entryFadeTween;
protected static float _entryFadeDuration;
protected static float _afterEntryFadeDelay;
protected static float _beforeExitFadeDelay;
protected static MMTweenType _exitFadeTween;
protected static float _exitFadeDuration;
protected static FadeModes _fadeMode;
protected static string _sceneToLoadName = "";
protected static string _loadingScreenSceneName;
protected static List<string> _scenesInBuild;
protected static Scene[] _initialScenes;
protected float _loadProgress = 0f;
protected float _interpolatedLoadProgress;
protected static bool _loadingInProgress = false;
protected AsyncOperation _unloadOriginAsyncOperation;
protected AsyncOperation _loadDestinationAsyncOperation;
protected AsyncOperation _unloadLoadingAsyncOperation;
protected bool _setRealtimeProgressValueIsNull;
protected bool _setInterpolatedProgressValueIsNull;
protected const float _asyncProgressLimit = 0.9f;
protected MMSceneLoadingAntiSpill _antiSpill = new MMSceneLoadingAntiSpill();
/// <summary>
/// Call this static method to load a scene from anywhere (packed settings signature)
/// </summary>
/// <param name="sceneToLoadName"></param>
/// <param name="settings"></param>
public static void LoadScene(string sceneToLoadName, MMAdditiveSceneLoadingManagerSettings settings)
{
LoadScene(sceneToLoadName, settings.LoadingSceneName, settings.ThreadPriority, settings.SecureLoad, settings.InterpolateProgress,
settings.BeforeEntryFadeDelay, settings.EntryFadeDuration, settings.AfterEntryFadeDelay, settings.BeforeExitFadeDelay,
settings.ExitFadeDuration, settings.EntryFadeTween, settings.ExitFadeTween, settings.ProgressBarSpeed, settings.FadeMode, settings.UnloadMethod);
}
/// <summary>
/// Call this static method to load a scene from anywhere
/// </summary>
/// <param name="sceneToLoadName">Level name.</param>
public static void LoadScene(string sceneToLoadName, string loadingSceneName = "MMAdditiveLoadingScreen",
ThreadPriority threadPriority = ThreadPriority.High, bool secureLoad = true,
bool interpolateProgress = true,
float beforeEntryFadeDelay = 0f,
float entryFadeDuration = 0.25f,
float afterEntryFadeDelay = 0.1f,
float beforeExitFadeDelay = 0.25f,
float exitFadeDuration = 0.2f,
MMTweenType entryFadeTween = null, MMTweenType exitFadeTween = null,
float progressBarSpeed = 5f,
FadeModes fadeMode = FadeModes.FadeInThenOut,
MMAdditiveSceneLoadingManagerSettings.UnloadMethods unloadMethod = MMAdditiveSceneLoadingManagerSettings.UnloadMethods.AllScenes)
{
if (_loadingInProgress)
{
Debug.LogError("MMLoadingSceneManagerAdditive : a request to load a new scene was emitted while a scene load was already in progress");
return;
}
if (entryFadeTween == null)
{
entryFadeTween = new MMTweenType(MMTween.MMTweenCurve.EaseInOutCubic);
}
if (exitFadeTween == null)
{
exitFadeTween = new MMTweenType(MMTween.MMTweenCurve.EaseInOutCubic);
}
if (secureLoad)
{
_scenesInBuild = MMScene.GetScenesInBuild();
if (!_scenesInBuild.Contains(sceneToLoadName))
{
Debug.LogError("MMLoadingSceneManagerAdditive : impossible to load the '"+sceneToLoadName+"' scene, " +
"there is no such scene in the project's build settings.");
return;
}
if (!_scenesInBuild.Contains(loadingSceneName))
{
Debug.LogError("MMLoadingSceneManagerAdditive : impossible to load the '"+loadingSceneName+"' scene, " +
"there is no such scene in the project's build settings.");
return;
}
}
_loadingInProgress = true;
_initialScenes = GetScenesToUnload(unloadMethod);
Application.backgroundLoadingPriority = threadPriority;
_sceneToLoadName = sceneToLoadName;
_loadingScreenSceneName = loadingSceneName;
_beforeEntryFadeDelay = beforeEntryFadeDelay;
_entryFadeDuration = entryFadeDuration;
_entryFadeTween = entryFadeTween;
_afterEntryFadeDelay = afterEntryFadeDelay;
_progressInterpolationSpeed = progressBarSpeed;
_beforeExitFadeDelay = beforeExitFadeDelay;
_exitFadeDuration = exitFadeDuration;
_exitFadeTween = exitFadeTween;
_fadeMode = fadeMode;
_interpolateProgress = interpolateProgress;
SceneManager.LoadScene(_loadingScreenSceneName, LoadSceneMode.Additive);
}
private static Scene[] GetScenesToUnload(MMAdditiveSceneLoadingManagerSettings.UnloadMethods unloaded)
{
switch (unloaded) {
case MMAdditiveSceneLoadingManagerSettings.UnloadMethods.None:
_initialScenes = new Scene[0];
break;
case MMAdditiveSceneLoadingManagerSettings.UnloadMethods.ActiveScene:
_initialScenes = new Scene[1] {SceneManager.GetActiveScene()};
break;
default:
case MMAdditiveSceneLoadingManagerSettings.UnloadMethods.AllScenes:
_initialScenes = MMScene.GetLoadedScenes();
break;
}
return _initialScenes;
}
/// <summary>
/// Starts loading the new level asynchronously
/// </summary>
protected virtual void Awake()
{
Initialization();
}
/// <summary>
/// Initializes timescale, computes null checks, and starts the load sequence
/// </summary>
protected virtual void Initialization()
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : Initialization");
if (DebugMode)
{
foreach (Scene scene in _initialScenes)
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : Initial scene : " + scene.name);
}
}
_setRealtimeProgressValueIsNull = SetRealtimeProgressValue == null;
_setInterpolatedProgressValueIsNull = SetInterpolatedProgressValue == null;
Time.timeScale = 1f;
if ((_sceneToLoadName == "") || (_loadingScreenSceneName == ""))
{
return;
}
StartCoroutine(LoadSequence());
}
/// <summary>
/// Every frame, we fill the bar smoothly according to loading progress
/// </summary>
protected virtual void Update()
{
UpdateProgress();
}
/// <summary>
/// Sends progress value via UnityEvents
/// </summary>
protected virtual void UpdateProgress()
{
if (!_setRealtimeProgressValueIsNull)
{
SetRealtimeProgressValue.Invoke(_loadProgress);
}
if (_interpolateProgress)
{
_interpolatedLoadProgress = MMMaths.Approach(_interpolatedLoadProgress, _loadProgress, Time.unscaledDeltaTime * _progressInterpolationSpeed);
if (!_setInterpolatedProgressValueIsNull)
{
SetInterpolatedProgressValue.Invoke(_interpolatedLoadProgress);
}
}
else
{
SetInterpolatedProgressValue.Invoke(_loadProgress);
}
}
/// <summary>
/// Loads the scene to load asynchronously.
/// </summary>
protected virtual IEnumerator LoadSequence()
{
_antiSpill?.PrepareAntiFill(_sceneToLoadName);
InitiateLoad();
yield return ProcessDelayBeforeEntryFade();
yield return EntryFade();
yield return ProcessDelayAfterEntryFade();
yield return UnloadOriginScenes();
yield return LoadDestinationScene();
yield return ProcessDelayBeforeExitFade();
yield return DestinationSceneActivation();
yield return ExitFade();
yield return UnloadSceneLoader();
}
/// <summary>
/// Initializes counters and timescale
/// </summary>
protected virtual void InitiateLoad()
{
_loadProgress = 0f;
_interpolatedLoadProgress = 0f;
Time.timeScale = 1f;
SetAudioListener(false);
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : Initiate Load");
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.LoadStarted);
OnLoadStarted?.Invoke();
}
/// <summary>
/// Waits for the specified BeforeEntryFadeDelay duration
/// </summary>
/// <returns></returns>
protected virtual IEnumerator ProcessDelayBeforeEntryFade()
{
if (_beforeEntryFadeDelay > 0f)
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : delay before entry fade, duration : " + _beforeEntryFadeDelay);
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.BeforeEntryFade);
OnBeforeEntryFade?.Invoke();
yield return MMCoroutine.WaitForUnscaled(_beforeEntryFadeDelay);
}
}
/// <summary>
/// Calls a fader on entry
/// </summary>
/// <returns></returns>
protected virtual IEnumerator EntryFade()
{
if (_entryFadeDuration > 0f)
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : entry fade, duration : " + _entryFadeDuration);
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.EntryFade);
OnEntryFade?.Invoke();
if (_fadeMode == FadeModes.FadeOutThenIn)
{
yield return null;
MMFadeOutEvent.Trigger(_entryFadeDuration, _entryFadeTween, FaderID, true);
}
else
{
yield return null;
MMFadeInEvent.Trigger(_entryFadeDuration, _entryFadeTween, FaderID, true);
}
yield return MMCoroutine.WaitForUnscaled(_entryFadeDuration);
}
}
/// <summary>
/// Waits for the specified AfterEntryFadeDelay
/// </summary>
/// <returns></returns>
protected virtual IEnumerator ProcessDelayAfterEntryFade()
{
if (_afterEntryFadeDelay > 0f)
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : delay after entry fade, duration : " + _afterEntryFadeDelay);
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.AfterEntryFade);
OnAfterEntryFade?.Invoke();
yield return MMCoroutine.WaitForUnscaled(_afterEntryFadeDelay);
}
}
/// <summary>
/// Unloads the original scene(s) and waits for the unload to complete
/// </summary>
/// <returns></returns>
protected virtual IEnumerator UnloadOriginScenes()
{
foreach (Scene scene in _initialScenes)
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : unload scene " + scene.name);
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.UnloadOriginScene);
OnUnloadOriginScene?.Invoke();
if (!scene.IsValid() || !scene.isLoaded)
{
Debug.LogWarning("MMLoadingSceneManagerAdditive : invalid scene : " + scene.name);
continue;
}
_unloadOriginAsyncOperation = SceneManager.UnloadSceneAsync(scene);
SetAudioListener(true);
while (_unloadOriginAsyncOperation.progress < _asyncProgressLimit)
{
yield return null;
}
}
}
/// <summary>
/// Loads the destination scene
/// </summary>
/// <returns></returns>
protected virtual IEnumerator LoadDestinationScene()
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : load destination scene");
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.LoadDestinationScene);
OnLoadDestinationScene?.Invoke();
_loadDestinationAsyncOperation = SceneManager.LoadSceneAsync(_sceneToLoadName, LoadSceneMode.Additive );
_loadDestinationAsyncOperation.completed += OnLoadOperationComplete;
_loadDestinationAsyncOperation.allowSceneActivation = false;
while (_loadDestinationAsyncOperation.progress < _asyncProgressLimit)
{
_loadProgress = _loadDestinationAsyncOperation.progress;
yield return null;
}
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : load progress complete");
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.LoadProgressComplete);
OnLoadProgressComplete?.Invoke();
// when the load is close to the end (it'll never reach it), we set it to 100%
_loadProgress = 1f;
// we wait for the bar to be visually filled to continue
if (_interpolateProgress)
{
while (_interpolatedLoadProgress < 1f)
{
yield return null;
}
}
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : interpolated load complete");
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.InterpolatedLoadProgressComplete);
OnInterpolatedLoadProgressComplete?.Invoke();
}
/// <summary>
/// Waits for BeforeExitFadeDelay seconds
/// </summary>
/// <returns></returns>
protected virtual IEnumerator ProcessDelayBeforeExitFade()
{
if (_beforeExitFadeDelay > 0f)
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : delay before exit fade, duration : " + _beforeExitFadeDelay);
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.BeforeExitFade);
OnBeforeExitFade?.Invoke();
yield return MMCoroutine.WaitForUnscaled(_beforeExitFadeDelay);
}
}
/// <summary>
/// Requests a fade on exit
/// </summary>
/// <returns></returns>
protected virtual IEnumerator ExitFade()
{
SetAudioListener(false);
if (_exitFadeDuration > 0f)
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : exit fade, duration : " + _exitFadeDuration);
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.ExitFade);
OnExitFade?.Invoke();
if (_fadeMode == FadeModes.FadeOutThenIn)
{
MMFadeInEvent.Trigger(_exitFadeDuration, _exitFadeTween, FaderID, true);
}
else
{
MMFadeOutEvent.Trigger(_exitFadeDuration, _exitFadeTween, FaderID, true);
}
yield return MMCoroutine.WaitForUnscaled(_exitFadeDuration);
}
}
/// <summary>
/// Activates the destination scene
/// </summary>
protected virtual IEnumerator DestinationSceneActivation()
{
yield return MMCoroutine.WaitForFrames(1);
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : activating destination scene");
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.DestinationSceneActivation);
OnDestinationSceneActivation?.Invoke();
_loadDestinationAsyncOperation.allowSceneActivation = true;
while (_loadDestinationAsyncOperation.progress < 1.0f)
{
yield return null;
}
}
/// <summary>
/// A method triggered when the async operation completes
/// </summary>
/// <param name="obj"></param>
protected virtual void OnLoadOperationComplete(AsyncOperation obj)
{
SceneManager.SetActiveScene(SceneManager.GetSceneByName(_sceneToLoadName));
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : set active scene to " + _sceneToLoadName);
}
/// <summary>
/// Unloads the scene loader
/// </summary>
/// <returns></returns>
protected virtual IEnumerator UnloadSceneLoader()
{
MMLoadingSceneDebug("MMLoadingSceneManagerAdditive : unloading scene loader");
MMSceneLoadingManager.LoadingSceneEvent.Trigger(_sceneToLoadName, MMSceneLoadingManager.LoadingStatus.UnloadSceneLoader);
OnUnloadSceneLoader?.Invoke();
yield return null; // mandatory yield to avoid an unjustified warning
_unloadLoadingAsyncOperation = SceneManager.UnloadSceneAsync(_loadingScreenSceneName);
while (_unloadLoadingAsyncOperation.progress < _asyncProgressLimit)
{
yield return null;
}
}
/// <summary>
/// Turns the loading audio listener on or off
/// </summary>
/// <param name="state"></param>
protected virtual void SetAudioListener(bool state)
{
if (LoadingAudioListener != null)
{
//LoadingAudioListener.gameObject.SetActive(state);
}
}
/// <summary>
/// On Destroy we reset our state
/// </summary>
protected virtual void OnDestroy()
{
_loadingInProgress = false;
}
/// <summary>
/// A debug method used to output console messages, for this class only
/// </summary>
/// <param name="message"></param>
protected virtual void MMLoadingSceneDebug(string message)
{
if (!DebugMode)
{
return;
}
string output = "";
output += "<color=#82d3f9>[" + Time.frameCount + "]</color> ";
output += "<color=#f9a682>[" + MMTime.FloatToTimeString(Time.time, false, true, true, true) + "]</color> ";
output += message;
Debug.Log(output);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 85f9f16a22943814196e731ffb6b0f62
timeCreated: 1523969843
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,79 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
namespace MoreMountains.Tools
{
/// <summary>
/// This helper class, meant to be used by the MMAdditiveSceneLoadingManager, creates a temporary scene to store objects that might get instantiated, and empties it in the destination scene once loading is complete
/// </summary>
public class MMSceneLoadingAntiSpill
{
protected Scene _antiSpillScene;
protected Scene _destinationScene;
protected UnityAction<Scene, Scene> _onActiveSceneChangedCallback;
protected string _sceneToLoadName;
protected List<GameObject> _spillSceneRoots = new List<GameObject>(50);
/// <summary>
/// Creates the temporary scene
/// </summary>
/// <param name="sceneToLoadName"></param>
public virtual void PrepareAntiFill(string sceneToLoadName)
{
_antiSpillScene = SceneManager.CreateScene($"AntiSpill_{sceneToLoadName}");
_destinationScene = default;
_sceneToLoadName = sceneToLoadName;
if (_onActiveSceneChangedCallback != null) { SceneManager.activeSceneChanged -= _onActiveSceneChangedCallback; }
_onActiveSceneChangedCallback = OnActiveSceneChanged;
SceneManager.activeSceneChanged += _onActiveSceneChangedCallback;
SceneManager.SetActiveScene(_antiSpillScene);
}
/// <summary>
/// Once the destination scene has been loaded, we catch that event and prepare to empty
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
protected virtual void OnActiveSceneChanged(Scene from, Scene to)
{
if (from == _antiSpillScene)
{
SceneManager.activeSceneChanged -= _onActiveSceneChangedCallback;
_onActiveSceneChangedCallback = null;
EmptyAntiSpillScene();
}
}
/// <summary>
/// Empties the contents of the anti spill scene into the destination scene
/// </summary>
protected virtual void EmptyAntiSpillScene()
{
if (_antiSpillScene.IsValid() && _antiSpillScene.isLoaded)
{
_spillSceneRoots.Clear();
_antiSpillScene.GetRootGameObjects(_spillSceneRoots);
_destinationScene = SceneManager.GetSceneByName(_sceneToLoadName);
if (_spillSceneRoots.Count > 0)
{
if (_destinationScene.IsValid() && _destinationScene.isLoaded)
{
foreach (var root in _spillSceneRoots)
{
SceneManager.MoveGameObjectToScene(root, _destinationScene);
}
}
}
SceneManager.UnloadSceneAsync(_antiSpillScene);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 11a82a4f9d8826e43b281ce3d781d6f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,190 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using MoreMountains.Tools;
using UnityEngine.SceneManagement;
using UnityEngine.Serialization;
namespace MoreMountains.Tools
{
/// <summary>
/// A class to load scenes using a loading screen instead of just the default API
/// This class used to be known as LoadingSceneManager, and has now been renamed to MMSceneLoadingManager for consistency
/// </summary>
public class MMSceneLoadingManager : MonoBehaviour
{
public enum LoadingStatus
{
LoadStarted, BeforeEntryFade, EntryFade, AfterEntryFade, UnloadOriginScene, LoadDestinationScene,
LoadProgressComplete, InterpolatedLoadProgressComplete, BeforeExitFade, ExitFade, DestinationSceneActivation, UnloadSceneLoader, LoadTransitionComplete
}
public struct LoadingSceneEvent
{
public LoadingStatus Status;
public string SceneName;
public LoadingSceneEvent(string sceneName, LoadingStatus status)
{
Status = status;
SceneName = sceneName;
}
static LoadingSceneEvent e;
public static void Trigger(string sceneName, LoadingStatus status)
{
e.Status = status;
e.SceneName = sceneName;
MMEventManager.TriggerEvent(e);
}
}
[Header("Binding")]
/// The name of the scene to load while the actual target scene is loading (usually a loading screen)
public static string LoadingScreenSceneName="LoadingScreen";
[Header("GameObjects")]
/// the text object where you want the loading message to be displayed
public Text LoadingText;
/// the canvas group containing the progress bar
public CanvasGroup LoadingProgressBar;
/// the canvas group containing the animation
public CanvasGroup LoadingAnimation;
/// the canvas group containing the animation to play when loading is complete
public CanvasGroup LoadingCompleteAnimation;
[Header("Time")]
/// the duration (in seconds) of the initial fade in
public float StartFadeDuration=0.2f;
/// the speed of the progress bar
public float ProgressBarSpeed=2f;
/// the duration (in seconds) of the load complete fade out
public float ExitFadeDuration=0.2f;
/// the delay (in seconds) before leaving the scene when complete
public float LoadCompleteDelay=0.5f;
protected AsyncOperation _asyncOperation;
protected static string _sceneToLoad = "";
protected float _fadeDuration = 0.5f;
protected float _fillTarget=0f;
protected string _loadingTextValue;
protected Image _progressBarImage;
protected static MMTweenType _tween;
/// <summary>
/// Call this static method to load a scene from anywhere
/// </summary>
/// <param name="sceneToLoad">Level name.</param>
public static void LoadScene(string sceneToLoad)
{
_sceneToLoad = sceneToLoad;
Application.backgroundLoadingPriority = ThreadPriority.High;
if (LoadingScreenSceneName!=null)
{
LoadingSceneEvent.Trigger(sceneToLoad, LoadingStatus.LoadStarted);
SceneManager.LoadScene(LoadingScreenSceneName);
}
}
/// <summary>
/// Call this static method to load a scene from anywhere
/// </summary>
/// <param name="sceneToLoad">Level name.</param>
public static void LoadScene(string sceneToLoad, string loadingSceneName)
{
_sceneToLoad = sceneToLoad;
Application.backgroundLoadingPriority = ThreadPriority.High;
SceneManager.LoadScene(loadingSceneName);
}
/// <summary>
/// On Start(), we start loading the new level asynchronously
/// </summary>
protected virtual void Start()
{
_tween = new MMTweenType(MMTween.MMTweenCurve.EaseOutCubic);
_progressBarImage = LoadingProgressBar.GetComponent<Image>();
_loadingTextValue =LoadingText.text;
if (!string.IsNullOrEmpty(_sceneToLoad))
{
StartCoroutine(LoadAsynchronously());
}
}
/// <summary>
/// Every frame, we fill the bar smoothly according to loading progress
/// </summary>
protected virtual void Update()
{
Time.timeScale = 1f;
_progressBarImage.fillAmount = MMMaths.Approach(_progressBarImage.fillAmount,_fillTarget,Time.deltaTime*ProgressBarSpeed);
}
/// <summary>
/// Loads the scene to load asynchronously.
/// </summary>
protected virtual IEnumerator LoadAsynchronously()
{
// we setup our various visual elements
LoadingSetup();
// we fade from black
MMFadeOutEvent.Trigger(StartFadeDuration, _tween);
yield return new WaitForSeconds(StartFadeDuration);
// we start loading the scene
_asyncOperation = SceneManager.LoadSceneAsync(_sceneToLoad,LoadSceneMode.Single );
_asyncOperation.allowSceneActivation = false;
// while the scene loads, we assign its progress to a target that we'll use to fill the progress bar smoothly
while (_asyncOperation.progress < 0.9f)
{
_fillTarget = _asyncOperation.progress;
yield return null;
}
// when the load is close to the end (it'll never reach it), we set it to 100%
_fillTarget = 1f;
// we wait for the bar to be visually filled to continue
while (_progressBarImage.fillAmount != _fillTarget)
{
yield return null;
}
// the load is now complete, we replace the bar with the complete animation
LoadingComplete();
yield return new WaitForSeconds(LoadCompleteDelay);
// we fade to black
MMFadeInEvent.Trigger(ExitFadeDuration, _tween);
yield return new WaitForSeconds(ExitFadeDuration);
// we switch to the new scene
_asyncOperation.allowSceneActivation = true;
LoadingSceneEvent.Trigger(_sceneToLoad, LoadingStatus.LoadTransitionComplete);
}
/// <summary>
/// Sets up all visual elements, fades from black at the start
/// </summary>
protected virtual void LoadingSetup()
{
LoadingCompleteAnimation.alpha=0;
_progressBarImage.fillAmount = 0f;
LoadingText.text = _loadingTextValue;
}
/// <summary>
/// Triggered when the actual loading is done, replaces the progress bar with the complete animation
/// </summary>
protected virtual void LoadingComplete()
{
LoadingSceneEvent.Trigger(_sceneToLoad, LoadingStatus.InterpolatedLoadProgressComplete);
LoadingCompleteAnimation.gameObject.SetActive(true);
StartCoroutine(MMFade.FadeCanvasGroup(LoadingProgressBar,0.1f,0f));
StartCoroutine(MMFade.FadeCanvasGroup(LoadingAnimation,0.1f,0f));
StartCoroutine(MMFade.FadeCanvasGroup(LoadingCompleteAnimation,0.1f,1f));
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 5fc9302e06a3ad240a410b9264fd8e56
timeCreated: 1523969843
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: