Add files via upload

This commit is contained in:
Gerard Gascón 2022-09-22 13:43:53 +02:00 committed by GitHub
parent 4151df9226
commit 1df7a33ab0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
69 changed files with 3583 additions and 0 deletions

19
SimpleTools/LICENSE.md Normal file
View file

@ -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.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 535f36a1918d4d2479031f3ca2725323
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

145
SimpleTools/README.md Normal file
View file

@ -0,0 +1,145 @@
# Simple Tools
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.
- 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/GerardGascon/SimpleTools.git](https://github.com/GerardGascon/SimpleTools.git)
or
Open the manifest.json file of your Unity project. Add "com.geri.simpletools": "[https://github.com/GerardGascon/SimpleTools.git](https://github.com/GerardGascon/SimpleTools.git)"
### Manual Installation
Download latest package from the Release section Import SimpleTools.unitypackage to your Unity Project
## Usage
### AudioManager
```csharp
using SimpleTools.AudioManager;
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.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
using SimpleTools.ObjectPooler;
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.Destroy(gameObject); //Destroys a GameObject and returns it into the pool scene
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
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
```
Text commands:
```html
<color=color></color> --> Sets font color within tags
<size=percentage></size> --> Sets font size within tags
<sprite=index> --> Draws a sprite from the TextMeshPro
<p:[tiny,short,normal,long,read]> --> Pauses during a period of time
<anim:[wobble,wave,rainbow,shake]></anim> --> Reproduces an animation
<sp:number></sp> --> Changes reveal speed
```
### SceneManager
```csharp
using SimpleTools.SceneManagement;
Loader.Load(0); //Loads a scene with a specific build index
Loader.Load("Scene"); //Loads a scene with a specific name
```
### ScreenShake
```csharp
using SimpleTools.Cinemachine;
ScreenShake.Shake(1f, .25f); //Shakes the camera with an intensity and duration
```
### Timer
```csharp
using SimpleTools.Timer;
//Setup a stopwatch that updates at an unscaled time
Timer timer = textMeshProText.SetupTimer(TimerType.Stopwatch, TimerUpdate.UnscaledTime);
//Setup a clock
Timer timer = textMeshProText.SetupTimer(TimerType.Clock, TimerUpdate.UnscaledTime);
//Setup a countdown with the default time of 60 seconds
Timer timer = textMeshProText.SetupTimer(TimerType.Countdown, TimerUpdate.UnscaledTime, 60f);
timer.Play(); //Play or resume the timer
timer.Stop(); //Pause the timer
timer.ResetTimer(); //Pause and sets the time to the default one
timer.Restart(); //Restarts the timer
```
### 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.

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ee23fd1b6b87e954f836c97747d4c083
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
SimpleTools/Tools.meta Normal file
View file

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

View file

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

View file

@ -0,0 +1,271 @@
using System.Collections;
using UnityEngine;
using System;
namespace SimpleTools.AudioManager {
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<AudioSource>();
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
/// <summary>Use this to play a sound with a specific name
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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();
}
/// <summary>Use this to play a sound with a specific name and with a certain delay
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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);
}
/// <summary>Use this to play one shot of a sound with a specific name
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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);
}
/// <summary>Use this to play an intro song and then start playing the song loop
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
public void PlayWithIntro(string intro, string song) {
Sounds.List s = Array.Find(soundList.sounds, sound => sound.name == intro);
if (s == null) {
Debug.LogWarning("Sound: " + intro + " not found!");
return;
}
s.source.pitch = s.RandomPitch;
s.source.volume = s.RandomVolume;
s.source.Play();
float introDuration = s.clip.length;
Play(song, introDuration);
}
/// <summary>Use this to play one shot of a random sound within a list
/// <para>They have to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
public void PlayRandomSound(params string[] names) {
int random = UnityEngine.Random.Range(0, names.Length);
PlayOneShot(names[random]);
}
#endregion
#region Pause
/// <summary>Use this to pause a sound with a specific name
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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();
}
/// <summary>Use this to unpause a sound with a specific name
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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
/// <summary>Use this to stop a sound with a specific name
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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();
}
/// <summary>Use this to stop all the sounds
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
public void StopAll() {
foreach (Sounds.List s in soundList.sounds) {
if (s.source) {
s.source.Stop();
}
}
}
#endregion
/// <summary>This function returns the AudioSource that contains a specific sound
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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
/// <summary>Use this to start playing a sound with a fade in
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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;
}
}
/// <summary>Use this to stop playing a sound with a fade out
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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;
}
}
/// <summary>Use this to start playing a sound muted
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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();
}
/// <summary>Use this to fade in a sound that is currently muted
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// <para>WARNING: If the PlayMuted hasn't been called before, this function won't work</para>
/// </summary>
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;
}
/// <summary>Use this to fade out a sound and keep playing that muted
/// <para>It has to be in the Sound asset referenced in the AudioManager instance</para>
/// </summary>
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
}
}

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -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:

View file

@ -0,0 +1,53 @@
using UnityEngine;
using UnityEngine.Audio;
namespace SimpleTools.AudioManager {
[CreateAssetMenu(fileName = "Sounds", menuName = "Simple Tools/Sounds", order = 11)]
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;
}
}
}
}
}

View file

@ -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:

View file

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

View file

