Reworked the dialogue system

Now the dialogue can use tags to add special effects
Reorganized project structure, updating may require adding some using statements
This commit is contained in:
Gerard Gascón 2022-09-15 17:27:28 +02:00 committed by GitHub
parent 95bad523b9
commit 0e8b8b1835
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 1912 additions and 1266 deletions

View file

@ -12,7 +12,6 @@ This package will be updated once I find another useful tool or someone suggest
- Basic menu with **music and SFX sliders** as well as **resolution and quality dropdowns.** - 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. - An **object pooler** with the ability to create pools with an undetermined size.
- A basic **scene manager** with a loading screen with progress bar. - A basic **scene manager** with a loading screen with progress bar.
- A **timer** that is displayed inside a TextMeshPro object.
All of that comes with some editor menu items for creating all of that as fast as possible. All of that comes with some editor menu items for creating all of that as fast as possible.
@ -37,6 +36,8 @@ Download latest package from the Release section Import SimpleTools.unitypackage
### AudioManager ### AudioManager
```csharp ```csharp
using SimpleTools.AudioManager;
AudioManager.instance.Play("Name"); //Plays the sound with that name 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.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.PlayOneShot("Name"); //Plays one shot of that sound (Useful for repeated sounds)
@ -63,6 +64,8 @@ AudioManager.instance.FadeMutedOut("Name", 1f); //Fade Out a sound without stopp
The SpawnFromPool function always return a GameObject The SpawnFromPool function always return a GameObject
```csharp ```csharp
using SimpleTools.ObjectPooler;
Pool pool; //The pool scriptable object goes here Pool pool; //The pool scriptable object goes here
Pooler.CreatePools(pool); //Create the pool, without creating it you cannot spawn it Pooler.CreatePools(pool); //Create the pool, without creating it you cannot spawn it
Pool[] pools; Pool[] pools;
@ -82,13 +85,28 @@ Pooler.SpawnFromPool("Name", Vector3.zero, Quaternion.identity, transform, true)
The Dialogue function returns a bool (true if it's talking, false if it has ended) The Dialogue function returns a bool (true if it's talking, false if it has ended)
```csharp ```csharp
using SimpleTools.DialogueSystem;
Dialogue dialogue; //The dialogue scriptable object goes here Dialogue dialogue; //The dialogue scriptable object goes here
DialogueSystem.instance.Dialogue(dialogue); //Start/Continue the dialogue 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:
| <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 ### SceneManager
```csharp ```csharp
using SimpleTools.SceneManagement;
Loader.Load(0); //Loads a scene with a specific build index Loader.Load(0); //Loads a scene with a specific build index
Loader.Load("Scene"); //Loads a scene with a specific name Loader.Load("Scene"); //Loads a scene with a specific name
``` ```
@ -96,6 +114,8 @@ Loader.Load("Scene"); //Loads a scene with a specific name
### ScreenShake ### ScreenShake
```csharp ```csharp
using SimpleTools.Cinemachine;
ScreenShake.Shake(1f, .25f); //Shakes the camera with an intensity and duration ScreenShake.Shake(1f, .25f); //Shakes the camera with an intensity and duration
``` ```

View file

@ -2,6 +2,7 @@
using UnityEngine; using UnityEngine;
using System; using System;
namespace SimpleTools.AudioManager {
public class AudioManager : MonoBehaviour { public class AudioManager : MonoBehaviour {
public static AudioManager instance; public static AudioManager instance;
@ -98,6 +99,13 @@ public class AudioManager : MonoBehaviour{
float introDuration = s.clip.length; float introDuration = s.clip.length;
Play(song, introDuration); 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 #endregion
#region Pause #region Pause
/// <summary>Use this to pause a sound with a specific name /// <summary>Use this to pause a sound with a specific name
@ -260,3 +268,4 @@ public class AudioManager : MonoBehaviour{
} }
#endregion #endregion
} }
}

View file

