Script isn't working. Easy solutions to adding dialogue? Help ASAP - project due in a few days
Hello,
I'm new to both Unity and C# and I need some help understanding why my script isn't working. I want a setup sort of like Fire Emblem where there's a display picture of the character right next to the dialogue, but I'm having trouble with that part.
I followed this tutorial to start:
(Part 1): https://www.youtube.com/watch?v=LgQrIC-8WmA&spfreload=1
(Part 2): https://www.youtube.com/watch?v=xcgqSxPgrBA\
I followed the tutorial down to the exact code, and just added comments to what everything meant. Then I went back and tried to add the display pictures (which are going to be GameObjects - UI images which I declared in the beginning) when each person was speaking by using the contains method. But it doesn't work and I'm not sure why. Help, anyone? I know this is a big question and a big script >.< Thank you to anyone who takes the time to try to help me out.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
// referencing going to be using UI elements
using System.Linq;
//going to be using Contains
[RequireComponent(typeof(Text))]
//requiring text is needed to use this script to prevent errors
public class Dialogue2 : MonoBehaviour
{
private Text _textComponent;
//declaring text variable
public string[] DialogueStrings;
//public - to edit through unity inspector - [] = you put number of strings in inspectors
**public GameObject Naoto;
public GameObject Lucia;
public GameObject Aria;
public GameObject Armin;
//for display pictures**
**private string NaotoString = "Naoto:";
private string LuciaString = "Lucia:";
private string AriaString = "Aria:";
private string ArminString = "Armin:";
//for checking to see if the characters name is in the string (colon at end prevents misconceptions if characters name is just used in the dialogue)**
public float SecondsBetweenCharacters = 0.08f;
//seconds inbetween time characters in text are displayed onto dialogue box
public float CharacterRateMultiplier = 0.2f;
//for speeding it up when return is held down
public KeyCode DialogueInput = KeyCode.Return;
//declaring key to be used return key
private bool _isStringBeingRevealed = false;
//make sure couroutine isnt being called multiple times
private bool _isDialoguePlaying = false;
private bool _isEndOfDialogue = false;
//to check to see if last string of dialogue has been played
public GameObject ContinueIcon;
public GameObject StopIcon;
//giving icons to stop / continue dialogue
// Use this for initialization
void Start ()
{
_textComponent = GetComponent<Text>();
_textComponent.text = "";
//getting text component and making sure its blank on start
HideIcons();
//hiding icons on start
HideAria();
HideLucia();
HideArmin();
HideNaoto();
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown(KeyCode.Return))
{
if (!_isDialoguePlaying)
{
_isDialoguePlaying = true;
StartCoroutine(StartDialogue());
}
}
}
private IEnumerator StartDialogue()
//this is a couroutine - function like a loop but can return into the middle of the loop
//The IEnumerator - Supports a simple iteration over a non-generic collection.
{
int dialogueLength = DialogueStrings.Length;
int currentDialogueIndex = 0;
while (currentDialogueIndex < dialogueLength || !_isStringBeingRevealed)
{
if (!_isStringBeingRevealed)
//if string isnt being revealed -> start couroutine
{
_isStringBeingRevealed = true;
StartCoroutine(DisplayString(DialogueStrings[currentDialogueIndex++]));
**//trying to show / hide character's display pictures
if (DialogueStrings.Contains(LuciaString))
{
HideAria();
HideArmin();
HideNaoto();
ShowLucia();
}
if (DialogueStrings.Contains(AriaString))
{
HideLucia();
HideArmin();
HideNaoto();
ShowAria();
}
if (DialogueStrings.Contains(ArminString))
{
HideLucia();
HideAria();
HideNaoto();
ShowArmin();
}
if (DialogueStrings.Contains(NaotoString))
{
HideLucia();
HideArmin();
HideAria();
ShowNaoto();
}**
if (currentDialogueIndex >= dialogueLength)
{
_isEndOfDialogue = true;
}
//saying that its the end of the dialogue
}
yield return 0;
}
while (true)
{
if (Input.GetKeyDown(DialogueInput))
{
break;
}
yield return 0;
}
HideIcons();
//when return is pressed and next string starts the icons are hidden
HideLucia();
HideAria();
HideArmin();
HideNaoto();
_isEndOfDialogue = false;
_isDialoguePlaying = false;
//resetting for next re-run basically
}
private IEnumerator DisplayString(string stringToDisplay)
{
int stringLength = stringToDisplay.Length;
//gets length of the string to be displayed
int currentCharacterIndex = 0;
//start at 0 at start of script
HideIcons();
//hiding icons at start
HideAria();
HideLucia();
HideArmin();
HideNaoto();
_textComponent.text = "";
//clearing text everytime its called so can display new text
while (currentCharacterIndex < stringLength)
{
_textComponent.text += stringToDisplay[currentCharacterIndex];
//get each character to stringToDisplay from textComponent using +=
//+= is someVar = someVar + otherVar
currentCharacterIndex++;
//adding 1 to the currentCharacterIndex so each character is revealed
if (currentCharacterIndex < stringLength)
{
if (Input.GetKey(DialogueInput))
{
yield return new WaitForSeconds(SecondsBetweenCharacters*CharacterRateMultiplier);
//if return key is being held down - text will be sped up
}
else
{
yield return new WaitForSeconds(SecondsBetweenCharacters);
}
}
else
{
break;
}
}
ShowIcon();
//showing continue icon after dialogue string has been revealed
while (true)
{
if (Input.GetKeyDown(DialogueInput))
{
break;
}
yield return 0;
}
//Will pause dialogue when string is revealed and let you view the next string when return is pressed
HideIcons();
_isStringBeingRevealed = false;
//will stop revealing string until couroutine repeats
_textComponent.text = "";
//clearing text again once while loop finished so couroutine is clear when it loops again
}
private void HideIcons()
//hides continue and stop icons
{
ContinueIcon.SetActive(false);
StopIcon.SetActive(false);
}
private void ShowIcon()
//shows continue icon if the dialogue is finished displaying
{
if (_isEndOfDialogue)
{
StopIcon.SetActive(true);
return;
}
ContinueIcon.SetActive(true);
}
**//making functions to show / hide character pictures
private void HideLucia()
{
Lucia.SetActive (false);
}
private void ShowLucia()
{
Lucia.SetActive (true);
}
private void HideNaoto()
{
Naoto.SetActive (false);
}
private void ShowNaoto()
{
Naoto.SetActive (true);
}
private void HideArmin()
{
Armin.SetActive (false);
}
private void ShowArmin()
{
Armin.SetActive (true);
}
private void HideAria()
{
Aria.SetActive (false);
}
private void ShowAria()
{
Aria.SetActive (true);
}**
}
I code in ** are some of the parts I added myself. (tried to bold the code, guess that doesn't work lol) The problems I'm having are that the dialogue keeps replaying itself once it gets to the last line, which I don't understand because it should work exactly the same as the guy's in the tutorial, as well as the character images not showing. I've been trying to get this to work for 3 days and just can't figure it out, as I don't have a lot of experience.
I'm doing this for a video game for school, which is a final exam grade. I've done a lot of research to see if there was a simple solution for putting in dialogue but it seems like there's not, unless I want to pay tons of money for a dialogue system. I'm not going to be a pro video game designer and I'll probably never use unity again so I'm not interested in that. But if anyone has any different ideas or suggestions for an easy solution I have an open mind.
Answer by Ahndrakhul · May 21, 2016 at 09:48 PM
I think your main issue is with the lines like these:
if (DialogueStrings.Contains(LuciaString))
You are trying to search the entire array to see if it contains the LuciaString string, but you really just want to search the current dialogue string. It would need to be changed to something like this for it to work properly.
if (DialogueStrings[currentDialogueIndex].Contains(LuciaString))
I altered your code a little bit, and I think it should work as long as I guessed right about how you have things set in the editor.
Since you are just trying to see who is speaking the current line of dialogue in order to display a picture, I moved the Contains() portion of the code down to your DisplayString method. This way you can use Contains on the "stringToDisplay" string that will always be the current line of dialogue. I also added a HideAll() method and made a change to the Show methods in order to shorten the code a bit. I hope this helps!
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Dialogue2 : MonoBehaviour
{
public Text _textComponent;
public string[] DialogueStrings;
public GameObject Naoto;
public GameObject Lucia;
public GameObject Aria;
public GameObject Armin;
//for display pictures**
private string NaotoString = "Naoto:";
private string LuciaString = "Lucia:";
private string AriaString = "Aria:";
private string ArminString = "Armin:";
//for checking to see if the characters name is in the string (colon at end prevents misconceptions if characters name is just used in the dialogue)**
public float SecondsBetweenCharacters = 0.08f;
//seconds inbetween time characters in text are displayed onto dialogue box
public float CharacterRateMultiplier = 0.2f;
//for speeding it up when return is held down
public KeyCode DialogueInput = KeyCode.Return;
//declaring key to be used return key
private bool _isStringBeingRevealed = false;
//make sure couroutine isnt being called multiple times
private bool _isDialoguePlaying = false;
private bool _isEndOfDialogue = false;
//to check to see if last string of dialogue has been played
public GameObject ContinueIcon;
public GameObject StopIcon;
//giving icons to stop / continue dialogue
// Use this for initialization
void Start()
{
_textComponent = GetComponent<Text>();
_textComponent.text = "";
//getting text component and making sure its blank on start
HideIcons();
//hiding icons on start
HideAll();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Return))
{
if (!_isDialoguePlaying)
{
_isDialoguePlaying = true;
StartCoroutine(StartDialogue());
}
}
}
private IEnumerator StartDialogue()
//this is a couroutine - function like a loop but can return into the middle of the loop
//The IEnumerator - Supports a simple iteration over a non-generic collection.
{
int dialogueLength = DialogueStrings.Length;
int currentDialogueIndex = 0;
while (currentDialogueIndex < dialogueLength || !_isStringBeingRevealed)
{
if (!_isStringBeingRevealed)
//if string isnt being revealed -> start couroutine
{
_isStringBeingRevealed = true;
StartCoroutine(DisplayString(DialogueStrings[currentDialogueIndex++]));
if (currentDialogueIndex >= dialogueLength)
{
_isEndOfDialogue = true;
}
//saying that its the end of the dialogue
}
yield return 0;
}
while (true)
{
if (Input.GetKeyDown(DialogueInput) && !_isStringBeingRevealed)
{
break;
}
yield return 0;
}
HideIcons();
//when return is pressed and next string starts the icons are hidden
_isEndOfDialogue = false;
_isDialoguePlaying = false;
//resetting for next re-run basically
}
private IEnumerator DisplayString(string stringToDisplay)
{
int stringLength = stringToDisplay.Length;
//gets length of the string to be displayed
int currentCharacterIndex = 0;
//start at 0 at start of script
HideIcons();
//hiding icons at start
if (stringToDisplay.Contains(LuciaString))
{
ShowLucia();
}
if (stringToDisplay.Contains(AriaString))
{
ShowAria();
}
if (stringToDisplay.Contains(ArminString))
{
ShowArmin();
}
if (stringToDisplay.Contains(NaotoString))
{
ShowNaoto();
}
_textComponent.text = "";
//clearing text everytime its called so can display new text
while (currentCharacterIndex < stringLength)
{
_textComponent.text += stringToDisplay[currentCharacterIndex];
//get each character to stringToDisplay from textComponent using +=
//+= is someVar = someVar + otherVar
currentCharacterIndex++;
//adding 1 to the currentCharacterIndex so each character is revealed
if (currentCharacterIndex < stringLength)
{
if (Input.GetKey(DialogueInput))
{
yield return new WaitForSeconds(SecondsBetweenCharacters * CharacterRateMultiplier);
//if return key is being held down - text will be sped up
}
else
{
yield return new WaitForSeconds(SecondsBetweenCharacters);
}
}
else
{
break;
}
}
ShowIcon();
//showing continue icon after dialogue string has been revealed
while (true)
{
if (Input.GetKeyDown(DialogueInput))
{
break;
}
yield return 0;
}
//Will pause dialogue when string is revealed and let you view the next string when return is pressed
HideIcons();
HideAll();
_isStringBeingRevealed = false;
//will stop revealing string until couroutine repeats
_textComponent.text = "";
//clearing text again once while loop finished so couroutine is clear when it loops again
}
private void HideIcons()
//hides continue and stop icons
{
ContinueIcon.SetActive(false);
StopIcon.SetActive(false);
}
private void ShowIcon()
//shows continue icon if the dialogue is finished displaying
{
if (_isEndOfDialogue)
{
StopIcon.SetActive(true);
return;
}
ContinueIcon.SetActive(true);
}
//making functions to show / hide character pictures
private void HideLucia()
{
Lucia.SetActive(false);
}
private void ShowLucia()
{
HideAll();
Lucia.SetActive(true);
}
private void HideNaoto()
{
Naoto.SetActive(false);
}
private void ShowNaoto()
{
HideAll();
Naoto.SetActive(true);
}
private void HideArmin()
{
Armin.SetActive(false);
}
private void ShowArmin()
{
HideAll();
Armin.SetActive(true);
}
private void HideAria()
{
Aria.SetActive(false);
}
private void ShowAria()
{
HideAll();
Aria.SetActive(true);
}
private void HideAll()
{
HideAria();
HideArmin();
HideLucia();
HideNaoto();
}
}