@ -0,0 +1,40 @@
using UnityEngine;
using Cinemachine;
namespace SimpleTools.Cinemachine {
public class CMCameraTrigger : MonoBehaviour {
CinemachineVirtualCamera vcam;
void Awake() {
vcam = GetComponentInChildren<CinemachineVirtualCamera>(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
}
}

View file

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

View file

@ -0,0 +1,38 @@
using Cinemachine;
using UnityEngine;
namespace SimpleTools.Cinemachine {
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<CinemachineBasicMultiChannelPerlin>();
multiChannelPerlin.m_AmplitudeGain = Mathf.Lerp(startingIntensity, 0f, 1 - (shakeTimer / shakeTimerTotal));
}
}
}
/// <summary>Shake the camera
/// <para>It needs a cinemachine camera with a noise profile in it.</para>
/// </summary>
public static void Shake(float intensity, float time) {
if (vCam == null) {
vCam = Camera.main.GetComponent<CinemachineBrain>().ActiveVirtualCamera.VirtualCameraGameObject.GetComponent<CinemachineVirtualCamera>();
}
if (shakeUpdate == null) {
shakeUpdate = new GameObject("ShakeUpdate").AddComponent<ScreenShakeUpdate>();
}
shakeUpdate.startingIntensity = intensity;
shakeUpdate.shakeTimer = shakeUpdate.shakeTimerTotal = time;
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,16 @@
using UnityEngine;
namespace SimpleTools.DialogueSystem {
[CreateAssetMenu(fileName = "New Dialogue", menuName = "Simple Tools/Dialogue", order = 11)]
public class Dialogue : ScriptableObject {
public DialogueBox[] sentences;
}
[System.Serializable]
public class DialogueBox {
public bool displayName;
public string characterName;
public Sprite characterImage;
[TextArea(5, 10)] public string sentence;
}
}

View file

@ -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:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -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:

View file

@ -0,0 +1,111 @@
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace SimpleTools.DialogueSystem {
public class DialogueManager : MonoBehaviour {
DialogueVertexAnimator dialogueVertexAnimator;
Queue<string> sentences;
Queue<bool> displayNames;
Queue<string> characterNames;
Queue<Sprite> characterImages;
bool talking;
public DialogueItems dialogueItems;
public static DialogueManager instance;
void Awake() {
instance = this;
sentences = new Queue<string>();
displayNames = new Queue<bool>();
characterNames = new Queue<string>();
characterImages = new Queue<Sprite>();
dialogueVertexAnimator = new DialogueVertexAnimator(dialogueItems.textBox);
}
public bool Dialogue(Dialogue dialogue) {
return Dialogue(dialogue, string.Empty);
}
public bool Dialogue(Dialogue dialogue, params string[] sounds) {
dialogueVertexAnimator.SetAudioSourceGroup(sounds);
if (!talking) {
sentences.Clear();
if (dialogue.sentences.Length != 0) {
foreach (DialogueBox sentence in dialogue.sentences) {
sentences.Enqueue(sentence.sentence);
displayNames.Enqueue(sentence.displayName);
characterNames.Enqueue(sentence.characterName);
characterImages.Enqueue(sentence.characterImage);
}
} else {
sentences.Enqueue("I am error. No text has been added");
}
talking = true;
if (sentences.Count == 0) {
talking = false;
return false;
}
string sentenceToShow = sentences.Peek();
bool displayName = displayNames.Peek();
string characterName = characterNames.Peek();
Sprite characterImage = characterImages.Peek();
if (PlayDialogue(sentenceToShow, displayName, characterName, characterImage)) {
sentences.Dequeue();
displayNames.Dequeue();
characterNames.Dequeue();
characterImages.Dequeue();
}
return true;
} else {
if (sentences.Count == 0) {
talking = false;
return false;
}
string sentenceToShow = sentences.Peek();
bool displayName = displayNames.Peek();
string characterName = characterNames.Peek();
Sprite characterImage = characterImages.Peek();
if (PlayDialogue(sentenceToShow, displayName, characterName, characterImage)) {
sentences.Dequeue();
displayNames.Dequeue();
characterNames.Dequeue();
characterImages.Dequeue();
}
return true;
}
}
private Coroutine typeRoutine = null;
bool PlayDialogue(string message, bool displayName = false, string characterName = "", Sprite characterImage = null) {
if (dialogueVertexAnimator.IsMessageAnimating()) {
dialogueVertexAnimator.SkipToEndOfCurrentMessage();
return false; //Next message hasn't been shown because the current one is still animating.
}
this.EnsureCoroutineStopped(ref typeRoutine);
dialogueVertexAnimator.textAnimating = false;
List<DialogueCommand> commands = DialogueUtility.ProcessInputString(message, out string totalTextMessage);
typeRoutine = StartCoroutine(dialogueVertexAnimator.AnimateTextIn(commands, totalTextMessage, null));
dialogueItems.characterImage.sprite = characterImage;
dialogueItems.characterName.text = displayName ? characterName : "???";
return true; //Next message shown successfully
}
}
[System.Serializable]
public struct DialogueItems {
public Image characterImage;
public TMP_Text characterName;
public TMP_Text textBox;
public Canvas canvas;
}
}

View file

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

View file

@ -0,0 +1,170 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System;
namespace SimpleTools.DialogueSystem {
public class DialogueUtility : MonoBehaviour {
// grab the remainder of the text until ">" or end of string
const string REMAINDER_REGEX = "(.*?((?=>)|(/|$)))";
const string PAUSE_REGEX_STRING = "<p:(?<pause>" + REMAINDER_REGEX + ")>";
static readonly Regex pauseRegex = new Regex(PAUSE_REGEX_STRING);
const string SOUND_REGEX_STRING = "<snd:(?<sound>" + REMAINDER_REGEX + ")>";
static readonly Regex soundRegex = new Regex(SOUND_REGEX_STRING);
const string SPEED_REGEX_STRING = "<sp:(?<speed>" + REMAINDER_REGEX + ")>";
static readonly Regex speedRegex = new Regex(SPEED_REGEX_STRING);
const string ANIM_START_REGEX_STRING = "<anim:(?<anim>" + REMAINDER_REGEX + ")>";
static readonly Regex animStartRegex = new Regex(ANIM_START_REGEX_STRING);
const string ANIM_END_REGEX_STRING = "</anim>";
static readonly Regex animEndRegex = new Regex(ANIM_END_REGEX_STRING);
static readonly Dictionary<string, float> pauseDictionary = new Dictionary<string, float>{
{ "tiny", .1f },
{ "short", .25f },
{ "normal", 0.666f },
{ "long", 1f },
{ "read", 2f },
};
public static List<DialogueCommand> ProcessInputString(string message, out string processedMessage) {
List<DialogueCommand> result = new List<DialogueCommand>();
processedMessage = message;
processedMessage = HandlePauseTags(processedMessage, result);
processedMessage = HandleSoundTags(processedMessage, result);
processedMessage = HandleSpeedTags(processedMessage, result);
processedMessage = HandleAnimStartTags(processedMessage, result);
processedMessage = HandleAnimEndTags(processedMessage, result);
return result;
}
static string HandleAnimEndTags(string processedMessage, List<DialogueCommand> result) {
MatchCollection animEndMatches = animEndRegex.Matches(processedMessage);
foreach (Match match in animEndMatches) {
result.Add(new DialogueCommand {
position = VisibleCharactersUpToIndex(processedMessage, match.Index),
type = DialogueCommandType.AnimEnd,
});
}
processedMessage = Regex.Replace(processedMessage, ANIM_END_REGEX_STRING, "");
return processedMessage;
}
static string HandleAnimStartTags(string processedMessage, List<DialogueCommand> result) {
MatchCollection animStartMatches = animStartRegex.Matches(processedMessage);
foreach (Match match in animStartMatches) {
string stringVal = match.Groups["anim"].Value;
result.Add(new DialogueCommand {
position = VisibleCharactersUpToIndex(processedMessage, match.Index),
type = DialogueCommandType.AnimStart,
textAnimValue = GetTextAnimationType(stringVal)
});
}
processedMessage = Regex.Replace(processedMessage, ANIM_START_REGEX_STRING, "");
return processedMessage;
}
static string HandleSpeedTags(string processedMessage, List<DialogueCommand> result) {
MatchCollection speedMatches = speedRegex.Matches(processedMessage);
foreach (Match match in speedMatches) {
string stringVal = match.Groups["speed"].Value;
if (!float.TryParse(stringVal, out float val)) {
val = 150f;
}
result.Add(new DialogueCommand {
position = VisibleCharactersUpToIndex(processedMessage, match.Index),
type = DialogueCommandType.TextSpeedChange,
floatValue = val
});
}
processedMessage = Regex.Replace(processedMessage, SPEED_REGEX_STRING, "");
return processedMessage;
}
static string HandlePauseTags(string processedMessage, List<DialogueCommand> result) {
MatchCollection pauseMatches = pauseRegex.Matches(processedMessage);
foreach (Match match in pauseMatches) {
string val = match.Groups["pause"].Value;
string pauseName = val;
Debug.Assert(pauseDictionary.ContainsKey(pauseName), "no pause registered for '" + pauseName + "'");
result.Add(new DialogueCommand {
position = VisibleCharactersUpToIndex(processedMessage, match.Index),
type = DialogueCommandType.Pause,
floatValue = pauseDictionary[pauseName]
});
}
processedMessage = Regex.Replace(processedMessage, PAUSE_REGEX_STRING, "");
return processedMessage;
}
static string HandleSoundTags(string processedMessage, List<DialogueCommand> result) {
MatchCollection soundMatches = soundRegex.Matches(processedMessage);
foreach (Match match in soundMatches) {
string val = match.Groups["sound"].Value;
string soundName = val;
result.Add(new DialogueCommand {
position = VisibleCharactersUpToIndex(processedMessage, match.Index),
type = DialogueCommandType.Sound,
stringValue = soundName
});
}
processedMessage = Regex.Replace(processedMessage, SOUND_REGEX_STRING, "");
return processedMessage;
}
static TextAnimationType GetTextAnimationType(string stringVal) {
TextAnimationType result;
try {
result = (TextAnimationType)Enum.Parse(typeof(TextAnimationType), stringVal, true);
} catch (ArgumentException) {
Debug.LogError("Invalid Text Animation Type: " + stringVal);
result = TextAnimationType.none;
}
return result;
}
static int VisibleCharactersUpToIndex(string message, int index) {
int result = 0;
bool insideBrackets = false;
for (int i = 0; i < index; i++) {
if (message[i] == '<') {
insideBrackets = true;
} else if (message[i] == '>') {
insideBrackets = false;
result--;
}
if (!insideBrackets) {
result++;
} else if (i + 6 < index && message.Substring(i, 6) == "sprite") {
result++;
}
}
return result;
}
}
public struct DialogueCommand {
public int position;
public DialogueCommandType type;
public float floatValue;
public string stringValue;
public TextAnimationType textAnimValue;
}
public enum DialogueCommandType {
Pause,
TextSpeedChange,
AnimStart,
AnimEnd,
Sound
}
public enum TextAnimationType {
none,
shake,
wave,
wobble,
rainbow,
}
}

View file

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

View file

@ -0,0 +1,265 @@
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
namespace SimpleTools.DialogueSystem {
public class DialogueVertexAnimator {
public bool textAnimating = false;
bool stopAnimating = false;
readonly TMP_Text textBox;
string[] audioSourceGroup;
public void SetAudioSourceGroup(params string[] _audioSourceGroup) {
audioSourceGroup = _audioSourceGroup;
}
public DialogueVertexAnimator(TMP_Text _textBox) {
textBox = _textBox;
}
static readonly Color32 clear = new Color32(0, 0, 0, 0);
const float CHAR_ANIM_TIME = 0.07f;
static readonly Vector3 vecZero = Vector3.zero;
public IEnumerator AnimateTextIn(List<DialogueCommand> commands, string processedMessage, Action onFinish) {
textAnimating = true;
float secondsPerCharacter = 1f / 150f;
float timeOfLastCharacter = 0;
TextAnimInfo[] textAnimInfo = SeparateOutTextAnimInfo(commands);
TMP_TextInfo textInfo = textBox.textInfo;
for (int i = 0; i < textInfo.meshInfo.Length; i++) {
TMP_MeshInfo meshInfer = textInfo.meshInfo[i];
if (meshInfer.vertices != null) {
for (int j = 0; j < meshInfer.vertices.Length; j++) {
meshInfer.vertices[j] = vecZero;
}
}
}
textBox.text = processedMessage;
textBox.ForceMeshUpdate();
TMP_MeshInfo[] cachedMeshInfo = textInfo.CopyMeshInfoVertexData();
Color32[][] originalColors = new Color32[textInfo.meshInfo.Length][];
for (int i = 0; i < originalColors.Length; i++) {
Color32[] theColors = textInfo.meshInfo[i].colors32;
originalColors[i] = new Color32[theColors.Length];
Array.Copy(theColors, originalColors[i], theColors.Length);
}
int charCount = textInfo.characterCount;
float[] charAnimStartTimes = new float[charCount];
for (int i = 0; i < charCount; i++) {
charAnimStartTimes[i] = -1;
}
int visableCharacterIndex = 0;
while (true) {
if (stopAnimating) {
for (int i = visableCharacterIndex; i < charCount; i++) {
charAnimStartTimes[i] = Time.unscaledTime;
}
visableCharacterIndex = charCount;
FinishAnimating(onFinish);
}
if (ShouldShowNextCharacter(secondsPerCharacter, timeOfLastCharacter)) {
if (visableCharacterIndex <= charCount) {
ExecuteCommandsForCurrentIndex(commands, visableCharacterIndex, ref secondsPerCharacter, ref timeOfLastCharacter);
if (visableCharacterIndex < charCount && ShouldShowNextCharacter(secondsPerCharacter, timeOfLastCharacter)) {
charAnimStartTimes[visableCharacterIndex] = Time.unscaledTime;
PlayDialogueSound();
visableCharacterIndex++;
timeOfLastCharacter = Time.unscaledTime;
if (visableCharacterIndex == charCount) {
FinishAnimating(onFinish);
}
}
}
}
for (int j = 0; j < charCount; j++) {
TMP_CharacterInfo charInfo = textInfo.characterInfo[j];
if (charInfo.isVisible) {
int vertexIndex = charInfo.vertexIndex;
int materialIndex = charInfo.materialReferenceIndex;
Color32[] destinationColors = textInfo.meshInfo[materialIndex].colors32;
Color32 theColor = j < visableCharacterIndex ? originalColors[materialIndex][vertexIndex] : clear;
destinationColors[vertexIndex + 0] = theColor;
destinationColors[vertexIndex + 1] = theColor;
destinationColors[vertexIndex + 2] = theColor;
destinationColors[vertexIndex + 3] = theColor;
Vector3[] sourceVertices = cachedMeshInfo[materialIndex].vertices;
Vector3[] destinationVertices = textInfo.meshInfo[materialIndex].vertices;
float charSize = 0;
float charAnimStartTime = charAnimStartTimes[j];
if (charAnimStartTime >= 0) {
float timeSinceAnimStart = Time.unscaledTime - charAnimStartTime;
charSize = Mathf.Min(1, timeSinceAnimStart / CHAR_ANIM_TIME);
}
Vector3 animPosAdjustment = GetAnimPosAdjustment(textAnimInfo, j, textBox.fontSize, Time.unscaledTime);
Vector3 offset = (sourceVertices[vertexIndex + 0] + sourceVertices[vertexIndex + 2]) / 2;
destinationVertices[vertexIndex + 0] = ((sourceVertices[vertexIndex + 0] - offset) * charSize) + offset + animPosAdjustment;
destinationVertices[vertexIndex + 1] = ((sourceVertices[vertexIndex + 1] - offset) * charSize) + offset + animPosAdjustment;
destinationVertices[vertexIndex + 2] = ((sourceVertices[vertexIndex + 2] - offset) * charSize) + offset + animPosAdjustment;
destinationVertices[vertexIndex + 3] = ((sourceVertices[vertexIndex + 3] - offset) * charSize) + offset + animPosAdjustment;
for (int i = 0; i < 4; i++) {
Vector3 animVertexAdjustment = GetAnimVertexAdjustment(textAnimInfo, j, textBox.fontSize, Time.unscaledTime + i);
destinationVertices[vertexIndex + i] += animVertexAdjustment;
Color animColorAdjustment = GetAnimColorAdjustment(textAnimInfo, j, Time.unscaledTime + i, destinationVertices[vertexIndex + i]);
if (animColorAdjustment == Color.white)
continue;
destinationColors[vertexIndex + i] += animColorAdjustment;
}
}
}
textBox.UpdateVertexData(TMP_VertexDataUpdateFlags.Colors32);
for (int i = 0; i < textInfo.meshInfo.Length; i++) {
TMP_MeshInfo theInfo = textInfo.meshInfo[i];
theInfo.mesh.vertices = theInfo.vertices;
textBox.UpdateGeometry(theInfo.mesh, i);
}
yield return null;
}
}
void ExecuteCommandsForCurrentIndex(List<DialogueCommand> commands, int visableCharacterIndex, ref float secondsPerCharacter, ref float timeOfLastCharacter) {
for (int i = 0; i < commands.Count; i++) {
DialogueCommand command = commands[i];
if (command.position == visableCharacterIndex) {
switch (command.type) {
case DialogueCommandType.Pause:
timeOfLastCharacter = Time.unscaledTime + command.floatValue;
break;
case DialogueCommandType.TextSpeedChange:
secondsPerCharacter = 1f / command.floatValue;
break;
case DialogueCommandType.Sound:
AudioManager.AudioManager.instance.PlayOneShot(command.stringValue);
break;
}
commands.RemoveAt(i);
i--;
}
}
}
void FinishAnimating(Action onFinish) {
textAnimating = false;
stopAnimating = false;
onFinish?.Invoke();
}
const float NOISE_MAGNITUDE_ADJUSTMENT = 0.06f;
const float NOISE_FREQUENCY_ADJUSTMENT = 15f;
const float WAVE_MAGNITUDE_ADJUSTMENT = 0.06f;
const float WOBBLE_MAGNITUDE_ADJUSTMENT = 0.5f;
const float RAINBOW_LENGTH_ADJUSTMENT = .001f;
Vector3 GetAnimPosAdjustment(TextAnimInfo[] textAnimInfo, int charIndex, float fontSize, float time) {
float x = 0;
float y = 0;
for (int i = 0; i < textAnimInfo.Length; i++) {
TextAnimInfo info = textAnimInfo[i];
if (charIndex >= info.startIndex && charIndex < info.endIndex) {
if (info.type == TextAnimationType.shake) {
float scaleAdjust = fontSize * NOISE_MAGNITUDE_ADJUSTMENT;
x += (Mathf.PerlinNoise((charIndex + time) * NOISE_FREQUENCY_ADJUSTMENT, 0) - 0.5f) * scaleAdjust;
y += (Mathf.PerlinNoise((charIndex + time) * NOISE_FREQUENCY_ADJUSTMENT, 1000) - 0.5f) * scaleAdjust;
} else if (info.type == TextAnimationType.wave) {
y += Mathf.Sin((charIndex * 1.5f) + (time * 6)) * fontSize * WAVE_MAGNITUDE_ADJUSTMENT;
}
}
}
return new Vector3(x, y, 0);
}
Vector3 GetAnimVertexAdjustment(TextAnimInfo[] textAnimInfo, int charIndex, float fontSize, float time) {
float x = 0;
float y = 0;
for (int i = 0; i < textAnimInfo.Length; i++) {
TextAnimInfo info = textAnimInfo[i];
if (charIndex >= info.startIndex && charIndex < info.endIndex) {
if (info.type == TextAnimationType.wobble) {
float scaleAdjust = fontSize * NOISE_MAGNITUDE_ADJUSTMENT;
x = Mathf.Sin(time * 3.3f) * scaleAdjust * WOBBLE_MAGNITUDE_ADJUSTMENT;
y = Mathf.Cos(time * 2.5f) * scaleAdjust * WOBBLE_MAGNITUDE_ADJUSTMENT;
}
}
}
return new Vector3(x, y, 0);
}
Color GetAnimColorAdjustment(TextAnimInfo[] textAnimInfo, int charIndex, float time, Vector3 destinationVertice) {
Color color = Color.white;
for (int i = 0; i < textAnimInfo.Length; i++) {
TextAnimInfo info = textAnimInfo[i];
if (charIndex >= info.startIndex && charIndex < info.endIndex) {
if (info.type == TextAnimationType.rainbow) {
color = Color.HSVToRGB(Mathf.Repeat((time + destinationVertice.x * RAINBOW_LENGTH_ADJUSTMENT), 1f), .6f, 1);
}
}
}
return color;
}
static bool ShouldShowNextCharacter(float secondsPerCharacter, float timeOfLastCharacter) {
return (Time.unscaledTime - timeOfLastCharacter) > secondsPerCharacter;
}
public void SkipToEndOfCurrentMessage() {
if (textAnimating) {
stopAnimating = true;
}
}
public bool IsMessageAnimating() {
return textAnimating;
}
float timeUntilNextDialogueSound = 0;
float lastDialogueSound = 0;
void PlayDialogueSound() {
if (Time.unscaledTime - lastDialogueSound > timeUntilNextDialogueSound) {
timeUntilNextDialogueSound = UnityEngine.Random.Range(0.02f, 0.08f);
lastDialogueSound = Time.unscaledTime;
if (audioSourceGroup[0] != string.Empty)
AudioManager.AudioManager.instance.PlayRandomSound(audioSourceGroup);
}
}
TextAnimInfo[] SeparateOutTextAnimInfo(List<DialogueCommand> commands) {
List<TextAnimInfo> tempResult = new List<TextAnimInfo>();
List<DialogueCommand> animStartCommands = new List<DialogueCommand>();
List<DialogueCommand> animEndCommands = new List<DialogueCommand>();
for (int i = 0; i < commands.Count; i++) {
DialogueCommand command = commands[i];
if (command.type == DialogueCommandType.AnimStart) {
animStartCommands.Add(command);
commands.RemoveAt(i);
i--;
} else if (command.type == DialogueCommandType.AnimEnd) {
animEndCommands.Add(command);
commands.RemoveAt(i);
i--;
}
}
if (animStartCommands.Count != animEndCommands.Count) {
Debug.LogError("Unequal number of start and end animation commands. Start Commands: " + animStartCommands.Count + " End Commands: " + animEndCommands.Count);
} else {
for (int i = 0; i < animStartCommands.Count; i++) {
DialogueCommand startCommand = animStartCommands[i];
DialogueCommand endCommand = animEndCommands[i];
tempResult.Add(new TextAnimInfo {
startIndex = startCommand.position,
endIndex = endCommand.position,
type = startCommand.textAnimValue
});
}
}
return tempResult.ToArray();
}
}
public struct TextAnimInfo {
public int startIndex;
public int endIndex;
public TextAnimationType type;
}
}

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 B

View file

@ -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:

View file

@ -0,0 +1,548 @@
#if UNITY_EDITOR
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;
using SimpleTools.AudioManager;
using SimpleTools.DialogueSystem;
using SimpleTools.Cinemachine;
using SimpleTools.SceneManagement;
using SimpleTools.Menu;
public class ToolsEditor{
[MenuItem("GameObject/Simple Tools/AudioManager", false, 10)]
static void CreateAudioManager(){
GameObject audioManager = new GameObject("AudioManager");
audioManager.AddComponent<AudioManager>();
}
[MenuItem("GameObject/Simple Tools/Dialogue System", false, 10)]
static void CreateDialogueSystem(){
GameObject dialogueCanvas = new GameObject("DialogueCanvas");
dialogueCanvas.AddComponent<RectTransform>();
Canvas canvas = dialogueCanvas.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
dialogueCanvas.AddComponent<CanvasScaler>();
dialogueCanvas.AddComponent<GraphicRaycaster>();
GameObject text = new GameObject("DialogueText");
text.transform.SetParent(dialogueCanvas.transform);
text.AddComponent<TextMeshProUGUI>().text = "Dialogue";
text.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
GameObject name = new GameObject("NameText");
name.transform.SetParent(dialogueCanvas.transform);
name.AddComponent<TextMeshProUGUI>().text = "Name";
name.GetComponent<RectTransform>().anchoredPosition = Vector2.up * 50f;
GameObject image = new GameObject("Image");
image.transform.SetParent(dialogueCanvas.transform);
image.AddComponent<Image>();
image.GetComponent<RectTransform>().anchoredPosition = new Vector2(-150f, 25f);
DialogueManager dialogueManager = dialogueCanvas.AddComponent<DialogueManager>();
Debug.Log(dialogueManager.dialogueItems);
dialogueManager.dialogueItems.textBox = text.GetComponent<TextMeshProUGUI>();
dialogueManager.dialogueItems.characterName = name.GetComponent<TextMeshProUGUI>();
dialogueManager.dialogueItems.characterImage = image.GetComponent<Image>();
dialogueManager.dialogueItems.canvas = canvas;
//DialogueSystem dialogueSystem = dialogueCanvas.AddComponent<DialogueSystem>();
//dialogueSystem.nameText = name.GetComponent<TextMeshProUGUI>();
//dialogueSystem.dialogue = text.GetComponent<TMP_Animated>();
//dialogueSystem.faceImage = image.GetComponent<Image>();
//dialogueSystem.nameField = name;
}
[MenuItem("GameObject/Simple Tools/Camera Trigger/2D", false, 10)]
static void CreateCameraTrigger2D(){
GameObject cameraTrigger = new GameObject("CameraTrigger2D");
cameraTrigger.AddComponent<BoxCollider2D>();
cameraTrigger.AddComponent<CMCameraTrigger>();
GameObject vCam = new GameObject("CM vcam1");
vCam.transform.SetParent(cameraTrigger.transform);
vCam.SetActive(false);
CinemachineVirtualCamera cam = vCam.AddComponent<CinemachineVirtualCamera>();
cam.m_Lens.Orthographic = true;
}
[MenuItem("GameObject/Simple Tools/Camera Trigger/3D", false, 10)]
static void CreateCameraTrigger3D(){
GameObject cameraTrigger = new GameObject("CameraTrigger3D");
cameraTrigger.AddComponent<BoxCollider>();
cameraTrigger.AddComponent<CMCameraTrigger>();
GameObject vCam = new GameObject("CM vcam1");
vCam.transform.SetParent(cameraTrigger.transform);
vCam.SetActive(false);
CinemachineVirtualCamera cam = vCam.AddComponent<CinemachineVirtualCamera>();
cam.m_Lens.FieldOfView = 60f;
}
#if CINEMACHINE_271_OR_NEWER
[MenuItem("GameObject/Simple Tools/ScreenShake Camera/2D", false, 10)]
static void CreateScreenShakeCamera2d(){
GameObject screenShakeCamera = new GameObject("ScreenShakeCamera");
CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent<CinemachineVirtualCamera>();
vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Orthographic;
CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
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/Simple Tools/ScreenShake Camera/3D", false, 10)]
static void CreateScreenShakeCamera3d(){
GameObject screenShakeCamera = new GameObject("ScreenShakeCamera");
CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent<CinemachineVirtualCamera>();
vCam.m_Lens.ModeOverride = LensSettings.OverrideModes.Perspective;
CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
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/Simple Tools/ScreenShake Camera", false, 10)]
static void CreateScreenShakeCamera2d(){
GameObject screenShakeCamera = new GameObject("ScreenShakeCamera");
CinemachineVirtualCamera vCam = screenShakeCamera.AddComponent<CinemachineVirtualCamera>();
CinemachineBasicMultiChannelPerlin shake = vCam.AddCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
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/Simple Tools/Create Loading Scene")]
[MenuItem("Simple 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<LoaderCallback>();
GameObject canvasObj = new GameObject("Canvas");
Canvas canvas = canvasObj.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
CanvasScaler canvasScaler = canvasObj.AddComponent<CanvasScaler>();
canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
canvasScaler.referenceResolution = new Vector2Int(951, 535);
canvasScaler.matchWidthOrHeight = 1f;
canvasObj.AddComponent<GraphicRaycaster>();
TextMeshProUGUI loadingText = new GameObject("LoadingText").AddComponent<TextMeshProUGUI>();
loadingText.transform.SetParent(canvasObj.transform);
RectTransform loadingTextTransform = loadingText.GetComponent<RectTransform>();
loadingTextTransform.anchoredPosition = new Vector2Int(-333, -212);
loadingTextTransform.sizeDelta = new Vector2Int(237, 52);
loadingText.text = "LOADING...";
Image bg = new GameObject("bg").AddComponent<Image>();
bg.transform.SetParent(canvasObj.transform);
RectTransform bgTransform = bg.GetComponent<RectTransform>();
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<Image>();
progressBar.transform.SetParent(bg.transform);
RectTransform progressBarTransform = progressBar.GetComponent<RectTransform>();
progressBarTransform.anchoredPosition = Vector2.zero;
progressBarTransform.sizeDelta = new Vector2Int(900, 20);
progressBar.sprite = (Sprite)AssetDatabase.LoadAssetAtPath("Packages/com.geri.simpletools/Simple 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<LoadingProgressBar>();
}
#if UNITY_2019_3_OR_NEWER
[MenuItem("Assets/Create/Simple Tools/Create Menu Scene")]
[MenuItem("Simple 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>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
CreateEventSystem(false, null);
CanvasScaler canvasScaler = canvasObj.AddComponent<CanvasScaler>();
canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
canvasScaler.referenceResolution = new Vector2Int(951, 535);
canvasScaler.matchWidthOrHeight = 1f;
canvasObj.AddComponent<GraphicRaycaster>();
GameObject qualityDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources());
qualityDropdown.transform.SetParent(canvasObj.transform);
RectTransform qualityRectTransform = qualityDropdown.GetComponent<RectTransform>();
qualityRectTransform.anchoredPosition = Vector2.up * 15f;
qualityDropdown.name = "QualityDropdown";
GameObject resolutionDropdown = TMP_DefaultControls.CreateDropdown(GetStandardResources());
resolutionDropdown.transform.SetParent(canvasObj.transform);
RectTransform resolutionRectTransform = resolutionDropdown.GetComponent<RectTransform>();
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<RectTransform>();
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<RectTransform>();
sfxRectTransform.anchoredPosition = Vector2.down * 60;
sfxSlider.name = "MusicSlider";
GameObject playButton = TMP_DefaultControls.CreateButton(GetStandardResources());
playButton.transform.SetParent(canvasObj.transform);
TMP_Text playTextComponent = playButton.GetComponentInChildren<TMP_Text>();
playTextComponent.fontSize = 24;
playTextComponent.text = "PLAY";
RectTransform playRectTransform = playButton.GetComponent<RectTransform>();
playRectTransform.anchoredPosition = Vector2.up * 45f;
playButton.name = "PlayButton";
GameObject quitButton = TMP_DefaultControls.CreateButton(GetStandardResources());
quitButton.transform.SetParent(canvasObj.transform);
TMP_Text quitTextComponent = quitButton.GetComponentInChildren<TMP_Text>();
quitTextComponent.fontSize = 24;
quitTextComponent.text = "QUIT";
RectTransform quitRectTransform = quitButton.GetComponent<RectTransform>();
quitRectTransform.anchoredPosition = Vector2.down * 85f;
quitButton.name = "QuitButton";
MenuController menuController = canvasObj.AddComponent<MenuController>();
Slider sliderMusic = menuController.musicSlider = musicSlider.GetComponent<Slider>();
Slider sliderSfx = menuController.sfxSlider = sfxSlider.GetComponent<Slider>();
TMP_Dropdown dropdownQuality = menuController.qualityDropdown = qualityDropdown.GetComponent<TMP_Dropdown>();
TMP_Dropdown dropdownResolution = menuController.resolutionDropdown = resolutionDropdown.GetComponent<TMP_Dropdown>();
sliderMusic.onValueChanged.AddListener(menuController.SetMusicVolume);
sliderSfx.onValueChanged.AddListener(menuController.SetSfxVolume);
dropdownQuality.onValueChanged.AddListener(menuController.SetQuality);
dropdownResolution.onValueChanged.AddListener(menuController.SetResolution);
playButton.GetComponent<Button>().onClick.AddListener(menuController.Play);
quitButton.GetComponent<Button>().onClick.AddListener(menuController.Quit);
}
#region CreateUISettings
const string kUILayerName = "UI";
const string kStandardSpritePath = "UI/Skin/UISprite.psd";
const string kBackgroundSpritePath = "UI/Skin/Background.psd";
const string kInputFieldBackgroundPath = "UI/Skin/InputFieldBackground.psd";
const string kKnobPath = "UI/Skin/Knob.psd";
const string kCheckmarkPath = "UI/Skin/Checkmark.psd";
const string kDropdownArrowPath = "UI/Skin/DropdownArrow.psd";
const string kMaskPath = "UI/Skin/UIMask.psd";
static TMP_DefaultControls.Resources s_StandardResources;
static TMP_DefaultControls.Resources GetStandardResources(){
if (s_StandardResources.standard == null){
s_StandardResources.standard = AssetDatabase.GetBuiltinExtraResource<Sprite>(kStandardSpritePath);
s_StandardResources.background = AssetDatabase.GetBuiltinExtraResource<Sprite>(kBackgroundSpritePath);
s_StandardResources.inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>(kInputFieldBackgroundPath);
s_StandardResources.knob = AssetDatabase.GetBuiltinExtraResource<Sprite>(kKnobPath);
s_StandardResources.checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>(kCheckmarkPath);
s_StandardResources.dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>(kDropdownArrowPath);
s_StandardResources.mask = AssetDatabase.GetBuiltinExtraResource<Sprite>(kMaskPath);
}
return s_StandardResources;
}
static void SetPositionVisibleinSceneView(RectTransform canvasRTransform, RectTransform itemTransform){
// Find the best scene view
SceneView sceneView = SceneView.lastActiveSceneView;
if (sceneView == null && SceneView.sceneViews.Count > 0)
sceneView = SceneView.sceneViews[0] as SceneView;
// Couldn't find a SceneView. Don't set position.
if (sceneView == null || sceneView.camera == null)
return;
// Create world space Plane from canvas position.
Camera camera = sceneView.camera;
Vector3 position = Vector3.zero;
Vector2 localPlanePosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform, new Vector2(camera.pixelWidth / 2, camera.pixelHeight / 2), camera, out localPlanePosition)){
// Adjust for canvas pivot
localPlanePosition.x = localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x;
localPlanePosition.y = localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y;
localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x);
localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y);
// Adjust for anchoring
position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x;
position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y;
Vector3 minLocalPosition;
minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) + itemTransform.sizeDelta.x * itemTransform.pivot.x;
minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) + itemTransform.sizeDelta.y * itemTransform.pivot.y;
Vector3 maxLocalPosition;
maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) - itemTransform.sizeDelta.x * itemTransform.pivot.x;
maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) - itemTransform.sizeDelta.y * itemTransform.pivot.y;
position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x);
position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y);
}
itemTransform.anchoredPosition = position;
itemTransform.localRotation = Quaternion.identity;
itemTransform.localScale = Vector3.one;
}
static GameObject CreateNewUI(){
// Root for the UI
var root = new GameObject("Canvas");
root.layer = LayerMask.NameToLayer(kUILayerName);
Canvas canvas = root.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
root.AddComponent<CanvasScaler>();
root.AddComponent<GraphicRaycaster>();
// Works for all stages.
StageUtility.PlaceGameObjectInCurrentStage(root);
bool customScene = false;
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null){
root.transform.SetParent(prefabStage.prefabContentsRoot.transform, false);
customScene = true;
}
Undo.RegisterCreatedObjectUndo(root, "Create " + root.name);
// If there is no event system add one...
// No need to place event system in custom scene as these are temporary anyway.
// It can be argued for or against placing it in the user scenes,
// but let's not modify scene user is not currently looking at.
if (!customScene)
CreateEventSystem(false);
return root;
}
static void CreateEventSystem(bool select){
CreateEventSystem(select, null);
}
static void CreateEventSystem(bool select, GameObject parent){
var esys = UnityEngine.Object.FindObjectOfType<EventSystem>();
if (esys == null){
var eventSystem = new GameObject("EventSystem");
GameObjectUtility.SetParentAndAlign(eventSystem, parent);
esys = eventSystem.AddComponent<EventSystem>();
eventSystem.AddComponent<StandaloneInputModule>();
Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name);
}
if (select && esys != null){
Selection.activeGameObject = esys.gameObject;
}
}
// Helper function that returns a Canvas GameObject; preferably a parent of the selection, or other existing Canvas.
static GameObject GetOrCreateCanvasGameObject(){
GameObject selectedGo = Selection.activeGameObject;
// Try to find a gameobject that is the selected GO or one if its parents.
Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null;
if (IsValidCanvas(canvas))
return canvas.gameObject;
// No canvas in selection or its parents? Then use any valid canvas.
// We have to find all loaded Canvases, not just the ones in main scenes.
Canvas[] canvasArray = StageUtility.GetCurrentStageHandle().FindComponentsOfType<Canvas>();
for (int i = 0; i < canvasArray.Length; i++)
if (IsValidCanvas(canvasArray[i]))
return canvasArray[i].gameObject;
// No canvas in the scene at all? Then create a new one.
return CreateNewUI();
}
static bool IsValidCanvas(Canvas canvas){
if (canvas == null || !canvas.gameObject.activeInHierarchy)
return false;
// It's important that the non-editable canvas from a prefab scene won't be rejected,
// but canvases not visible in the Hierarchy at all do. Don't check for HideAndDontSave.
if (EditorUtility.IsPersistent(canvas) || (canvas.hideFlags & HideFlags.HideInHierarchy) != 0)
return false;
if (StageUtility.GetStageHandle(canvas.gameObject) != StageUtility.GetCurrentStageHandle())
return false;
return true;
}
class FactorySwapToEditor : IDisposable{
DefaultControls.IFactoryControls factory;
public FactorySwapToEditor(){
factory = DefaultControls.factory;
DefaultControls.factory = DefaultEditorFactory.Default;
}
public void Dispose(){
DefaultControls.factory = factory;
}
}
const string kStandardSpritePathDefault = "UI/Skin/UISprite.psd";
const string kBackgroundSpritePathDefault = "UI/Skin/Background.psd";
const string kInputFieldBackgroundPathDefault = "UI/Skin/InputFieldBackground.psd";
const string kKnobPathDefault = "UI/Skin/Knob.psd";
const string kCheckmarkPathDefault = "UI/Skin/Checkmark.psd";
const string kDropdownArrowPathDefault = "UI/Skin/DropdownArrow.psd";
const string kMaskPathDefault = "UI/Skin/UIMask.psd";
static DefaultControls.Resources s_StandardResourcesDefault;
static DefaultControls.Resources GetStandardUIResources(){
if (s_StandardResourcesDefault.standard == null){
s_StandardResourcesDefault.standard = AssetDatabase.GetBuiltinExtraResource<Sprite>(kStandardSpritePathDefault);
s_StandardResourcesDefault.background = AssetDatabase.GetBuiltinExtraResource<Sprite>(kBackgroundSpritePathDefault);
s_StandardResourcesDefault.inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>(kInputFieldBackgroundPathDefault);
s_StandardResourcesDefault.knob = AssetDatabase.GetBuiltinExtraResource<Sprite>(kKnobPathDefault);
s_StandardResourcesDefault.checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>(kCheckmarkPathDefault);
s_StandardResourcesDefault.dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>(kDropdownArrowPathDefault);
s_StandardResourcesDefault.mask = AssetDatabase.GetBuiltinExtraResource<Sprite>(kMaskPathDefault);
}
return s_StandardResourcesDefault;
}
static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand){
GameObject parent = menuCommand.context as GameObject;
bool explicitParentChoice = true;
if (parent == null){
parent = GetOrCreateCanvasGameObject();
explicitParentChoice = false;
// If in Prefab Mode, Canvas has to be part of Prefab contents,
// otherwise use Prefab root instead.
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null && !prefabStage.IsPartOfPrefabContents(parent))
parent = prefabStage.prefabContentsRoot;
}
if (parent.GetComponentsInParent<Canvas>(true).Length == 0){
// Create canvas under context GameObject,
// and make that be the parent which UI element is added under.
GameObject canvas = CreateNewUIDefault();
Undo.SetTransformParent(canvas.transform, parent.transform, "");
parent = canvas;
}
GameObjectUtility.EnsureUniqueNameForSibling(element);
SetParentAndAlign(element, parent);
if (!explicitParentChoice) // not a context click, so center in sceneview
SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(), element.GetComponent<RectTransform>());
// This call ensure any change made to created Objects after they where registered will be part of the Undo.
Undo.RegisterFullObjectHierarchyUndo(parent == null ? element : parent, "");
// We have to fix up the undo name since the name of the object was only known after reparenting it.
Undo.SetCurrentGroupName("Create " + element.name);
Selection.activeGameObject = element;
}
static GameObject CreateNewUIDefault(){
// Root for the UI
var root = ObjectFactory.CreateGameObject("Canvas", typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster));
root.layer = LayerMask.NameToLayer(kUILayerName);
Canvas canvas = root.GetComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
// Works for all stages.
StageUtility.PlaceGameObjectInCurrentStage(root);
bool customScene = false;
PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null){
Undo.SetTransformParent(root.transform, prefabStage.prefabContentsRoot.transform, "");
customScene = true;
}
Undo.SetCurrentGroupName("Create " + root.name);
// If there is no event system add one...
// No need to place event system in custom scene as these are temporary anyway.
// It can be argued for or against placing it in the user scenes,
// but let's not modify scene user is not currently looking at.
if (!customScene)
CreateEventSystem(false);
return root;
}
static void SetParentAndAlign(GameObject child, GameObject parent){
if (parent == null)
return;
Undo.SetTransformParent(child.transform, parent.transform, "");
RectTransform rectTransform = child.transform as RectTransform;
if (rectTransform){
rectTransform.anchoredPosition = Vector2.zero;
Vector3 localPosition = rectTransform.localPosition;
localPosition.z = 0;
rectTransform.localPosition = localPosition;
}else{
child.transform.localPosition = Vector3.zero;
}
child.transform.localRotation = Quaternion.identity;
child.transform.localScale = Vector3.one;
SetLayerRecursively(child, parent.layer);
}
static void SetLayerRecursively(GameObject go, int layer){
go.layer = layer;
Transform t = go.transform;
for (int i = 0; i < t.childCount; i++)
SetLayerRecursively(t.GetChild(i).gameObject, layer);
}
class DefaultEditorFactory : DefaultControls.IFactoryControls{
public static DefaultEditorFactory Default = new DefaultEditorFactory();
public GameObject CreateGameObject(string name, params Type[] components){
return ObjectFactory.CreateGameObject(name, components);
}
}
#endregion
#endif
}
#endif

