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:
parent
95bad523b9
commit
0e8b8b1835
25 changed files with 1912 additions and 1266 deletions
|
@ -1,12 +1,16 @@
|
|||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu(fileName = "New Character", menuName = "Simple Tools/Character", order = 11)]
|
||||
public class Dialogue : ScriptableObject{
|
||||
namespace SimpleTools.DialogueSystem {
|
||||
[CreateAssetMenu(fileName = "New Dialogue", menuName = "Simple Tools/Dialogue", order = 11)]
|
||||
public class Dialogue : ScriptableObject {
|
||||
public DialogueBox[] sentences;
|
||||
}
|
||||
|
||||
public bool displayName;
|
||||
public string characterName;
|
||||
|
||||
[Space]
|
||||
public Sprite characterImage;
|
||||
[TextArea] public string[] sentences;
|
||||
}
|
||||
[System.Serializable]
|
||||
public class DialogueBox {
|
||||
public bool displayName;
|
||||
public string characterName;
|
||||
public Sprite characterImage;
|
||||
[TextArea(5, 10)] public string sentence;
|
||||
}
|
||||
}
|
112
Tools/DialogueSystem/DialogueManager.cs
Normal file
112
Tools/DialogueSystem/DialogueManager.cs
Normal 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;
|
||||
}
|
||||
}
|
11
Tools/DialogueSystem/DialogueManager.cs.meta
Normal file
11
Tools/DialogueSystem/DialogueManager.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23d6a059fd2bc464a9cba3a5ced1724d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
152
Tools/DialogueSystem/DialogueUtility.cs
Normal file
152
Tools/DialogueSystem/DialogueUtility.cs
Normal 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,
|
||||
}
|
||||
}
|
11
Tools/DialogueSystem/DialogueUtility.cs.meta
Normal file
11
Tools/DialogueSystem/DialogueUtility.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d4649243ed65dff45b7891eed22eb4c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
262
Tools/DialogueSystem/DialogueVertexAnimator.cs
Normal file
262
Tools/DialogueSystem/DialogueVertexAnimator.cs
Normal 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;
|
||||
}
|
||||
}
|
11
Tools/DialogueSystem/DialogueVertexAnimator.cs.meta
Normal file
11
Tools/DialogueSystem/DialogueVertexAnimator.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dcef7fafd8716284392e9621424bfa6a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Add table
Add a link
Reference in a new issue