From 8857a110383c09fe928eb10d6e87123c63ceca0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerard=20Gasc=C3=B3n?= <52170489+GerardGascon@users.noreply.github.com> Date: Mon, 10 Oct 2022 23:32:15 +0200 Subject: [PATCH] Added auto-save --- README.md | 31 +++--- Tools/AudioManager/AudioManager.cs | 21 ++++ Tools/AutoSave.meta | 8 ++ Tools/AutoSave/AutoSaveConfig.cs | 124 ++++++++++++++++++++++++ Tools/AutoSave/AutoSaveConfig.cs.meta | 11 +++ Tools/Cinemachine/CMCameraTrigger.cs | 9 +- Tools/DialogueSystem/DialogueManager.cs | 19 +++- package.json | 4 +- 8 files changed, 206 insertions(+), 21 deletions(-) create mode 100644 Tools/AutoSave.meta create mode 100644 Tools/AutoSave/AutoSaveConfig.cs create mode 100644 Tools/AutoSave/AutoSaveConfig.cs.meta diff --git a/README.md b/README.md index d5b7394..cb0ba62 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ This package contains simple tools to use in your project. -This package will be updated once I find another useful tool or someone suggest me one. - ## Features - **AudioManager** with Play, Pause and most of the other basic things, as well as some effects like FadeIn or FadeOut. @@ -12,6 +10,8 @@ This package will be updated once I find another useful tool or someone suggest - Basic menu with **music and SFX sliders** as well as **resolution and quality dropdowns.** - An **object pooler** with the ability to create pools with an undetermined size. - A basic **scene manager** with a loading screen with progress bar. +- A simple **timer** that allows you to easily create clocks, countdowns and stopwatches with TextMeshPro +- An **auto-save** feature to reduce the chances of loosing data on crashes. All of that comes with some editor menu items for creating all of that as fast as possible. @@ -33,7 +33,7 @@ Download latest package from the Release section Import SimpleTools.unitypackage ## Usage -### AudioManager +### **AudioManager** ```csharp using SimpleTools.AudioManager; @@ -42,6 +42,7 @@ AudioManager.instance.Play("Name"); //Plays the sound with that name AudioManager.instance.Play("Name", 1f); //Starts playing the sound "Name" in 1 second AudioManager.instance.PlayOneShot("Name"); //Plays one shot of that sound (Useful for repeated sounds) AudioManager.instance.PlayWithIntro("Intro", "Loop"); //Plays the intro and then the loop +AudioManager.instance.PlayRandomSound("Name1", "Name2", "Name3"); // Plays one shot of a random sound AudioManager.instance.Pause("Name"); //Pauses the sound AudioManager.instance.UnPause("Name"); //Unpauses the sound @@ -59,7 +60,7 @@ AudioManager.instance.FadeMutedIn("Name", 1f); //Fade In a muted sound with a sp AudioManager.instance.FadeMutedOut("Name", 1f); //Fade Out a sound without stopping it ``` -### ObjectPooler +### **ObjectPooler** The SpawnFromPool function always return a GameObject @@ -80,7 +81,7 @@ Pooler.SpawnFromPool("Name", Vector3.zero, transform, true); //Spawn into a spec Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity, transform, true); //Spawn into a specific position, rotation, parent and instantiate in worldSpace or not ``` -### Dialogue System +### **Dialogue System** The Dialogue function returns a bool (true if it's talking, false if it has ended) @@ -88,13 +89,13 @@ The Dialogue function returns a bool (true if it's talking, false if it has ende using SimpleTools.DialogueSystem; Dialogue dialogue; //The dialogue scriptable object goes here -DialogueSystem.instance.Dialogue(dialogue); //Start/Continue the dialogue -DialogueSystem.instance.Dialogue(dialogue, "Sound1", "Sound2"); //Start/Continue the dialogue with a random set of sounds for the text reveal +DialogueManager.instance.Dialogue(dialogue); //Start/Continue the dialogue +DialogueManager.instance.Dialogue(dialogue, "Sound1", "Sound2"); //Start/Continue the dialogue with a random set of sounds for the text reveal ``` Text commands: -```html +``` --> Sets font color within tags --> Sets font size within tags --> Draws a sprite from the TextMeshPro @@ -106,7 +107,7 @@ Text commands: --> Fades a music in ``` -### SceneManager +### **SceneManager** ```csharp using SimpleTools.SceneManagement; @@ -115,7 +116,7 @@ Loader.Load(0); //Loads a scene with a specific build index Loader.Load("Scene"); //Loads a scene with a specific name ``` -### ScreenShake +### **ScreenShake** ```csharp using SimpleTools.Cinemachine; @@ -123,7 +124,7 @@ using SimpleTools.Cinemachine; ScreenShake.Shake(1f, .25f); //Shakes the camera with an intensity and duration ``` -### Timer +### **Timer** ```csharp using SimpleTools.Timer; @@ -141,8 +142,12 @@ timer.ResetTimer(); //Pause and sets the time to the default one timer.Restart(); //Restarts the timer ``` -### Editor +### **Auto-save** + +To enable auto-save you have access the menu from the top bar, *Simple Tools>Auto Save Configuration.* You can auto-save every several minutes or auto-save every time you enter play mode. + +### **Editor** You can easily set up some things by right clicking in your Project Tab and then selecting Tools and clicking on the one you want to create. -Also you can right click in the Hierarchy for easily creating some GameObjects with the Tools in it. +Also you can right click in the Hierarchy for easily creating some GameObjects with the Tools in it. \ No newline at end of file diff --git a/Tools/AudioManager/AudioManager.cs b/Tools/AudioManager/AudioManager.cs index 7ce5230..56b4dd6 100644 --- a/Tools/AudioManager/AudioManager.cs +++ b/Tools/AudioManager/AudioManager.cs @@ -47,6 +47,7 @@ namespace SimpleTools.AudioManager { /// Use this to play a sound with a specific name /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound public void Play(string name) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -60,6 +61,8 @@ namespace SimpleTools.AudioManager { /// Use this to play a sound with a specific name and with a certain delay /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound + /// The delay in seconds public void Play(string name, float delay) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -73,6 +76,7 @@ namespace SimpleTools.AudioManager { /// Use this to play one shot of a sound with a specific name /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound public void PlayOneShot(string name) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -86,6 +90,8 @@ namespace SimpleTools.AudioManager { /// Use this to play an intro song and then start playing the song loop /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the intro song + /// The name of the song loop public void PlayWithIntro(string intro, string song) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == intro); if (s == null) { @@ -102,6 +108,7 @@ namespace SimpleTools.AudioManager { /// Use this to play one shot of a random sound within a list /// They have to be in the Sound asset referenced in the AudioManager instance /// + /// The names of the sounds public void PlayRandomSound(params string[] names) { int random = UnityEngine.Random.Range(0, names.Length); PlayOneShot(names[random]); @@ -111,6 +118,7 @@ namespace SimpleTools.AudioManager { /// Use this to pause a sound with a specific name /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound public void Pause(string name) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -124,6 +132,7 @@ namespace SimpleTools.AudioManager { /// Use this to unpause a sound with a specific name /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound public void UnPause(string name) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -139,6 +148,7 @@ namespace SimpleTools.AudioManager { /// Use this to stop a sound with a specific name /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound public void Stop(string name) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -163,6 +173,8 @@ namespace SimpleTools.AudioManager { /// This function returns the AudioSource that contains a specific sound /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound + /// The AudioSource in the scene public AudioSource GetSource(string name) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -175,6 +187,8 @@ namespace SimpleTools.AudioManager { /// Use this to start playing a sound with a fade in /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound + /// The duration of the fade in public void FadeIn(string name, float duration) { StartCoroutine(FadeInCoroutine(name, duration)); } @@ -195,6 +209,8 @@ namespace SimpleTools.AudioManager { /// Use this to stop playing a sound with a fade out /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound + /// The duration of the fade out public void FadeOut(string name, float duration) { StartCoroutine(FadeOutCoroutine(name, duration)); } @@ -217,6 +233,7 @@ namespace SimpleTools.AudioManager { /// Use this to start playing a sound muted /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound public void PlayMuted(string name) { Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); if (s == null) { @@ -231,6 +248,8 @@ namespace SimpleTools.AudioManager { /// It has to be in the Sound asset referenced in the AudioManager instance /// WARNING: If the PlayMuted hasn't been called before, this function won't work /// + /// The name of the sound + /// The duration of the fade in public void FadeMutedIn(string name, float duration) { StartCoroutine(FadeMutedInCoroutine(name, duration)); } @@ -250,6 +269,8 @@ namespace SimpleTools.AudioManager { /// Use this to fade out a sound and keep playing that muted /// It has to be in the Sound asset referenced in the AudioManager instance /// + /// The name of the sound + /// The duration of the fade out public void FadeMutedOut(string name, float duration) { StartCoroutine(FadeMutedOutCoroutine(name, duration)); } diff --git a/Tools/AutoSave.meta b/Tools/AutoSave.meta new file mode 100644 index 0000000..ca4fccd --- /dev/null +++ b/Tools/AutoSave.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2f2d8faa0dc23b34f9f347dc08bd85be +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/AutoSave/AutoSaveConfig.cs b/Tools/AutoSave/AutoSaveConfig.cs new file mode 100644 index 0000000..b0544df --- /dev/null +++ b/Tools/AutoSave/AutoSaveConfig.cs @@ -0,0 +1,124 @@ +#if UNITY_EDITOR +using UnityEngine; +using UnityEditor; +using System; +using System.Threading; +using UnityEditor.SceneManagement; +using System.Threading.Tasks; + +namespace SimpleTools.AutoSave { + public class AutoSaveConfig : EditorWindow { + + [MenuItem("Simple Tools/Auto Save Configuration")] + public static void ShowWindow(){ + EditorWindow w = GetWindow("Auto-save Configuration"); + w.position = new Rect(w.position.position, new Vector2(400, 150)); + var data = EditorPrefs.GetString("AutoSave", JsonUtility.ToJson(w, false)); + JsonUtility.FromJsonOverwrite(data, w); + } + + [InitializeOnLoadMethod] + static void OnInitialize(){ + int _index = EditorPrefs.GetInt("Index", 0); + bool _logging = EditorPrefs.GetBool("Logging", false); + ChangeAutoSaveMode(_index, _logging); + } + + protected void OnEnable() { + OnInitialize(); + } + + protected void OnDisable() { + var data = JsonUtility.ToJson(this, false); + EditorPrefs.SetString("AutoSave", data); + EditorPrefs.SetInt("Index", index); + EditorPrefs.SetBool("Logging", logging); + } + + readonly static string[] options = new string[] { "Disabled", "On Play", "1 Minute", "10 Minutes", "1 Hour" }; + public static int index; + public static bool enabled; + public static bool logging; + + void OnGUI() { + GUILayout.Label("Select auto-save mode:", EditorStyles.boldLabel); + int i = EditorGUILayout.Popup(index, options); + if (i != index) ChangeAutoSaveMode(i, logging); + + GUILayout.Label("Log a message every time a the scene gets saved."); + if (logging) { + if (GUILayout.Button("Disable Logging")){ + logging ^= true; + ChangeAutoSaveMode(i, logging); + } + + } else { + if (GUILayout.Button("Enable Logging")) { + logging ^= true; + ChangeAutoSaveMode(i, logging); + } + } + } + + static CancellationTokenSource _tokenSource; + static Task _task; + static int frequency; + static void ChangeAutoSaveMode(int mode, bool log){ + index = mode; + logging = log; + CancelTask(); + enabled = true; + EditorApplication.playModeStateChanged -= AutoSaveWhenPlayModeStarts; + + switch(index){ + case 0: + enabled = false; + return; + case 1: + EditorApplication.playModeStateChanged += AutoSaveWhenPlayModeStarts; + return; + case 2: + frequency = 1 * 60 * 1000; + break; + case 3: + frequency = 10 * 60 * 1000; + break; + case 4: + frequency = 60 * 60 * 1000; + break; + } + + _tokenSource = new CancellationTokenSource(); + _task = SaveInterval(_tokenSource.Token); + } + + static void AutoSaveWhenPlayModeStarts(PlayModeStateChange state){ + if(state == PlayModeStateChange.ExitingEditMode){ + EditorSceneManager.SaveOpenScenes(); + AssetDatabase.SaveAssets(); + if (logging) Debug.Log($"Auto-saved at {DateTime.Now:h:mm:ss tt}"); + } + } + + static void CancelTask() { + if (_task == null) return; + _tokenSource.Cancel(); + } + + static async Task SaveInterval(CancellationToken token) { + while (!token.IsCancellationRequested) { + await Task.Delay(frequency, token); + + if (token.IsCancellationRequested) break; + + if (!enabled || Application.isPlaying || BuildPipeline.isBuildingPlayer || EditorApplication.isCompiling) return; + if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive) return; + + EditorSceneManager.SaveOpenScenes(); + AssetDatabase.SaveAssets(); + if (logging) Debug.Log($"Auto-saved at {DateTime.Now:h:mm:ss tt}"); + } + } + } +} +#endif \ No newline at end of file diff --git a/Tools/AutoSave/AutoSaveConfig.cs.meta b/Tools/AutoSave/AutoSaveConfig.cs.meta new file mode 100644 index 0000000..d4e6164 --- /dev/null +++ b/Tools/AutoSave/AutoSaveConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3f4095259fcc1f45991636604af9829 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/Cinemachine/CMCameraTrigger.cs b/Tools/Cinemachine/CMCameraTrigger.cs index 8afd47a..2fbae3a 100644 --- a/Tools/Cinemachine/CMCameraTrigger.cs +++ b/Tools/Cinemachine/CMCameraTrigger.cs @@ -5,6 +5,7 @@ namespace SimpleTools.Cinemachine { public class CMCameraTrigger : MonoBehaviour { CinemachineVirtualCamera vcam; + [SerializeField, Tooltip("Name of the collider's tag that will trigger the camera.")] string triggerTagName; void Awake() { vcam = GetComponentInChildren(true); @@ -13,12 +14,12 @@ namespace SimpleTools.Cinemachine { #region 3D void OnTriggerEnter(Collider col) { - if (col.CompareTag("Player")) { + if (col.CompareTag(triggerTagName)) { vcam.gameObject.SetActive(true); } } void OnTriggerExit(Collider col) { - if (col.CompareTag("Player")) { + if (col.CompareTag(triggerTagName)) { vcam.gameObject.SetActive(true); } } @@ -26,12 +27,12 @@ namespace SimpleTools.Cinemachine { #region 2D void OnTriggerEnter2D(Collider2D col) { - if (col.CompareTag("Player")) { + if (col.CompareTag(triggerTagName)) { vcam.gameObject.SetActive(true); } } void OnTriggerExit2D(Collider2D col) { - if (col.CompareTag("Player")) { + if (col.CompareTag(triggerTagName)) { vcam.gameObject.SetActive(false); } } diff --git a/Tools/DialogueSystem/DialogueManager.cs b/Tools/DialogueSystem/DialogueManager.cs index 4b025a9..e69e584 100644 --- a/Tools/DialogueSystem/DialogueManager.cs +++ b/Tools/DialogueSystem/DialogueManager.cs @@ -14,7 +14,7 @@ namespace SimpleTools.DialogueSystem { Queue characterImages; bool talking; - public DialogueItems dialogueItems; + public DialogueManagerItems dialogueItems; public static DialogueManager instance; void Awake() { @@ -27,10 +27,21 @@ namespace SimpleTools.DialogueSystem { dialogueVertexAnimator = new DialogueVertexAnimator(dialogueItems.textBox); } + /// + /// This is the main function to call to start a dialogue. + /// + /// The dialogue to start. + /// A bool that is false if the dialogue has finished and true if it hasn't. public bool Dialogue(Dialogue dialogue) { return Dialogue(dialogue, string.Empty); } + /// + /// This is the main function to call to start a dialogue. + /// + /// The dialogue to start. + /// The sounds from the AudioManager that will be played on character reveal. + /// A bool that is false if the dialogue has finished and true if it hasn't. public bool Dialogue(Dialogue dialogue, params string[] sounds) { dialogueVertexAnimator.SetAudioSourceGroup(sounds); @@ -49,6 +60,8 @@ namespace SimpleTools.DialogueSystem { talking = true; if (sentences.Count == 0) { + if (dialogueVertexAnimator.IsMessageAnimating()) + return true; talking = false; return false; } @@ -66,6 +79,8 @@ namespace SimpleTools.DialogueSystem { return true; } else { if (sentences.Count == 0) { + if (dialogueVertexAnimator.IsMessageAnimating()) + return true; talking = false; return false; } @@ -102,7 +117,7 @@ namespace SimpleTools.DialogueSystem { } [System.Serializable] - public struct DialogueItems { + public struct DialogueManagerItems { public Image characterImage; public TMP_Text characterName; public TMP_Text textBox; diff --git a/package.json b/package.json index 1c96dc5..a1f46e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.geri.simpletools", - "version": "1.2.3", + "version": "1.2.2", "displayName": "Simple Tools", "description": "This package contains simple tools to use in your project.", "unity": "2018.4", @@ -20,4 +20,4 @@ "url": "https://geri8.itch.io/" }, "type": "commonjs" -} +} \ No newline at end of file