View file

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

View file

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

View file

@ -0,0 +1,110 @@
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using UnityEngine.UI;
using TMPro;
using UnityEngine.Audio;
namespace SimpleTools.Menu {
[System.Serializable] public class OnPlay : UnityEngine.Events.UnityEvent { }
public class MenuController : MonoBehaviour {
[Header("Audio")]
[SerializeField] AudioMixer mainMixer = default;
[Tooltip("The music volume the first time you start the game")][SerializeField, Range(0, 1)] float defaultMusicValue = .75f;
[Tooltip("The SFX volume the first time you start the game")][SerializeField, Range(0, 1)] float defaultSfxValue = .75f;
public Slider musicSlider = default;
public Slider sfxSlider = default;
[Header("Visual")]
public TMP_Dropdown qualityDropdown = default;
int qualitySelected;
public TMP_Dropdown resolutionDropdown = default;
Resolution[] resolutions;
int currentResolutionIndex;
[Space]
[SerializeField] OnPlay onPlay = default;
void Awake() {
if (mainMixer) {
float musicVolume = PlayerPrefs.GetFloat("MusicVolume", defaultMusicValue);
float sfxVolume = PlayerPrefs.GetFloat("SFXVolume", defaultSfxValue);
mainMixer.SetFloat("Master", Mathf.Log10(musicVolume <= .0001f ? .0001f : musicVolume) * 20);
mainMixer.SetFloat("SFX", Mathf.Log10(sfxVolume <= .0001f ? .0001f : sfxVolume) * 20);
}
resolutions = Screen.resolutions.Select(resolution => new Resolution { width = resolution.width, height = resolution.height }).Distinct().ToArray();
resolutionDropdown.ClearOptions();
List<string> options = new List<string>();
for (int i = 0; i < resolutions.Length; i++) {
string option = resolutions[i].width + "x" + resolutions[i].height;
options.Add(option);
if (resolutions[i].width == Screen.currentResolution.width && resolutions[i].height == Screen.currentResolution.height) {
currentResolutionIndex = i;
}
}
resolutions.Reverse();
resolutionDropdown.AddOptions(options);
resolutionDropdown.value = currentResolutionIndex;
resolutionDropdown.RefreshShownValue();
qualityDropdown.ClearOptions();
List<string> qualityNames = new List<string>();
for (int i = 0; i < QualitySettings.names.Length; i++) {
qualityNames.Add(QualitySettings.names[i]);
}
qualityDropdown.AddOptions(qualityNames);
qualitySelected = PlayerPrefs.HasKey("QualitySelected") ? PlayerPrefs.GetInt("QualitySelected") : QualitySettings.GetQualityLevel();
qualityDropdown.value = qualitySelected;
QualitySettings.SetQualityLevel(qualitySelected);
qualityDropdown.RefreshShownValue();
}
void OnValidate() {
if (musicSlider) musicSlider.minValue = musicSlider.minValue < .0001f ? .0001f : musicSlider.minValue;
if (sfxSlider) sfxSlider.minValue = sfxSlider.minValue < .0001f ? .0001f : sfxSlider.minValue;
}
void Start() {
musicSlider.value = PlayerPrefs.GetFloat("MusicVolume", defaultMusicValue);
sfxSlider.value = PlayerPrefs.GetFloat("SFXVolume", defaultSfxValue);
}
//Needs a slider between 0.0001 and 1
public void SetMusicVolume(float sliderValue) {
mainMixer.SetFloat("Master", Mathf.Log10(sliderValue) * 20);
PlayerPrefs.SetFloat("MusicVolume", sliderValue);
}
//Needs a slider between 0.0001 and 1
public void SetSfxVolume(float sliderValue) {
mainMixer.SetFloat("SFX", Mathf.Log10(sliderValue) * 20);
PlayerPrefs.SetFloat("SFXVolume", sliderValue);
}
public void SetQuality(int qualityIndex) {
QualitySettings.SetQualityLevel(qualityIndex);
PlayerPrefs.SetInt("QualitySelected", qualityIndex);
}
public void SetResolution(int resolutionIndex) {
Resolution resolution = resolutions[resolutionIndex];
Screen.SetResolution(resolution.width, resolution.height, Screen.fullScreen);
}
public void Play() {
onPlay.Invoke();
}
public void Quit() {
Application.Quit();
}
}
}