@ -1,6 +1,7 @@
using UnityEngine; using UnityEngine;
using UnityEngine.Audio; using UnityEngine.Audio;
namespace SimpleTools.AudioManager {
[CreateAssetMenu(fileName = "Sounds", menuName = "Simple Tools/Sounds", order = 11)] [CreateAssetMenu(fileName = "Sounds", menuName = "Simple Tools/Sounds", order = 11)]
public class Sounds : ScriptableObject { public class Sounds : ScriptableObject {
@ -11,7 +12,8 @@ public class Sounds : ScriptableObject{
public List[] sounds; public List[] sounds;
[System.Serializable] public class List{ [System.Serializable]
public class List {
[Tooltip("Name of the sound. Each name has to be different between each other.")] [Tooltip("Name of the sound. Each name has to be different between each other.")]
public string name; public string name;
@ -48,3 +50,4 @@ public class Sounds : ScriptableObject{
} }
} }
} }
}

View file

@ -1,6 +1,7 @@
using UnityEngine; using UnityEngine;
using Cinemachine; using Cinemachine;
namespace SimpleTools.Cinemachine {
public class CMCameraTrigger : MonoBehaviour { public class CMCameraTrigger : MonoBehaviour {
CinemachineVirtualCamera vcam; CinemachineVirtualCamera vcam;
@ -36,3 +37,4 @@ public class CMCameraTrigger : MonoBehaviour{
} }
#endregion #endregion
} }
}

View file

@ -1,6 +1,7 @@
using Cinemachine; using Cinemachine;
using UnityEngine; using UnityEngine;
namespace SimpleTools.Cinemachine {
public static class ScreenShake { public static class ScreenShake {
static CinemachineVirtualCamera vCam; static CinemachineVirtualCamera vCam;
@ -34,3 +35,4 @@ public static class ScreenShake{
shakeUpdate.shakeTimer = shakeUpdate.shakeTimerTotal = time; shakeUpdate.shakeTimer = shakeUpdate.shakeTimerTotal = time;
} }
} }
}

View file

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

View file

@ -0,0 +1,112 @@
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, "");
}
public bool Dialogue(Dialogue dialogue, params string[] sounds) {
if (sounds != null)
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,152 @@
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 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 = 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 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
}
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,262 @@
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;
}
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 != null)
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

@ -11,6 +11,11 @@ using UnityEditor.SceneManagement;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
using UnityEditor.Experimental.SceneManagement; using UnityEditor.Experimental.SceneManagement;
using System; using System;
using SimpleTools.AudioManager;
using SimpleTools.DialogueSystem;
using SimpleTools.Cinemachine;
using SimpleTools.SceneManagement;
using SimpleTools.Menu;
public class ToolsEditor{ public class ToolsEditor{
@ -29,9 +34,9 @@ public class ToolsEditor{
dialogueCanvas.AddComponent<CanvasScaler>(); dialogueCanvas.AddComponent<CanvasScaler>();
dialogueCanvas.AddComponent<GraphicRaycaster>(); dialogueCanvas.AddComponent<GraphicRaycaster>();
GameObject text = new GameObject("TMP_Animated"); GameObject text = new GameObject("DialogueText");
text.transform.SetParent(dialogueCanvas.transform); text.transform.SetParent(dialogueCanvas.transform);
text.AddComponent<TMP_Animated>().text = "New Text"; text.AddComponent<TextMeshProUGUI>().text = "Dialogue";
text.GetComponent<RectTransform>().anchoredPosition = Vector2.zero; text.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
GameObject name = new GameObject("NameText"); GameObject name = new GameObject("NameText");
@ -44,11 +49,17 @@ public class ToolsEditor{
image.AddComponent<Image>(); image.AddComponent<Image>();
image.GetComponent<RectTransform>().anchoredPosition = new Vector2(-150f, 25f); image.GetComponent<RectTransform>().anchoredPosition = new Vector2(-150f, 25f);
DialogueSystem dialogueSystem = dialogueCanvas.AddComponent<DialogueSystem>(); DialogueManager dialogueManager = dialogueCanvas.AddComponent<DialogueManager>();
dialogueSystem.nameText = name.GetComponent<TextMeshProUGUI>(); Debug.Log(dialogueManager.dialogueItems);
dialogueSystem.dialogue = text.GetComponent<TMP_Animated>(); dialogueManager.dialogueItems.textBox = text.GetComponent<TextMeshProUGUI>();
dialogueSystem.faceImage = image.GetComponent<Image>(); dialogueManager.dialogueItems.characterName = name.GetComponent<TextMeshProUGUI>();
dialogueSystem.nameField = name; 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)] [MenuItem("GameObject/Simple Tools/Camera Trigger/2D", false, 10)]

View file

@ -5,6 +5,7 @@ using UnityEngine.UI;
using TMPro; using TMPro;
using UnityEngine.Audio; using UnityEngine.Audio;
namespace SimpleTools.Menu {
[System.Serializable] public class OnPlay : UnityEngine.Events.UnityEvent { } [System.Serializable] public class OnPlay : UnityEngine.Events.UnityEvent { }
public class MenuController : MonoBehaviour { public class MenuController : MonoBehaviour {
@ -42,8 +43,7 @@ public class MenuController : MonoBehaviour{
string option = resolutions[i].width + "x" + resolutions[i].height; string option = resolutions[i].width + "x" + resolutions[i].height;
options.Add(option); options.Add(option);
if (resolutions[i].width == Screen.currentResolution.width && resolutions[i].height == Screen.currentResolution.height) if (resolutions[i].width == Screen.currentResolution.width && resolutions[i].height == Screen.currentResolution.height) {
{
currentResolutionIndex = i; currentResolutionIndex = i;
} }
} }
@ -107,3 +107,4 @@ public class MenuController : MonoBehaviour{
Application.Quit(); Application.Quit();
} }
} }
}

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

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

