OldBlueWater/BlueWater/Assets/Doozy/Runtime/SceneManagement/SceneDirector.cs

215 lines
10 KiB
C#
Raw Normal View History

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using Doozy.Runtime.Common;
using Doozy.Runtime.Common.Attributes;
using Doozy.Runtime.Common.Utils;
using Doozy.Runtime.SceneManagement.Events;
using Doozy.Runtime.SceneManagement.ScriptableObjects;
using Doozy.Runtime.Signals;
using UnityEngine;
using UnityEngine.SceneManagement;
// ReSharper disable MemberCanBePrivate.Global
namespace Doozy.Runtime.SceneManagement
{
/// <summary>
/// Loads and unloads scenes and has callbacks for when the active scene changed, a scene was loaded and a scene was unloaded.
/// </summary>
[AddComponentMenu("Doozy/Scene Management/Scene Director")]
public class SceneDirector : SingletonBehaviour<SceneDirector>
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("GameObject/Doozy/Scene Management/Scene Director", false, 9)]
private static void CreateComponent(UnityEditor.MenuCommand menuCommand)
{
GameObjectUtils.AddToScene<SceneDirector>(true, true);
}
#endif
/// <summary> Stream category name </summary>
public const string k_StreamCategory = "SceneManagement";
public const string k_StreamName = nameof(SceneDirector);
[ClearOnReload]
private static SignalStream s_stream;
/// <summary> Signal stream for this component type </summary>
public static SignalStream stream => s_stream ??= SignalsService.GetStream(k_StreamCategory, k_StreamName);
/// <summary> Reference to the SceneManagement global settings </summary>
public static SceneManagementSettings settings => SceneManagementSettings.instance;
/// <summary> Debug flag </summary>
public bool debug => DebugMode | settings.DebugMode;
/// <summary> Enable relevant debug messages to be printed to the console </summary>
public bool DebugMode;
[SerializeField] private ActiveSceneChangedEvent OnActiveSceneChanged;
/// <summary> UnityEvent executed when the active Scene has changed </summary>
public ActiveSceneChangedEvent onActiveSceneChanged => OnActiveSceneChanged ?? (OnActiveSceneChanged = new ActiveSceneChangedEvent());
[SerializeField] private SceneLoadedEvent OnSceneLoaded;
/// <summary> UnityEvent executed when a Scene has loaded </summary>
public SceneLoadedEvent onSceneLoaded => OnSceneLoaded ?? (OnSceneLoaded = new SceneLoadedEvent());
[SerializeField] private SceneUnloadedEvent OnSceneUnloaded;
/// <summary> UnityEvent executed when a Scene has unloaded </summary>
public SceneUnloadedEvent onSceneUnloaded => OnSceneUnloaded ?? (OnSceneUnloaded = new SceneUnloadedEvent());
/// <summary> Signal receiver </summary>
private SignalReceiver receiver { get; set; }
private void ProcessSignal(Signal signal)
{
if (!signal.hasValue)
return;
if (!(signal.valueAsObject is SceneLoaderSignalData data))
return;
}
protected override void Awake()
{
base.Awake();
receiver = new SignalReceiver().SetOnSignalCallback(ProcessSignal);
stream.ConnectReceiver(receiver);
}
private void OnEnable()
{
SceneManager.activeSceneChanged += ActiveSceneChanged;
SceneManager.sceneLoaded += SceneLoaded;
SceneManager.sceneUnloaded += SceneUnloaded;
}
private void OnDisable()
{
SceneManager.activeSceneChanged -= ActiveSceneChanged;
SceneManager.sceneLoaded -= SceneLoaded;
SceneManager.sceneUnloaded -= SceneUnloaded;
}
protected override void OnDestroy()
{
base.OnDestroy();
stream.DisconnectReceiver(receiver);
}
/// <summary> Method called by the SceneManager.activeSceneChanged UnityAction </summary>
/// <param name="current"> Replaced Scene </param>
/// <param name="next"> Next Scene </param>
private void ActiveSceneChanged(Scene current, Scene next)
{
onActiveSceneChanged?.Invoke(current, next);
if (debug) Log($"{ObjectNames.NicifyVariableName(nameof(ActiveSceneChanged))} - Replaced Scene: {current.name} / Next Scene: {next.name}");
}
/// <summary> Method called by the SceneManager.sceneLoaded UnityAction </summary>
/// <param name="scene"> Loaded Scene </param>
/// <param name="mode"> LoadSceneMode used to load the scene </param>
private void SceneLoaded(Scene scene, LoadSceneMode mode)
{
onSceneLoaded?.Invoke(scene, mode);
if (debug) Log($"{ObjectNames.NicifyVariableName(nameof(SceneLoaded))} - Scene: {scene.name} / LoadSceneMode: {mode}");
}
/// <summary> Method called by the SceneManager.sceneUnloaded UnityAction </summary>
/// <param name="unloadedScene"> Unloaded Scene</param>
private void SceneUnloaded(Scene unloadedScene)
{
onSceneUnloaded?.Invoke(unloadedScene);
if (debug) Log($"{ObjectNames.NicifyVariableName(nameof(SceneUnloaded))} - Scene: {unloadedScene.name}");
}
/// <summary> Create a SceneLoader that loads the Scene asynchronously in the background by its index in Build Settings, then returns a reference to the newly created SceneLoader </summary>
/// <param name="sceneBuildIndex"> Index of the Scene in the Build Settings to load </param>
/// <param name="loadSceneMode"> If LoadSceneMode.Single then all current Scenes will be unloaded before loading </param>
public static SceneLoader LoadSceneAsync(int sceneBuildIndex, LoadSceneMode loadSceneMode)
{
if (instance.debug) Log($"{ObjectNames.NicifyVariableName(nameof(LoadSceneAsync))} - sceneBuildIndex: {sceneBuildIndex} / loadSceneMode: {loadSceneMode}", instance);
return
SceneLoader
.GetLoader()
.SetSceneBuildIndex(sceneBuildIndex)
.SetLoadSceneBy(GetSceneBy.BuildIndex)
.SetLoadSceneMode(loadSceneMode)
.LoadSceneAsync();
}
/// <summary> Create a SceneLoader that loads the Scene asynchronously in the background by its name in Build Settings, then returns a reference to the newly created SceneLoader </summary>
/// <param name="sceneName"> Name or path of the Scene to load </param>
/// <param name="loadSceneMode"> If LoadSceneMode.Single then all current Scenes will be unloaded before loading </param>
public static SceneLoader LoadSceneAsync(string sceneName, LoadSceneMode loadSceneMode)
{
if (instance.debug) Log($"{ObjectNames.NicifyVariableName(nameof(LoadSceneAsync))} - sceneName: {sceneName} / loadSceneMode: {loadSceneMode}", instance);
return
SceneLoader
.GetLoader()
.SetSceneName(sceneName)
.SetLoadSceneBy(GetSceneBy.Name)
.SetLoadSceneMode(loadSceneMode)
.LoadSceneAsync();
}
/// <summary>
/// Create a SceneLoader that loads the given Scene asynchronously in the background, then returns a reference to the newly created SceneLoader
/// </summary>
/// <param name="scene"> Scene to load </param>
/// <param name="loadSceneMode"> If LoadSceneMode.Single then all current Scenes will be unloaded before loading </param>
/// <returns></returns>
public static SceneLoader LoadSceneAsync(Scene scene, LoadSceneMode loadSceneMode)
{
if (instance.debug) Log($"{ObjectNames.NicifyVariableName(nameof(LoadSceneAsync))} - scene: {scene.name} / loadSceneMode: {loadSceneMode}", instance);
return
SceneLoader
.GetLoader()
.LoadSceneAsync(scene, loadSceneMode);
}
/// <summary> Destroys all GameObjects associated with the given Scene and removes the Scene from the SceneManager </summary>
/// <param name="scene"> Scene to unload. </param>
public static AsyncOperation UnloadSceneAsync(Scene scene)
{
if (instance.debug) Log($"{ObjectNames.NicifyVariableName(nameof(UnloadSceneAsync))} - scene: {scene.name}", instance);
return scene.IsValid() ? SceneManager.UnloadSceneAsync(scene) : null;
}
/// <summary> Destroys all GameObjects associated with the given Scene and removes the Scene from the SceneManager </summary>
/// <param name="sceneBuildIndex"> Index of the Scene in BuildSettings </param>
public static AsyncOperation UnloadSceneAsync(int sceneBuildIndex)
{
if (instance.debug) Log($"{ObjectNames.NicifyVariableName(nameof(UnloadSceneAsync))} - sceneBuildIndex: {sceneBuildIndex}", instance);
return
SceneManager
.GetSceneByBuildIndex(sceneBuildIndex).IsValid()
? SceneManager.UnloadSceneAsync(sceneBuildIndex)
: null;
}
/// <summary> Destroys all GameObjects associated with the given Scene and removes the Scene from the SceneManager </summary>
/// <param name="sceneName"> Name or path of the Scene to unload. </param>
public static AsyncOperation UnloadSceneAsync(string sceneName)
{
if (instance.debug) Log($"{ObjectNames.NicifyVariableName(nameof(UnloadSceneAsync))} - sceneName: {sceneName}", instance);
return
SceneManager
.GetSceneByName(sceneName).IsValid()
? SceneManager.UnloadSceneAsync(sceneName)
: null;
}
// ReSharper disable once MemberCanBePrivate.Global
/// <summary> Adds SceneDirector to scene and returns a reference to it </summary>
public static SceneDirector AddToScene(bool selectGameObjectAfterCreation = false) =>
GameObjectUtils.AddToScene<SceneDirector>(true, selectGameObjectAfterCreation);
private void Log(string message) =>
Log($"[{name}] {message}", this);
private static void Log(string message, Object context) =>
Debugger.Log($"({nameof(SceneDirector)}) {message}", context);
}
}