View file

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

View file

@ -0,0 +1,12 @@
using UnityEngine;
namespace SimpleTools {
public static class MonobehaviourExtensions {
public static void EnsureCoroutineStopped(this MonoBehaviour value, ref Coroutine routine) {
if (routine != null) {
value.StopCoroutine(routine);
routine = null;
}
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,5 @@
namespace SimpleTools.ObjectPooler {
public interface IPooledObject {
void OnObjectSpawn();
}
}

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -0,0 +1,96 @@
fileFormatVersion: 2
guid: 8a0a572e598bbe3439aa4dab4a39293f
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:

View file

@ -0,0 +1,20 @@
using System.Collections.Generic;
using UnityEngine;
namespace SimpleTools.ObjectPooler {
[CreateAssetMenu(fileName = "New Pool", menuName = "Simple Tools/Pool", order = 11)]
public class Pool : ScriptableObject {
public List<PoolPrefab> pools;
[System.Serializable]
public class PoolPrefab {
public string tag;
public GameObject prefab;
public bool undetermined;
public int size;
[HideInInspector] public Queue<GameObject> determinedPool;
[HideInInspector] public List<GameObject> undeterminedPool;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5ff40c8bb5e75d4fabf7bd1d6a59c68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 8a0a572e598bbe3439aa4dab4a39293f, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,371 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace SimpleTools.ObjectPooler {
public static class Pooler {
class PoolChecker : MonoBehaviour {
public string poolTag;
}
static Dictionary<string, Pool.PoolPrefab> poolDictionary;
static Scene poolScene;
/// <summary>Generate a scene with the objects of the pools in it
/// <para>If this isn't called, the pooler won't work</para>
/// </summary>
public static void CreatePools(Pool pool) {
if (pool == null) {
Debug.LogWarning("You have to provide a pool.");
return;
}
poolDictionary = new Dictionary<string, Pool.PoolPrefab>();
if (SceneManager.GetSceneByName("PoolScene").IsValid()) {
poolScene = SceneManager.GetSceneByName("PoolScene");
} else {
poolScene = SceneManager.CreateScene("PoolScene");
}
foreach (Pool.PoolPrefab p in pool.pools) {
if (!p.undetermined) {
if (p.determinedPool == null) {
p.determinedPool = new Queue<GameObject>();
}
for (int i = 0; i < p.size; i++) {
GameObject obj = Object.Instantiate(p.prefab);
obj.SetActive(false);
obj.AddComponent<PoolChecker>().poolTag = p.tag;
SceneManager.MoveGameObjectToScene(obj, poolScene);
p.determinedPool.Enqueue(obj);
}
} else {
if (p.undeterminedPool == null) {
p.undeterminedPool = new List<GameObject>();
}
}
poolDictionary.Add(p.tag, p);
}
}
/// <summary>Generate a scene with the objects of the pools in it
/// <para>If this isn't called, the pooler won't work</para>
/// </summary>
public static void CreatePools(Pool[] pools) {
if (pools == null) {
Debug.LogWarning("You have to provide a pool.");
return;
}
poolDictionary = new Dictionary<string, Pool.PoolPrefab>();
if (SceneManager.GetSceneByName("PoolScene").IsValid()) {
poolScene = SceneManager.GetSceneByName("PoolScene");
} else {
poolScene = SceneManager.CreateScene("PoolScene");
}
for (int i = 0; i < pools.Length; i++) {
foreach (Pool.PoolPrefab p in pools[i].pools) {
if (!p.undetermined) {
if (p.determinedPool == null) {
p.determinedPool = new Queue<GameObject>();
}
for (int j = 0; j < p.size; j++) {
GameObject obj = Object.Instantiate(p.prefab);
obj.SetActive(false);
obj.AddComponent<PoolChecker>().poolTag = p.tag;
SceneManager.MoveGameObjectToScene(obj, poolScene);
p.determinedPool.Enqueue(obj);
}
} else {
if (p.undeterminedPool == null) {
p.undeterminedPool = new List<GameObject>();
}
}
poolDictionary.Add(p.tag, p);
}
}
}
/// <summary>Destroy an object and return it to the pool scene
/// </summary>
public static void Destroy(GameObject gameObject) {
PoolChecker poolChecker = gameObject.GetComponent<PoolChecker>();
if (poolChecker == null) {
Debug.LogWarning("GameObject: " + gameObject + " isn't from a pool", gameObject);
return;
}
gameObject.transform.SetParent(null);
SceneManager.MoveGameObjectToScene(gameObject, poolScene);
if (poolDictionary.ContainsKey(poolChecker.poolTag)) {
Pool.PoolPrefab pool = poolDictionary[poolChecker.poolTag];
if (pool.undetermined) {
gameObject.SetActive(false);
pool.undeterminedPool.Remove(gameObject);
} else {
gameObject.SetActive(false);
}
}
}
/// <summary>Spawn an object into a specific position
/// <para>The CreatePools function must have been called before.</para>
/// </summary>
public static GameObject SpawnFromPool(string tag, Vector3 position) {
if (!poolDictionary.ContainsKey(tag)) {
Debug.Log("Pool with tag " + tag + " doesn't exist.");
return null;
}
Pool.PoolPrefab pool = poolDictionary[tag];
GameObject objectToSpawn;
if (!pool.undetermined) {
objectToSpawn = pool.determinedPool.Dequeue();
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = Quaternion.identity;
objectToSpawn.SetActive(true);
pool.determinedPool.Enqueue(objectToSpawn);
} else {
if (pool.undeterminedPool.Count != 0) {
int lastIndex = pool.undeterminedPool.Count - 1;
objectToSpawn = pool.undeterminedPool[lastIndex];
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = Quaternion.identity;
objectToSpawn.SetActive(true);
} else {
objectToSpawn = Object.Instantiate(pool.prefab, position, Quaternion.identity);
SceneManager.MoveGameObjectToScene(objectToSpawn, poolScene);
objectToSpawn.AddComponent<PoolChecker>().poolTag = tag;
}
}
IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();
if (pooledObj != null) {
pooledObj.OnObjectSpawn();
}
return objectToSpawn;
}
/// <summary>Spawn an object into a specific position and parent
/// <para>The CreatePools function must have been called before.</para>
/// </summary>
public static GameObject SpawnFromPool(string tag, Vector3 position, Transform parent) {
if (!poolDictionary.ContainsKey(tag)) {
Debug.Log("Pool with tag " + tag + " doesn't exist.");
return null;
}
Pool.PoolPrefab pool = poolDictionary[tag];
GameObject objectToSpawn;
if (!pool.undetermined) {
objectToSpawn = pool.determinedPool.Dequeue();
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = Quaternion.identity;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
pool.determinedPool.Enqueue(objectToSpawn);
} else {
if (pool.undeterminedPool.Count != 0) {
int lastIndex = pool.undeterminedPool.Count - 1;
objectToSpawn = pool.undeterminedPool[lastIndex];
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = Quaternion.identity;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
} else {
objectToSpawn = Object.Instantiate(pool.prefab, position, Quaternion.identity, parent);
objectToSpawn.AddComponent<PoolChecker>().poolTag = tag;
}
}
IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();
if (pooledObj != null) {
pooledObj.OnObjectSpawn();
}
return objectToSpawn;
}
/// <summary>Spawn an object into a specific position, parent and set if it's in world space or not
/// <para>The CreatePools function must have been called before.</para>
/// </summary>
public static GameObject SpawnFromPool(string tag, Vector3 position, Transform parent, bool instantiateInWorldSpace) {
if (!poolDictionary.ContainsKey(tag)) {
Debug.Log("Pool with tag " + tag + " doesn't exist.");
return null;
}
if (!instantiateInWorldSpace) {
SpawnFromPool(tag, position, parent);
}
Pool.PoolPrefab pool = poolDictionary[tag];
GameObject objectToSpawn;
if (!pool.undetermined) {
objectToSpawn = pool.determinedPool.Dequeue();
objectToSpawn.transform.localPosition = position;
objectToSpawn.transform.localRotation = Quaternion.identity;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
pool.determinedPool.Enqueue(objectToSpawn);
} else {
if (pool.undeterminedPool.Count != 0) {
int lastIndex = pool.undeterminedPool.Count - 1;
objectToSpawn = pool.undeterminedPool[lastIndex];
objectToSpawn.transform.localPosition = position;
objectToSpawn.transform.localRotation = Quaternion.identity;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
} else {
objectToSpawn = Object.Instantiate(pool.prefab);
objectToSpawn.transform.localPosition = position;
objectToSpawn.transform.localRotation = Quaternion.identity;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.AddComponent<PoolChecker>().poolTag = tag;
}
}
IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();
if (pooledObj != null) {
pooledObj.OnObjectSpawn();
}
return objectToSpawn;
}
/// <summary>Spawn an object into a specific position and rotation
/// <para>The CreatePools function must have been called before.</para>
/// </summary>
public static GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation) {
if (!poolDictionary.ContainsKey(tag)) {
Debug.Log("Pool with tag " + tag + " doesn't exist.");
return null;
}
Pool.PoolPrefab pool = poolDictionary[tag];
GameObject objectToSpawn;
if (!pool.undetermined) {
objectToSpawn = pool.determinedPool.Dequeue();
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
objectToSpawn.SetActive(true);
pool.determinedPool.Enqueue(objectToSpawn);
} else {
if (pool.undeterminedPool.Count != 0) {
int lastIndex = pool.undeterminedPool.Count - 1;
objectToSpawn = pool.undeterminedPool[lastIndex];
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
objectToSpawn.SetActive(true);
} else {
objectToSpawn = Object.Instantiate(pool.prefab, position, rotation);
SceneManager.MoveGameObjectToScene(objectToSpawn, poolScene);
objectToSpawn.AddComponent<PoolChecker>().poolTag = tag;
}
}
IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();
if (pooledObj != null) {
pooledObj.OnObjectSpawn();
}
return objectToSpawn;
}
/// <summary>Spawn an object into a specific position, rotation and parent
/// <para>The CreatePools function must have been called before.</para>
/// </summary>
public static GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation, Transform parent) {
if (!poolDictionary.ContainsKey(tag)) {
Debug.Log("Pool with tag " + tag + " doesn't exist.");
return null;
}
Pool.PoolPrefab pool = poolDictionary[tag];
GameObject objectToSpawn;
if (!pool.undetermined) {
objectToSpawn = pool.determinedPool.Dequeue();
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
pool.determinedPool.Enqueue(objectToSpawn);
} else {
if (pool.undeterminedPool.Count != 0) {
int lastIndex = pool.undeterminedPool.Count - 1;
objectToSpawn = pool.undeterminedPool[lastIndex];
objectToSpawn.transform.position = position;
objectToSpawn.transform.rotation = rotation;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
} else {
objectToSpawn = Object.Instantiate(pool.prefab, position, rotation, parent);
objectToSpawn.AddComponent<PoolChecker>().poolTag = tag;
}
}
IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();
if (pooledObj != null) {
pooledObj.OnObjectSpawn();
}
return objectToSpawn;
}
/// <summary>Spawn an object into a specific position, rotation, parent and set if it's in world space or not
/// <para>The CreatePools function must have been called before.</para>
/// </summary>
public static GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation, Transform parent, bool instantiateInWorldSpace) {
if (!poolDictionary.ContainsKey(tag)) {
Debug.Log("Pool with tag " + tag + " doesn't exist.");
return null;
}
if (!instantiateInWorldSpace) {
SpawnFromPool(tag, position, rotation, parent);
}
Pool.PoolPrefab pool = poolDictionary[tag];
GameObject objectToSpawn;
if (!pool.undetermined) {
objectToSpawn = pool.determinedPool.Dequeue();
objectToSpawn.transform.localPosition = position;
objectToSpawn.transform.localRotation = rotation;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
pool.determinedPool.Enqueue(objectToSpawn);
} else {
if (pool.undeterminedPool.Count != 0) {
int lastIndex = pool.undeterminedPool.Count - 1;
objectToSpawn = pool.undeterminedPool[lastIndex];
objectToSpawn.transform.localPosition = position;
objectToSpawn.transform.localRotation = rotation;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.SetActive(true);
} else {
objectToSpawn = Object.Instantiate(pool.prefab);
objectToSpawn.transform.localPosition = position;
objectToSpawn.transform.localRotation = rotation;
objectToSpawn.transform.SetParent(parent);
objectToSpawn.AddComponent<PoolChecker>().poolTag = tag;
}
}
IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();
if (pooledObj != null) {
pooledObj.OnObjectSpawn();
}
return objectToSpawn;
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,71 @@
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace SimpleTools.SceneManagement {
public static class Loader {
class LoadingMonoBehaviour : MonoBehaviour { }
static Action onLoaderCallback;
static AsyncOperation loadingAsyncOperation;
/// <summary>Load a scene with a loading scene
/// <para>It requires a scene called "Loading" where the loading screen is located.</para>
/// </summary>
public static void Load(int scene) {
onLoaderCallback = () => {
GameObject loadingGameObject = new GameObject("LoadingGameObject");
loadingGameObject.AddComponent<LoadingMonoBehaviour>().StartCoroutine(LoadSceneAsync(scene));
};
SceneManager.LoadScene("Loading");
}
/// <summary>Load a scene with a loading scene
/// <para>It requires a scene called "Loading" where the loading screen is located.</para>
/// </summary>
public static void Load(string scene) {
onLoaderCallback = () => {
GameObject loadingGameObject = new GameObject("LoadingGameObject");
loadingGameObject.AddComponent<LoadingMonoBehaviour>().StartCoroutine(LoadSceneAsync(scene));
};
SceneManager.LoadScene("Loading");
}
static IEnumerator LoadSceneAsync(int scene) {
yield return null;
loadingAsyncOperation = SceneManager.LoadSceneAsync(scene);
while (!loadingAsyncOperation.isDone) {
yield return null;
}
}
static IEnumerator LoadSceneAsync(string scene) {
yield return null;
loadingAsyncOperation = SceneManager.LoadSceneAsync(scene);
while (!loadingAsyncOperation.isDone) {
yield return null;
}
}
/// <summary>Returns the loading progress
/// </summary>
public static float GetLoadingProgress() {
if (loadingAsyncOperation != null) {
return loadingAsyncOperation.progress;
} else {
return 0f;
}
}
public static void LoaderCallback() {
if (onLoaderCallback != null) {
onLoaderCallback();
onLoaderCallback = null;
}
}
}
}

View file

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

View file

@ -0,0 +1,16 @@
using UnityEngine;
namespace SimpleTools.SceneManagement {
public class LoaderCallback : MonoBehaviour {
bool isFirstUpdate = true;
// Update is called once per frame
void Update() {
if (isFirstUpdate) {
isFirstUpdate = false;
Loader.LoaderCallback();
}
}
}
}

View file

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

View file

@ -0,0 +1,19 @@
using UnityEngine;
using UnityEngine.UI;
namespace SimpleTools.SceneManagement {
public class LoadingProgressBar : MonoBehaviour {
Image image;
// Start is called before the first frame update
void Awake() {
image = transform.GetComponent<Image>();
}
// Update is called once per frame
void Update() {
image.fillAmount = Loader.GetLoadingProgress();
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,99 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using TMPro;
namespace SimpleTools.Timer{
public class Timer : MonoBehaviour{
float elapsedTime;
public float ElapsedTime { get { return elapsedTime; } }
bool isPaused;
public bool IsPaused { get { return isPaused; } }
TimeSpan timePlaying;
public TimeSpan TimePlaying { get { return timePlaying; } }
TMP_Text timer;
public TMP_Text TimerText { get { return timer; } }
TimerType timerType;
public TimerType TimerType { get { return timerType; } }
TimerUpdate timerUpdate;
public TimerUpdate TimerUpdate { get { return timerUpdate; } }
float defaultTime;
/// <summary>
/// Setup the timer
/// </summary>
public void Setup(float elapsedTime, bool isPaused, TimeSpan timePlaying, TMP_Text timer, TimerType timerType, TimerUpdate timerUpdate, string text){
this.elapsedTime = defaultTime = elapsedTime;
this.isPaused = isPaused;
this.timePlaying = timePlaying;
this.timer = timer;
this.timerType = timerType;
this.timerUpdate = timerUpdate;
timer.text = text;
}
IEnumerator UpdateTimer(){
while (!isPaused){
if(timerType == TimerType.Clock){
timer.text = DateTime.Now.ToString("HH:mm:ss");
}else{
switch (timerType){
case TimerType.Countdown:
elapsedTime -= timerUpdate == TimerUpdate.UnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
if(elapsedTime < 0f){
elapsedTime = 0f;
isPaused = true;
}
break;
case TimerType.Stopwatch:
elapsedTime += timerUpdate == TimerUpdate.UnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
break;
}
timePlaying = TimeSpan.FromSeconds(elapsedTime);
timer.text = timePlaying.ToString("m':'ss'.'ff");
}
yield return null;
}
}
/// <summary>
/// Play or resume the timer
/// </summary>
public void Play(){
isPaused = false;
StartCoroutine(UpdateTimer());
}
/// <summary>
/// Pause the timer
/// </summary>
public void Stop(){
isPaused = true;
}
/// <summary>
/// Pause and sets the time to the defaultOne
/// </summary>
public void ResetTimer(){
isPaused = true;
elapsedTime = defaultTime;
timePlaying = TimeSpan.FromSeconds(elapsedTime);
timer.text = timePlaying.ToString("m':'ss'.'ff");
}
/// <summary>
/// Restarts the timer
/// </summary>
public void Restart(){
isPaused = false;
elapsedTime = defaultTime;
timePlaying = TimeSpan.FromSeconds(elapsedTime);
timer.text = timePlaying.ToString("m':'ss'.'ff");
StopAllCoroutines();
StartCoroutine(UpdateTimer());
}
}
}

View file

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

View file

@ -0,0 +1,7 @@
namespace SimpleTools.Timer{
public enum TimerType{
Countdown,
Stopwatch,
Clock
}
}

View file

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

View file

@ -0,0 +1,6 @@
namespace SimpleTools.Timer{
public enum TimerUpdate{
ScaledTime,
UnscaledTime,
}
}

View file

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

View file

@ -0,0 +1,36 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using TMPro;
namespace SimpleTools.Timer{
public static class TimerUtility {
/// <summary>
/// Setup the timer
/// </summary>
/// <param name="container">TMPro object that will contain the timer</param>
/// <param name="timerType">What type of timer will it be (Countdown, Stopwatch, Clock)</param>
/// <param name="countdownTime">The time that will have in case it is a countdown timer</param>
/// <returns></returns>
public static Timer SetupTimer(this TMP_Text container, TimerType timerType, TimerUpdate timerUpdate, float countdownTime = 60f){
Timer t = container.gameObject.AddComponent<Timer>();
float elapsedTime = 0f;
string text = string.Empty;
TimeSpan timePlaying = TimeSpan.Zero;
switch (timerType){
case TimerType.Countdown:
elapsedTime = countdownTime;
timePlaying = TimeSpan.FromSeconds(elapsedTime);
text = timePlaying.ToString("m':'ss'.'ff");
break;
case TimerType.Clock:
text = DateTime.Now.ToString("HH:mm:ss");
break;
}
t.Setup(elapsedTime, true, timePlaying, container, timerType, timerUpdate, text);
return t;
}
}
}

View file

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

View file

@ -0,0 +1,24 @@
{
"name": "SimpleTools",
"rootNamespace": "",
"references": [
"Cinemachine",
"TMP_Runtime-CSharp",
"Unity.TextMeshPro"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.cinemachine",
"expression": "2.7.1",
"define": "CINEMACHINE_271_OR_NEWER"
}
],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ee6e31376ad94a04aa42bdea5f22b2ab
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

23
SimpleTools/package.json Normal file
View file

@ -0,0 +1,23 @@
{
"name": "com.geri.simpletools",
"version": "1.2.2",
"displayName": "Simple Tools",
"description": "This package contains simple tools to use in your project.",
"unity": "2018.4",
"unityRelease": "30f1",
"dependencies": {
"com.unity.cinemachine": "2.2.0",
"com.unity.textmeshpro": "1.4.1"
},
"keywords": [
"gamejam",
"simple",
"easy"
],
"author": {
"name": "Geri",
"email": "ggasconmoline@gmail.com",
"url": "https://geri8.itch.io/"
},
"type": "commonjs"
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d9e8f428943ed2045a746644f61eb664
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

40
manifest.json Normal file
View file

@ -0,0 +1,40 @@
{
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.cinemachine": "2.8.6",
"com.unity.ide.visualstudio": "2.0.16",
"com.unity.textmeshpro": "3.0.6",
"com.unity.ugui": "1.0.0",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.cloth": "1.0.0",
"com.unity.modules.director": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.physics2d": "1.0.0",
"com.unity.modules.screencapture": "1.0.0",
"com.unity.modules.terrain": "1.0.0",
"com.unity.modules.terrainphysics": "1.0.0",
"com.unity.modules.tilemap": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.uielements": "1.0.0",
"com.unity.modules.umbra": "1.0.0",
"com.unity.modules.unityanalytics": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.unitywebrequesttexture": "1.0.0",
"com.unity.modules.unitywebrequestwww": "1.0.0",
"com.unity.modules.vehicles": "1.0.0",
"com.unity.modules.video": "1.0.0",
"com.unity.modules.vr": "1.0.0",
"com.unity.modules.wind": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
}

325
packages-lock.json Normal file
View file

@ -0,0 +1,325 @@
{
"dependencies": {
"com.geri.simpletools": {
"version": "file:SimpleTools",
"depth": 0,
"source": "embedded",
"dependencies": {
"com.unity.cinemachine": "2.2.0",
"com.unity.textmeshpro": "1.4.1"
}
},
"com.unity.2d.sprite": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.cinemachine": {
"version": "2.8.6",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ext.nunit": {
"version": "1.0.6",
"depth": 2,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ide.visualstudio": {
"version": "2.0.16",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.test-framework": "1.1.9"
},
"url": "https://packages.unity.com"
},
"com.unity.test-framework": {
"version": "1.1.33",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.ext.nunit": "1.0.6",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.textmeshpro": {
"version": "3.0.6",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ugui": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.ugui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0"
}
},
"com.unity.modules.ai": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.androidjni": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.animation": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.assetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.audio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.cloth": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.director": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.animation": "1.0.0"
}
},
"com.unity.modules.imageconversion": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.imgui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.jsonserialize": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.particlesystem": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics2d": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.screencapture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.subsystems": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.terrain": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.terrainphysics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.terrain": "1.0.0"
}
},
"com.unity.modules.tilemap": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics2d": "1.0.0"
}
},
"com.unity.modules.ui": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.uielements": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.uielementsnative": "1.0.0"
}
},
"com.unity.modules.uielementsnative": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.umbra": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unityanalytics": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0"
}
},
"com.unity.modules.unitywebrequest": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.unitywebrequestassetbundle": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.unitywebrequestaudio": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.audio": "1.0.0"
}
},
"com.unity.modules.unitywebrequesttexture": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.unitywebrequestwww": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.unitywebrequest": "1.0.0",
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
"com.unity.modules.unitywebrequestaudio": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.assetbundle": "1.0.0",
"com.unity.modules.imageconversion": "1.0.0"
}
},
"com.unity.modules.vehicles": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0"
}
},
"com.unity.modules.video": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.unitywebrequest": "1.0.0"
}
},
"com.unity.modules.vr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.xr": "1.0.0"
}
},
"com.unity.modules.wind": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.xr": {
"version": "1.0.0",
"depth": 0,
"source": "builtin",
"dependencies": {
"com.unity.modules.physics": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.subsystems": "1.0.0"
}
}
}
}