View file

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
namespace SimpleTools.ObjectPooler {
[CreateAssetMenu(fileName = "New Pool", menuName = "Simple Tools/Pool", order = 11)] [CreateAssetMenu(fileName = "New Pool", menuName = "Simple Tools/Pool", order = 11)]
public class Pool : ScriptableObject { public class Pool : ScriptableObject {
@ -16,3 +17,4 @@ public class Pool : ScriptableObject{
[HideInInspector] public List<GameObject> undeterminedPool; [HideInInspector] public List<GameObject> undeterminedPool;
} }
} }
}

View file

@ -2,6 +2,7 @@
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
namespace SimpleTools.ObjectPooler {
public static class Pooler { public static class Pooler {
class PoolChecker : MonoBehaviour { class PoolChecker : MonoBehaviour {
@ -367,3 +368,4 @@ public static class Pooler{
return objectToSpawn; return objectToSpawn;
} }
} }
}

View file

@ -3,6 +3,7 @@ using System.Collections;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
namespace SimpleTools.SceneManagement {
public static class Loader { public static class Loader {
class LoadingMonoBehaviour : MonoBehaviour { } class LoadingMonoBehaviour : MonoBehaviour { }
@ -67,3 +68,4 @@ public static class Loader{
} }
} }
} }
}

View file

@ -1,5 +1,6 @@
using UnityEngine; using UnityEngine;
namespace SimpleTools.SceneManagement {
public class LoaderCallback : MonoBehaviour { public class LoaderCallback : MonoBehaviour {
bool isFirstUpdate = true; bool isFirstUpdate = true;
@ -12,3 +13,4 @@ public class LoaderCallback : MonoBehaviour{
} }
} }
} }
}

View file

@ -1,6 +1,7 @@
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
namespace SimpleTools.SceneManagement {
public class LoadingProgressBar : MonoBehaviour { public class LoadingProgressBar : MonoBehaviour {
Image image; Image image;
@ -15,3 +16,4 @@ public class LoadingProgressBar : MonoBehaviour{
image.fillAmount = Loader.GetLoadingProgress(); image.fillAmount = Loader.GetLoadingProgress();
} }
} }
}

View file

@ -75,7 +75,7 @@ namespace SimpleTools.Timer{
} }
/// <summary> /// <summary>
/// Pause and sets the time to the default one /// Pause and sets the time to the defaultOne
/// </summary> /// </summary>
public void ResetTimer(){ public void ResetTimer(){
isPaused = true; isPaused = true;

View file

@ -1,6 +1,6 @@
{ {
"name": "com.geri.simpletools", "name": "com.geri.simpletools",
"version": "1.1.2", "version": "1.2.0",
"displayName": "Simple Tools", "displayName": "Simple Tools",
"description": "This package contains simple tools to use in your project.", "description": "This package contains simple tools to use in your project.",
"unity": "2018.4", "unity": "2018.4",