Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Dialogue manager question

Discussion in 'Scripting' started by Phobiegames, Sep 16, 2019.

  1. Phobiegames

    Phobiegames

    Joined:
    Apr 3, 2017
    Posts:
    113
    so currently have a dialogue manager that triggers a set of dialogue, however its more of a monologue system, as it can only display one name and a set of sentences, how can i go about fixing this? Here are the scripts.

    Code (CSharp):
    1. public class DialogueTrigger : MonoBehaviour
    2. {
    3.  
    4.     public Dialogue dialogue;
    5.     public bool isTriggerArea;
    6.     public bool isInConversation;
    7.  
    8.     public void TriggerDialogue()
    9.     {
    10.         DialogueManager.instance.StartDialogue(dialogue);
    11.     }
    12.  
    13.     private void Update()
    14.     {
    15.         if(isTriggerArea == true && Input.GetKeyDown(KeyCode.E) && isInConversation == false)
    16.         {
    17.             TriggerDialogue();
    18.             isInConversation = true;
    19.         }
    20.     }
    21.  
    22.     private void OnTriggerEnter(Collider other)
    23.     {
    24.         if (other.CompareTag("Player"))
    25.         {
    26.             isTriggerArea = true;
    27.         }
    28.     }
    29.  
    30.     private void OnTriggerExit(Collider other)
    31.     {
    32.         if (other.CompareTag("Player"))
    33.         {
    34.             isTriggerArea = false;
    35.         }
    36.     }
    37. }
    Code (CSharp):
    1. public class DialogueManager : MonoBehaviour
    2. {
    3.  
    4.     public Text nameText;
    5.     public Text dialogueText;
    6.     public Animator animator;
    7.     public Queue<string> sentences;
    8.  
    9.     public static DialogueManager instance = null;
    10.  
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         sentences = new Queue<string>();
    15.     }
    16.  
    17.     private void Awake()
    18.     {
    19.         if (instance == null)
    20.  
    21.             //if not, set instance to this
    22.             instance = this;
    23.  
    24.         //If instance already exists and it's not this:
    25.         else if (instance != this)
    26.  
    27.             //Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
    28.             Destroy(gameObject);
    29.  
    30.         //Sets this to not be destroyed when reloading scene
    31.         DontDestroyOnLoad(gameObject);
    32.     }
    33.  
    34.     public void StartDialogue(Dialogue dialogue)
    35.     {
    36.         FindObjectOfType<PlayerController>().enabled = false;
    37.         FindObjectOfType<ThirdPersonCamera>().enabled = false;
    38.         animator.SetBool("IsOpen", true);
    39.         nameText.text = dialogue.name;
    40.  
    41.         sentences.Clear();
    42.  
    43.         foreach(string sentence in dialogue.sentences)
    44.         {
    45.             sentences.Enqueue(sentence);
    46.         }
    47.  
    48.         DisplayNextSentence();
    49.     }
    50.  
    51.     public void DisplayNextSentence()
    52.     {
    53.         if(sentences.Count == 0)
    54.         {
    55.             EndDialogue();
    56.             return;
    57.         }
    58.  
    59.         string sentence = sentences.Dequeue();
    60.         StopAllCoroutines();
    61.         StartCoroutine(TypeSentence(sentence));
    62.     }
    63.  
    64.     IEnumerator TypeSentence (string sentence)
    65.     {
    66.         dialogueText.text = "";
    67.         foreach (char letter in sentence.ToCharArray())
    68.         {
    69.             dialogueText.text += letter;
    70.  
    71.             yield return null;
    72.         }
    73.     }
    74.  
    75.     void EndDialogue()
    76.     {
    77.         animator.SetBool("IsOpen", false);
    78.         FindObjectOfType<PlayerController>().enabled = true;
    79.         FindObjectOfType<ThirdPersonCamera>().enabled = true;
    80.     }
    81. }
    Code (CSharp):
    1. [System.Serializable]
    2. public class Dialogue
    3. {
    4.     public string name;
    5.  
    6.     [TextArea(3, 10)]
    7.     public string[] sentences;
    8.  
    9. }
     
  2. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,748
    You need something like this.

    Code (CSharp):
    1. [System.Serializable]
    2. public class Monologue
    3. {
    4.     public string name;
    5.     [TextArea(3, 10)]
    6.     public string[] sentences;
    7.  
    8.    public Monologue[] responses;
    9. }
    After that, you may let player choose from sences in one of possible responses to this machine monologue and then choose next monologue (or action) for machine from choosen player response.
     
  3. Phobiegames

    Phobiegames

    Joined:
    Apr 3, 2017
    Posts:
    113
    Im trying to simply make characters talk back and forth, so after a character gets done speaking, the other character speaks (and changes the name text depending on character speaking)
     
  4. Phobiegames

    Phobiegames

    Joined:
    Apr 3, 2017
    Posts:
    113
    Okay so a quick update, i managed to get it to where i can use multiple dialogues to do what i want by using a foreach loop. However this isn't working with the characters name text to display who is speaking, what am i doing wrong?

    Updated code that made it work:

    Code (CSharp):
    1.     public void StartDialogue(Dialogue[] dialogue)
    2.     {
    3.         FindObjectOfType<PlayerController>().enabled = false;
    4.         FindObjectOfType<ThirdPersonCamera>().enabled = false;
    5.         animator.SetBool("IsOpen", true);
    6.         //if(dialogue.isObject == true)
    7.         //{
    8.             //nameText.text = "";
    9.             //nameBox.SetActive(false);
    10.         //}
    11.         //else
    12.         //{
    13.             //nameText.text = dialogue.name;
    14.             //nameBox.SetActive(true);
    15.         //}
    16.         sentences.Clear();
    17.  
    18.         foreach (Dialogue item in dialogue)
    19.         {
    20.             nameText.text = item.name;
    21.             foreach (string sentence in item.sentences)
    22.             {
    23.                 sentences.Enqueue(sentence);
    24.             }
    25.         }
    26.  
    27.         DisplayNextSentence();
    28.     }
    Edit: just to clarify whats not working, the nameText.text is always turning out to be the very last element in the dialogue array for character names, Where as i need it to display each name per dialogue sequence, any ideas would be helpful!
     
    Last edited: Sep 17, 2019
  5. Phobiegames

    Phobiegames

    Joined:
    Apr 3, 2017
    Posts:
    113
    I've managed to get everything working, but I can't seem to find a way to swap out the name string between each dialogue. I don't really want to add an array of strings to the dialogue class because i only need one name per class used. I'm pretty much stumped, have no idea how i'm suppose to access the name data of each dialogue and i have no idea how to display it with the ui text either.

    The closest thing i could come up with is this bit of code here, but i keep getting an error in the foreach line called Assets\Scripts\DialogueManager.cs(70,13): error CS0030: Cannot convert type 'char' to 'string'.

    Code (CSharp):
    1.         for (int i = 0; i < dialogue.Length; i++)
    2.         {
    3.             foreach (string namesin in dialogue[i].name)
    4.             {
    5.                 nameText.text = namesin;
    6.             }
    7.         }
     
    Last edited: Sep 18, 2019
  6. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    strings are also treated as char arrays. in your foreach loop, you are looping through dialogue.name. Maybe you meant to loop through something else in dialogue?

    On another note, how sophisticated are you intending to make this? Are you intending to eventually allow the player to make story altering choices through this system?
     
  7. Phobiegames

    Phobiegames

    Joined:
    Apr 3, 2017
    Posts:
    113
    Not at the moment, i only plan to have the characters talk back and forth at the moment, and i use this for quest text. Otherwise not super sophisticated. The idea was to loop through dialogue to access dialogue.name so i could display the name but its not working and if i did loop through it, i notice its just showing the final name of the dialogue class list
     
    Last edited: Sep 18, 2019
  8. doctorpangloss

    doctorpangloss

    Joined:
    Feb 20, 2013
    Posts:
    270
    For a free solution, use Ink!

    There is a $20 asset called Dialogue Manager with an excellent in-game nodes and lines editor. But writers hate that interface, so really, use Ink.
     
  9. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,616
    That's because you wrote
    Code (csharp):
    1.  
    2. nameText.text = item.name;
    3.  
    nameText.text can only have one value so all you are doing in your loop is replacing that value over and over again.
     
  10. Phobiegames

    Phobiegames

    Joined:
    Apr 3, 2017
    Posts:
    113
    Thanks for the response! Yeah, what would you do to get all of the names but still display them when they need to be? I know i could use a list to get all the name strings but i dont really know where to go from there