diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..58c3550 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,19 @@ +Copyright (c) 2021 Geri + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/LICENSE.md.meta b/LICENSE.md.meta new file mode 100644 index 0000000..de5ec90 --- /dev/null +++ b/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 535f36a1918d4d2479031f3ca2725323 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md new file mode 100644 index 0000000..6ef300a --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +# Simple Tools + +## Features + +- **AudioManager** with Play, Pause and most of the other basic things, as well as some effects like FadeIn or FadeOut. +- Some Cinemachine tools for making a **camera trigger** and an easy way for creating a **screen shake camera.** +- Basic **dialogue system** that works with TextMeshPro. +- 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. + +All of that comes with some editor menu items for creating all of that as fast as possible. + +## How to install + +First install the TextMeshPro and Cinemachine into your Unity project + +### Git Installation (Best way to get latest version) + +If you have git in your computer, you can open Package Manager inside Unity, select "Add package from Git url...", and paste link [https://github.com/IntoTheDev/Save-System-for-Unity.git](https://github.com/IntoTheDev/Save-System-for-Unity.git) + +or + +Open the manifest.json file of your Unity project. Add "com.geri.simpletools": "[https://github.com/IntoTheDev/Save-System-for-Unity.git](https://github.com/IntoTheDev/Save-System-for-Unity.git)" + +### Manual Installation + +Download latest package from the Release section Import SimpleTools.unitypackage to your Unity Project + +## Usage + +### AudioManager + +```csharp +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.Pause("Name"); //Pauses the sound +AudioManager.instance.UnPause("Name"); //Unpauses the sound + +AudioManager.instance.Stop("Name"); //Stops the sound +AudioManager.instance.StopAll(); //Stops all the sounds that are being played + +AudioManager.instance.GetSource("Name"); //Gets the AudioSource with that name + +AudioManager.instance.FadeIn("Name", 1f); //Fade In the source with a specific duration +AudioManager.instance.FadeOut("Name", 1f); //Fade Out the source with a specific duration + +AudioManager.instance.PlayMuted("Name"); //Play a sound muted +AudioManager.instance.FadeMutedIn("Name", 1f); //Fade In a muted sound with a specific duration +AudioManager.instance.FadeMutedOut("Name", 1f); //Fade Out a sound without stopping it +``` + +### ObjectPooler + +The SpawnFromPool function always return a GameObject + +```csharp +Pool pool; //The pool scriptable object goes here +Pooler.CreatePools(pool); //Create the pool, without creating it you cannot spawn it +Pool[] pools; +Pooler.CreatePools(pools); //Create multiple pools +Pooler.SpawnFromPool("Name", Vector3.zero); //Spawns an object into a specific position +Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity); //Spawn into a specific position and rotation +Pooler.SpawnFromPool("Name", Vector3.zero, transform); //Spawn into a specific position and parent +Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity, transform); //Spawn into a specific position, rotation and parent +Pooler.SpawnFromPool("Name", Vector3.zero, transform, true); //Spawn into a specific position, parent and instantiate in worldSpace or not +Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity, transform, true); //Spawn into a specific position, rotation, parent and instantiate in worldSpace or not +``` + +### Dialogue System + +The Dialogue function returns a bool (true if it's talking, false if it has ended) + +```csharp +Dialogue dialogue; //The dialogue scriptable object goes here +DialogueSystem.instance.Dialogue(dialogue); //Start/Continue the dialogue +``` + +### SceneManager + +```csharp +Loader.Load(0); //Loads a scene with a specific build index +Loader.Load("Scene"); //Loads a scene with a specific name +``` + +### ScreenShake + +```csharp +ScreenShake.Shake(1f, .25f); //Shakes the camera with an intensity and duration +``` \ No newline at end of file diff --git a/README.md.meta b/README.md.meta new file mode 100644 index 0000000..c9d9e2a --- /dev/null +++ b/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e9c1d398f3d17184a97bce327ff06621 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools.meta b/Tools.meta new file mode 100644 index 0000000..b32c30e --- /dev/null +++ b/Tools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78a1b199ab0716542b34cc9a3dd3a9df +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/AudioManager.meta b/Tools/AudioManager.meta new file mode 100644 index 0000000..f12a26c --- /dev/null +++ b/Tools/AudioManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1d98cf7b5d008ba4a832612b94195e04 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/AudioManager/AudioManager.cs b/Tools/AudioManager/AudioManager.cs new file mode 100644 index 0000000..c35fa6f --- /dev/null +++ b/Tools/AudioManager/AudioManager.cs @@ -0,0 +1,206 @@ +using System.Collections; +using UnityEngine; +using System; + +public class AudioManager : MonoBehaviour{ + + public static AudioManager instance; + + [SerializeField] Sounds soundList = default; + + void Awake(){ + if(instance == null){ + instance = this; + }else{ + Destroy(gameObject); + return; + } + DontDestroyOnLoad(gameObject); + + foreach(Sounds.List s in soundList.sounds){ + if(string.IsNullOrEmpty(s.name) || string.IsNullOrWhiteSpace(s.name)){ + Debug.LogWarning("The name one sound is empty"); + continue; + } + + GameObject sound = new GameObject(s.name); + sound.transform.parent = transform; + s.source = sound.AddComponent(); + + if(soundList.mainMixer && soundList.sfxMixer){ + if (s.type == Sounds.List.Type.Music) + s.source.outputAudioMixerGroup = soundList.mainMixer; + else + s.source.outputAudioMixerGroup = soundList.sfxMixer; + } + + s.source.clip = s.clip; + + s.source.volume = s.volume; + s.source.pitch = s.pitch; + s.source.loop = s.loop; + } + } + + #region Play + public void Play(string name){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if(s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.Play(); + } + public void Play(string name, float delay){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.PlayDelayed(delay); + } + public void PlayOneShot(string name){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.PlayOneShot(s.clip); + } + #endregion + #region Pause + public void Pause(string name){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.Pause(); + } + public void UnPause(string name){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.UnPause(); + } + #endregion + #region Stop + public void Stop(string name){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = s.RandomVolume; + s.source.Stop(); + } + public void StopAll(){ + foreach (Sounds.List s in soundList.sounds){ + if (s.source){ + s.source.Stop(); + } + } + } + #endregion + public AudioSource GetSource(string name){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return null; + } + return s.source; + } + #region Fades + public void FadeIn(string name, float duration){ + StartCoroutine(FadeInCoroutine(name, duration)); + } + IEnumerator FadeInCoroutine(string name, float fadeTime){ + AudioSource audioSource = GetSource(name); + if (audioSource != null && !audioSource.isPlaying){ + float volume = audioSource.volume; + audioSource.volume = 0; + audioSource.Play(); + while (audioSource.volume < volume){ + audioSource.volume += Time.deltaTime / fadeTime; + yield return null; + } + + audioSource.volume = volume; + } + } + public void FadeOut(string name, float duration){ + StartCoroutine(FadeOutCoroutine(name, duration)); + } + IEnumerator FadeOutCoroutine(string name, float fadeTime){ + AudioSource audioSource = GetSource(name); + + if (audioSource && audioSource.isPlaying){ + float startVolume = audioSource.volume; + + while (audioSource.volume > 0){ + audioSource.volume -= startVolume * Time.deltaTime / fadeTime; + yield return null; + } + + audioSource.Stop(); + audioSource.volume = startVolume; + } + } + + public void PlayMuted(string name){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + return; + } + s.source.pitch = s.RandomPitch; + s.source.volume = 0f; + s.source.Play(); + } + public void FadeMutedIn(string name, float duration){ + StartCoroutine(FadeMutedInCoroutine(name, duration)); + } + IEnumerator FadeMutedInCoroutine(string name, float fadeTime){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + yield break; + } + + while (s.source.volume < s.volume){ + s.source.volume += Time.deltaTime / fadeTime; + yield return null; + } + s.source.volume = s.volume; + } + public void FadeMutedOut(string name, float duration){ + StartCoroutine(FadeMutedOutCoroutine(name, duration)); + } + IEnumerator FadeMutedOutCoroutine(string name, float fadeTime){ + Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == name); + if (s == null){ + Debug.LogWarning("Sound: " + name + " not found!"); + yield break; + } + + while (s.source.volume > 0){ + s.source.volume -= Time.deltaTime / fadeTime; + yield return null; + } + s.source.volume = 0; + } + #endregion +} diff --git a/Tools/AudioManager/AudioManager.cs.meta b/Tools/AudioManager/AudioManager.cs.meta new file mode 100644 index 0000000..4a77e93 --- /dev/null +++ b/Tools/AudioManager/AudioManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d2879f3876727040b4f0cc799ec7ada +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/AudioManager/AudioManager.png b/Tools/AudioManager/AudioManager.png new file mode 100644 index 0000000..712262f Binary files /dev/null and b/Tools/AudioManager/AudioManager.png differ diff --git a/Tools/AudioManager/AudioManager.png.meta b/Tools/AudioManager/AudioManager.png.meta new file mode 100644 index 0000000..61ce9f6 --- /dev/null +++ b/Tools/AudioManager/AudioManager.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: af0857324620d1d4b8b6bf41b6cdecfc +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/AudioManager/Sounds.cs b/Tools/AudioManager/Sounds.cs new file mode 100644 index 0000000..366dc67 --- /dev/null +++ b/Tools/AudioManager/Sounds.cs @@ -0,0 +1,50 @@ +using UnityEngine; +using UnityEngine.Audio; + +[CreateAssetMenu(fileName = "Sounds", menuName = "Tools/Sounds", order = 0)] +public class Sounds : ScriptableObject{ + + [Tooltip("The music mixer.")] + public AudioMixerGroup mainMixer = default; + [Tooltip("The SFX mixer.")] + public AudioMixerGroup sfxMixer = default; + + public List[] sounds; + + [System.Serializable] public class List{ + [Tooltip("Name of the sound. Each name has to be different between each other.")] + public string name; + + public AudioClip clip; + + [System.Serializable] public enum Type { Music, SFX } + [Space] + [Tooltip("Is it part of the music or the SFX?")] public Type type; + + [Space] + [Tooltip("Default volume of the sound."), Range(0f, 1f)] public float volume; + [Tooltip("Variance percentage of the volume"), Range(0f, 1f)] public float volumeVariance; + [Tooltip("Default pitch of the sound."), Range(.1f, 3f)] public float pitch; + [Tooltip("Variance percentage of the pitch"), Range(0f, 1f)] public float pitchVariance; + + public bool loop; + + [HideInInspector] public AudioSource source; + + float randomVolume; + public float RandomVolume{ + get{ + randomVolume = volume * (1f + Random.Range(-volumeVariance / 2f, volumeVariance / 2f)); + return randomVolume; + } + } + + float randomPitch; + public float RandomPitch{ + get{ + randomPitch = pitch * (1f + Random.Range(-pitchVariance / 2f, pitchVariance / 2f)); + return randomPitch; + } + } + } +} diff --git a/Tools/AudioManager/Sounds.cs.meta b/Tools/AudioManager/Sounds.cs.meta new file mode 100644 index 0000000..a22e5ea --- /dev/null +++ b/Tools/AudioManager/Sounds.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ded47588579f3047b1c3cd72cd87044 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: af0857324620d1d4b8b6bf41b6cdecfc, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/Cinemachine.meta b/Tools/Cinemachine.meta new file mode 100644 index 0000000..608d7cd --- /dev/null +++ b/Tools/Cinemachine.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5a2ff5ceb779d824d811d139fa608262 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/Cinemachine/CMCameraTrigger.cs b/Tools/Cinemachine/CMCameraTrigger.cs new file mode 100644 index 0000000..b89a5c0 --- /dev/null +++ b/Tools/Cinemachine/CMCameraTrigger.cs @@ -0,0 +1,38 @@ +using UnityEngine; +using Cinemachine; + +public class CMCameraTrigger : MonoBehaviour{ + + CinemachineVirtualCamera vcam; + + void Awake(){ + vcam = GetComponentInChildren(true); + vcam.gameObject.SetActive(false); + } + + #region 3D + void OnTriggerEnter(Collider col){ + if (col.CompareTag("Player")){ + vcam.gameObject.SetActive(true); + } + } + void OnTriggerExit(Collider col){ + if (col.CompareTag("Player")){ + vcam.gameObject.SetActive(true); + } + } + #endregion + + #region 2D + void OnTriggerEnter2D(Collider2D col){ + if (col.CompareTag("Player")){ + vcam.gameObject.SetActive(true); + } + } + void OnTriggerExit2D(Collider2D col){ + if (col.CompareTag("Player")){ + vcam.gameObject.SetActive(false); + } + } + #endregion +} diff --git a/Tools/Cinemachine/CMCameraTrigger.cs.meta b/Tools/Cinemachine/CMCameraTrigger.cs.meta new file mode 100644 index 0000000..7d3bb42 --- /dev/null +++ b/Tools/Cinemachine/CMCameraTrigger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 368758c1440a4cb4c867e140e8934c09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/Cinemachine/ScreenShake.cs b/Tools/Cinemachine/ScreenShake.cs new file mode 100644 index 0000000..e2a1eaf --- /dev/null +++ b/Tools/Cinemachine/ScreenShake.cs @@ -0,0 +1,31 @@ +using Cinemachine; +using UnityEngine; + +public static class ScreenShake{ + + static CinemachineVirtualCamera vCam; + static ScreenShakeUpdate shakeUpdate; + + class ScreenShakeUpdate : MonoBehaviour { + [HideInInspector] public float shakeTimer; + [HideInInspector] public float shakeTimerTotal; + [HideInInspector] public float startingIntensity; + + void Update(){ + if (shakeTimer > 0){ + shakeTimer -= Time.deltaTime; + CinemachineBasicMultiChannelPerlin multiChannelPerlin = vCam.GetCinemachineComponent(); + multiChannelPerlin.m_AmplitudeGain = Mathf.Lerp(startingIntensity, 0f, 1 - (shakeTimer / shakeTimerTotal)); + } + } + } + + public static void Shake(float intensity, float time){ + if(vCam == null || shakeUpdate == null){ + vCam = Camera.main.GetComponent().ActiveVirtualCamera.VirtualCameraGameObject.GetComponent(); + shakeUpdate = new GameObject("ShakeUpdate").AddComponent(); + } + shakeUpdate.startingIntensity = intensity; + shakeUpdate.shakeTimer = shakeUpdate.shakeTimerTotal = time; + } +} diff --git a/Tools/Cinemachine/ScreenShake.cs.meta b/Tools/Cinemachine/ScreenShake.cs.meta new file mode 100644 index 0000000..048e505 --- /dev/null +++ b/Tools/Cinemachine/ScreenShake.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 181034c7ad5ece241a2737ab35d47c5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/DialogueSystem.meta b/Tools/DialogueSystem.meta new file mode 100644 index 0000000..b94d838 --- /dev/null +++ b/Tools/DialogueSystem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 645cca644899cc74882ea9bc1d9c5aa9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/DialogueSystem/Dialogue.cs b/Tools/DialogueSystem/Dialogue.cs new file mode 100644 index 0000000..6df4ba6 --- /dev/null +++ b/Tools/DialogueSystem/Dialogue.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "New Character", menuName = "Tools/Character", order = 0)] +public class Dialogue : ScriptableObject{ + + public bool displayName; + public string characterName; + + [Space] + public Sprite characterImage; + [TextArea] public string[] sentences; +} diff --git a/Tools/DialogueSystem/Dialogue.cs.meta b/Tools/DialogueSystem/Dialogue.cs.meta new file mode 100644 index 0000000..63ccf99 --- /dev/null +++ b/Tools/DialogueSystem/Dialogue.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd553cd05b84d614b998afe62e37c17c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 4dfc626116fd10c4f972c17720d957ac, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/DialogueSystem/Dialogue.png b/Tools/DialogueSystem/Dialogue.png new file mode 100644 index 0000000..3bff2d3 Binary files /dev/null and b/Tools/DialogueSystem/Dialogue.png differ diff --git a/Tools/DialogueSystem/Dialogue.png.meta b/Tools/DialogueSystem/Dialogue.png.meta new file mode 100644 index 0000000..4991597 --- /dev/null +++ b/Tools/DialogueSystem/Dialogue.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 4dfc626116fd10c4f972c17720d957ac +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/DialogueSystem/DialogueSystem.cs b/Tools/DialogueSystem/DialogueSystem.cs new file mode 100644 index 0000000..234cad5 --- /dev/null +++ b/Tools/DialogueSystem/DialogueSystem.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using TMPro; +using UnityEngine; +using UnityEngine.UI; + +public class DialogueSystem : MonoBehaviour{ + + public static DialogueSystem instance; + + public GameObject nameField = default; + public TextMeshProUGUI nameText = default; + public TMP_Animated dialogue = default; + public Image faceImage = default; + + Queue sentences; + bool talking; + Animator anim; + + void Awake(){ + instance = this; + sentences = new Queue(); + anim = GetComponent(); + } + + public bool Dialogue(Dialogue dialogue){ + if(!talking){ + if (dialogue.displayName){ + nameText.text = dialogue.characterName; + nameField.SetActive(true); + nameText.gameObject.SetActive(true); + }else{ + nameField.SetActive(false); + nameText.gameObject.SetActive(false); + } + + if (dialogue.characterImage) + faceImage.sprite = dialogue.characterImage; + else + faceImage.sprite = null; + + sentences.Clear(); + if(dialogue.sentences.Length != 0){ + foreach (string sentence in dialogue.sentences){ + sentences.Enqueue(sentence); + } + }else{ + sentences.Enqueue("I am error. No text has been added"); + } + talking = true; + + if(sentences.Count == 0){ + talking = false; + return false; + } + + string sentenceToShow = sentences.Dequeue(); + this.dialogue.ReadText(sentenceToShow); + anim.SetBool("Talking", true); + return true; + }else{ + if (sentences.Count == 0){ + talking = false; + anim.SetBool("Talking", false); + return false; + } + + string sentenceToShow = sentences.Dequeue(); + this.dialogue.ReadText(sentenceToShow); + return true; + } + } +} diff --git a/Tools/DialogueSystem/DialogueSystem.cs.meta b/Tools/DialogueSystem/DialogueSystem.cs.meta new file mode 100644 index 0000000..8211dcb --- /dev/null +++ b/Tools/DialogueSystem/DialogueSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: caad12703fd5c3349acc637253734ac9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/DialogueSystem/TMP_Animated.cs b/Tools/DialogueSystem/TMP_Animated.cs new file mode 100644 index 0000000..b85b257 --- /dev/null +++ b/Tools/DialogueSystem/TMP_Animated.cs @@ -0,0 +1,71 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Events; + +namespace TMPro{ + [System.Serializable] public class TextRevealEvent : UnityEvent { } + [System.Serializable] public class DialogueEvent : UnityEvent { } + + public class TMP_Animated : TextMeshProUGUI{ + + float speed; + + public TextRevealEvent onTextReveal; + public DialogueEvent onDialogueFinish; + + public void ReadText(string newText){ + text = string.Empty; + + string[] subTexts = newText.Split('<', '>'); + + string displayText = ""; + for (int i = 0; i < subTexts.Length; i++){ + if (i % 2 == 0) + displayText += subTexts[i]; + else if (!isCustomTag(subTexts[i].Replace(" ", ""))) + displayText += $"<{subTexts[i]}>"; + } + + bool isCustomTag(string tag){ + return tag.StartsWith("speed=") || tag.StartsWith("pause="); + } + + text = displayText; + maxVisibleCharacters = 0; + StartCoroutine(Read()); + + IEnumerator Read(){ + int subCounter = 0; + int visibleCounter = 0; + while(subCounter < subTexts.Length){ + if(subCounter % 2 == 1){ + yield return EvaluateTag(subTexts[subCounter].Replace(" ", "")); + }else{ + while(visibleCounter < subTexts[subCounter].Length){ + onTextReveal.Invoke(subTexts[subCounter][visibleCounter]); + visibleCounter++; + maxVisibleCharacters++; + yield return new WaitForSeconds(1f / speed); + } + visibleCounter = 0; + } + subCounter++; + } + yield return null; + + WaitForSeconds EvaluateTag(string tag){ + if (tag.Length > 0){ + if (tag.StartsWith("speed=")){ + speed = float.Parse(tag.Split('=')[1]); + }else if (tag.StartsWith("pause=")){ + return new WaitForSeconds(float.Parse(tag.Split('=')[1])); + } + } + return null; + } + + onDialogueFinish.Invoke(); + } + } + } +} diff --git a/Tools/DialogueSystem/TMP_Animated.cs.meta b/Tools/DialogueSystem/TMP_Animated.cs.meta new file mode 100644 index 0000000..8231160 --- /dev/null +++ b/Tools/DialogueSystem/TMP_Animated.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f713d84a3ae882945800780459e26170 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 2fd6421f253b4ef1a19526541f9ffc0c, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/Editor.meta b/Tools/Editor.meta new file mode 100644 index 0000000..550a16f --- /dev/null +++ b/Tools/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 53d517df853ee5d44b788e900f897c54 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/Editor/Square.png b/Tools/Editor/Square.png new file mode 100644 index 0000000..8eb1b1e Binary files /dev/null and b/Tools/Editor/Square.png differ diff --git a/Tools/Editor/Square.png.meta b/Tools/Editor/Square.png.meta new file mode 100644 index 0000000..f6ffc2c --- /dev/null +++ b/Tools/Editor/Square.png.meta @@ -0,0 +1,104 @@ +fileFormatVersion: 2 +guid: d93624141d1826749b7f50e692cc2a93 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 0 + aniso: 1 + mipBias: 0 + wrapU: 0 + wrapV: 0 + wrapW: 0 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 3 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 4 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 4 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: + - - {x: -2, y: -2} + - {x: -2, y: 2} + - {x: 2, y: 2} + - {x: 2, y: -2} + physicsShape: + - - {x: -2, y: -2} + - {x: -2, y: 2} + - {x: 2, y: 2} + - {x: 2, y: -2} + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tools/Editor/ToolsEditor.cs b/Tools/Editor/ToolsEditor.cs new file mode 100644 index 0000000..3569126 --- /dev/null +++ b/Tools/Editor/ToolsEditor.cs @@ -0,0 +1,531 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; +using UnityEngine.UI; +using TMPro; +using Cinemachine; +using UnityEngine.SceneManagement; +using UnityEditor.SceneManagement; +using UnityEngine.EventSystems; +using UnityEditor.Experimental.SceneManagement; +using System; + +public class ToolsEditor{ + + [MenuItem("GameObject/Tools/AudioManager", false, 10)] + static void CreateAudioManager(){ + GameObject audioManager = new GameObject("AudioManager"); + audioManager.AddComponent(); + } + + [MenuItem("GameObject/Tools/Dialogue System", false, 10)] + static void CreateDialogueSystem(){ + GameObject dialogueCanvas = new GameObject("DialogueCanvas"); + dialogueCanvas.AddComponent(); + Canvas canvas = dialogueCanvas.AddComponent(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; + dialogueCanvas.AddComponent(); + dialogueCanvas.AddComponent(); + + GameObject text = new GameObject("TMP_Animated"); + text.transform.SetParent(dialogueCanvas.transform); + text.AddComponent().text = "New Text"; + text.GetComponent().anchoredPosition = Vector2.zero; + + GameObject name = new GameObject("NameText"); + name.transform.SetParent(dialogueCanvas.transform); + name.AddComponent().text = "Name"; + name.GetComponent().anchoredPosition = Vector2.up * 50f; + + GameObject image = new GameObject("Image"); + image.transform.SetParent(dialogueCanvas.transform); + image.AddComponent(); + image.GetComponent().anchoredPosition = new Vector2(-150f, 25f); + + DialogueSystem dialogueSystem = dialogueCanvas.AddComponent(); + dialogueSystem.nameText = name.GetComponent(); + dialogueSystem.dialogue = text.GetComponent(); + dialogueSystem.faceImage = image.GetComponent(); + dialogueSystem.nameField = name; + } + + [MenuItem("GameObject/Tools/Camera Trigger/2D", false, 10)] + static void CreateCameraTrigger2D(){ + GameObject cameraTrigger = new GameObject("CameraTrigger2D"); + cameraTrigger.AddComponent(); + cameraTrigger.AddComponent(); + + GameObject vCam = new GameObject("CM vcam1"); + vCam.transform.SetParent(cameraTrigger.transform); + vCam.SetActive(false); + CinemachineVirtualCamera cam = vCam.AddComponent(); + cam.m_Lens.Orthographic = true; + } + + [MenuItem("GameObject/Tools/Camera Trigger/3D", false, 10)] + static void CreateCameraTrigger3D(){ + GameObject cameraTrigger = new GameObject("CameraTrigger3D"); + cameraTrigger.AddComponent(); + cameraTrigger.AddComponent(); + + GameObject vCam = new GameObject("CM vcam1"); + vCam.transform.SetParent(cameraTrigger.transform); + vCam.SetActive(false); + CinemachineVirtualCamera cam = vCam.AddComponent(); + cam.m_Lens.FieldOfView = 60f; + } + +#if CINEMACHINE_271_OR_NEWER + [MenuItem("GameObject/Tools/ScreenShake Camera/2D", false, 10)] + static void CreateScreenShakeCamera2d(){ + GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); + CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); + vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Orthographic; + + CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); + + NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); + + shake.m_NoiseProfile = noise; + shake.m_AmplitudeGain = 0f; + shake.m_FrequencyGain = 1f; + } + [MenuItem("GameObject/Tools/ScreenShake Camera/3D", false, 10)] + static void CreateScreenShakeCamera3d(){ + GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); + CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); + vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Perspective; + + CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); + + NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); + + shake.m_NoiseProfile = noise; + shake.m_AmplitudeGain = 0f; + shake.m_FrequencyGain = 1f; + } +#else + [MenuItem("GameObject/Tools/ScreenShake Camera", false, 10)] + static void CreateScreenShakeCamera2d(){ + GameObject screenShakeCamera = new GameObject("ScreenShakeCamera"); + CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent(); + + CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent(); + + NoiseSettings noise = (NoiseSettings)AssetDatabase.LoadAssetAtPath("Packages/com.unity.cinemachine/Presets/Noise/6D Shake.asset", typeof(NoiseSettings)); + + shake.m_NoiseProfile = noise; + shake.m_AmplitudeGain = 0f; + shake.m_FrequencyGain = 1f; + } +#endif + + [MenuItem("Assets/Create/Tools/Create Loading Scene")] + static void CreateLoadingScene(){ + EditorSceneManager.SaveOpenScenes(); + + Scene loadingScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); + loadingScene.name = "Loading"; + + GameObject loaderCallback = new GameObject("LoaderCallback"); + loaderCallback.AddComponent(); + + GameObject canvasObj = new GameObject("Canvas"); + Canvas canvas = canvasObj.AddComponent(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; + + CanvasScaler canvasScaler = canvasObj.AddComponent(); + canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; + canvasScaler.referenceResolution = new Vector2Int(951, 535); + canvasScaler.matchWidthOrHeight = 1f; + + canvasObj.AddComponent(); + + TextMeshProUGUI loadingText = new GameObject("LoadingText").AddComponent(); + loadingText.transform.SetParent(canvasObj.transform); + RectTransform loadingTextTransform = loadingText.GetComponent(); + loadingTextTransform.anchoredPosition = new Vector2Int(-333, -212); + loadingTextTransform.sizeDelta = new Vector2Int(237, 52); + loadingText.text = "LOADING..."; + + Image bg = new GameObject("bg").AddComponent(); + bg.transform.SetParent(canvasObj.transform); + RectTransform bgTransform = bg.GetComponent(); + bgTransform.anchoredPosition = new Vector2Int(0, -235); + bgTransform.sizeDelta = new Vector2Int(900, 20); + bg.color = new Color(36f / 255f, 36f / 255f, 36f / 255f); + + Image progressBar = new GameObject("ProgressBar").AddComponent(); + progressBar.transform.SetParent(bg.transform); + RectTransform progressBarTransform = progressBar.GetComponent(); + progressBarTransform.anchoredPosition = Vector2.zero; + progressBarTransform.sizeDelta = new Vector2Int(900, 20); + + progressBar.sprite = (Sprite)AssetDatabase.LoadAssetAtPath("Packages/com.geri.simpletools/Tools/Editor/Square.png", typeof(Sprite)); + progressBar.type = Image.Type.Filled; + progressBar.fillMethod = Image.FillMethod.Horizontal; + progressBar.fillOrigin = (int)Image.OriginHorizontal.Left; + progressBar.fillAmount = 1f; + progressBar.gameObject.AddComponent(); + } + + [MenuItem("Assets/Create/Tools/Create Menu Scene")] + static void CreateMenuScene(){ + EditorSceneManager.SaveOpenScenes(); + + Scene menuScene = EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects); + menuScene.name = "Menu"; + + GameObject canvasObj = new GameObject("Canvas"); + Canvas canvas = canvasObj.AddComponent(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; + + CreateEventSystem(false, null); + + CanvasScaler canvasScaler = canvasObj.AddComponent(); + canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize; + canvasScaler.referenceResolution = new Vector2Int(951, 535); + canvasScaler.matchWidthOrHeight = 1f; + + canvasObj.AddComponent(); + + GameObject qualityDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources()); + qualityDropdown.transform.SetParent(canvasObj.transform); + RectTransform qualityRectTransform = qualityDropdown.GetComponent(); + qualityRectTransform.anchoredPosition = Vector2.up * 15f; + qualityDropdown.name = "QualityDropdown"; + + GameObject resolutionDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources()); + resolutionDropdown.transform.SetParent(canvasObj.transform); + RectTransform resolutionRectTransform = resolutionDropdown.GetComponent(); + resolutionRectTransform.anchoredPosition = Vector2.down * 15f; + resolutionDropdown.name = "ResolutionDropdown"; + + GameObject musicSlider; + using (new FactorySwapToEditor()) + musicSlider = DefaultControls.CreateSlider(GetStandardUIResources()); + musicSlider.transform.SetParent(canvasObj.transform); + RectTransform musicRectTransform = musicSlider.GetComponent(); + musicRectTransform.anchoredPosition = Vector2.down * 40f; + musicSlider.name = "MusicSlider"; + + GameObject sfxSlider; + using (new FactorySwapToEditor()) + sfxSlider = DefaultControls.CreateSlider(GetStandardUIResources()); + sfxSlider.transform.SetParent(canvasObj.transform); + RectTransform sfxRectTransform = sfxSlider.GetComponent(); + sfxRectTransform.anchoredPosition = Vector2.down * 60; + sfxSlider.name = "MusicSlider"; + + GameObject playButton = TMP_DefaultControls.CreateButton(GetStandardResources()); + playButton.transform.SetParent(canvasObj.transform); + TMP_Text playTextComponent = playButton.GetComponentInChildren(); + playTextComponent.fontSize = 24; + playTextComponent.text = "PLAY"; + RectTransform playRectTransform = playButton.GetComponent(); + playRectTransform.anchoredPosition = Vector2.up * 45f; + playButton.name = "PlayButton"; + + GameObject quitButton = TMP_DefaultControls.CreateButton(GetStandardResources()); + quitButton.transform.SetParent(canvasObj.transform); + TMP_Text quitTextComponent = quitButton.GetComponentInChildren(); + quitTextComponent.fontSize = 24; + quitTextComponent.text = "QUIT"; + RectTransform quitRectTransform = quitButton.GetComponent(); + quitRectTransform.anchoredPosition = Vector2.down * 85f; + quitButton.name = "QuitButton"; + + MenuController menuController = canvasObj.AddComponent(); + Slider sliderMusic = menuController.musicSlider = musicSlider.GetComponent(); + Slider sliderSfx = menuController.sfxSlider = sfxSlider.GetComponent(); + TMP_Dropdown dropdownQuality = menuController.qualityDropdown = qualityDropdown.GetComponent(); + TMP_Dropdown dropdownResolution = menuController.resolutionDropdown = resolutionDropdown.GetComponent(); + + sliderMusic.onValueChanged.AddListener(menuController.SetMusicVolume); + sliderSfx.onValueChanged.AddListener(menuController.SetSfxVolume); + dropdownQuality.onValueChanged.AddListener(menuController.SetQuality); + dropdownResolution.onValueChanged.AddListener(menuController.SetResolution); + + playButton.GetComponent