Search Unity

Resolved Need help with dialogue script using event broker

Discussion in 'Scripting' started by dannyryba, Jul 16, 2020.

  1. dannyryba

    dannyryba

    Joined:
    Jun 22, 2020
    Posts:
    45
    Hi everyone, I'm at my wit's end trying to figure this one out. I apologize in advance for the amounts of code I'm going to have to post here, as I can't exactly pinpoint where the issue lies (though I have a good idea). Hope some people here are up for the challenge :)

    Some context: I have been trying to build my project with an emphasis on de-coupling code and using an observer pattern, employing an event system that uses a broker to manage things indirectly. The problem I am running into is using a dialogue system based on this one from Brackeys:


    Everything in my project works perfectly fine except the text will not move past the first sentence in my queue. It stays stuck on the first sentence and I can't seem to find where the problem is - though if I had to guess it would lie in the DialogController script.

    Here is the PlayerInput script to start.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEditor.Experimental.GraphView;
    5. using UnityEngine;
    6.  
    7.  
    8. public class PlayerInput : MonoBehaviour
    9.  
    10. //this script is to handle inputs by the player
    11.  
    12. {
    13.     public bool canInput = true;
    14.  
    15.     private void Awake()
    16.     {
    17.         PlayerBroker.PlayerStop += StopInput;
    18.         PlayerBroker.PlayerMove += StartInput;
    19.     }
    20.     void Update()
    21.     {
    22.         if(canInput)
    23.         {
    24.  
    25.             if (Input.GetAxisRaw("Horizontal") > 0.5f || Input.GetAxisRaw("Horizontal") < -0.5f) //if the horizontal button returns a value greater than .5 in either direction
    26.             {
    27.                 PlayerBroker.CallMoveHorizontal(); //call this event from the PlayerBroker
    28.             }
    29.             else if (Input.GetAxisRaw("Vertical") > 0.5f || Input.GetAxisRaw("Vertical") < -0.5f) //if the vertical button returns a value greater than .5 in either direction
    30.             {
    31.                 PlayerBroker.CallMoveVertical(); //call this event from the PlayerBroker
    32.             }
    33.             if (Input.GetKeyDown(KeyCode.Space) || Input.GetButtonDown("Submit"))
    34.             {
    35.                 PlayerBroker.CallCanTalk();
    36.                 Debug.Log("Checking to see if the player can talk...");
    37.             }
    38.         }
    39.  
    40.     }
    41.  
    42.  
    43.     private void StopInput()
    44.     {
    45.         canInput = false;
    46.     }
    47.  
    48.     private void StartInput()
    49.     {
    50.         canInput = true;
    51.     }
    52. }
    This calls into the PlayerBroker script, which handles pretty much anything to do with player activation or actions.
    Code (CSharp):
    1. using System;
    2. using System.Diagnostics;
    3.  
    4. public class PlayerBroker
    5. {
    6.     //this class is to broker event actions for the player
    7.  
    8.     public static event Action MoveVertical;
    9.     public static event Action MoveHorizontal;
    10.     public static event Action PlayerStop;
    11.     public static event Action PlayerMove;
    12.     public static event Action CanTalk;
    13.     public static event Action<Dialog> StartDialog;
    14.     public static void CallMoveVertical()
    15.     {
    16.         MoveVertical?.Invoke(); //if movevertical is not null, invoke it
    17.     }
    18.  
    19.     public static void CallMoveHorizontal()
    20.     {
    21.         MoveHorizontal?.Invoke(); //if movehorizontal is not null, invoke it
    22.     }
    23.  
    24.     public static void CallPlayerStop()
    25.     {
    26.         PlayerStop?.Invoke();
    27.     }
    28.  
    29.     public static void CallPlayerMove()
    30.     {
    31.         PlayerMove?.Invoke();
    32.     }
    33.  
    34.     public static void CallCanTalk()
    35.     {
    36.         CanTalk?.Invoke();
    37.     }
    38.  
    39.     public static void CallStartDialog(Dialog dialog)
    40.     {
    41.         StartDialog?.Invoke(dialog);
    42.     }
    43. }
    This then raises a flag to the DialogTrigger, which sees if the player can activate any dialog based on Collision Triggers...

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class DialogTrigger : MonoBehaviour
    6. {
    7.     public Dialog dialog;
    8.     private bool canActivate = false;
    9.  
    10.     // Update is called once per frame
    11.     void Update()
    12.     {
    13.         if (canActivate)
    14.         {
    15.             PlayerBroker.CanTalk += StartDialog;
    16.         }
    17.         else if (!canActivate)
    18.         {
    19.             PlayerBroker.CanTalk -= StartDialog;
    20.         }
    21.  
    22.     }
    23.  
    24.     private void StartDialog()
    25.     {
    26.         PlayerBroker.CallStartDialog(dialog);
    27.         PlayerBroker.CallPlayerStop();
    28.     }
    29.  
    30.     private void OnTriggerEnter2D(Collider2D other)
    31.     {
    32.         if (other.CompareTag("Player"))
    33.         {
    34.             canActivate = true;
    35.         }
    36.     }
    37.  
    38.     private void OnTriggerExit2D(Collider2D other)
    39.     {
    40.         if (other.CompareTag("Player"))
    41.         {
    42.             canActivate = false;
    43.         }
    44.     }
    45. }
    Which then calls back to the PlayerBroker, which then raises an event to the DialogController, where the meat of the dialog system lies (it also stops the player from putting any inputs related to movement and initial dialog activation)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5.  
    6. public class DialogController : MonoBehaviour
    7. {
    8.  
    9.     public TextMeshProUGUI nameText;
    10.     public TextMeshProUGUI dialogText;
    11.     public bool dialogStarted = false;
    12.  
    13.     private Queue<string> sentences;
    14.  
    15.     private void Awake()
    16.     {
    17.         PlayerBroker.StartDialog += StartDialog;
    18.     }
    19.  
    20.     private void Start()
    21.     {
    22.         sentences = new Queue<string>();
    23.     }
    24.  
    25.     public void StartDialog(Dialog dialog)
    26.     {
    27.         if(!dialogStarted)
    28.         {
    29.             Debug.Log("dialogstarted is now true");
    30.        
    31.             dialogStarted = true;
    32.        
    33.             PlayerBroker.CallPlayerStop();
    34.             Debug.Log("calling player stop event.");
    35.  
    36.             nameText.text = dialog.name;
    37.  
    38.             sentences.Clear(); //clear any sentences in the queue
    39.  
    40.             foreach (string sentence in dialog.sentences) //for each sentence, enqueue it
    41.             {
    42.                 sentences.Enqueue(sentence);
    43.             }
    44.  
    45.             if(dialogStarted && Input.GetButtonDown("Submit") || Input.GetKeyDown(KeyCode.Space))
    46.             {
    47.                 DisplayNextSentence(); //then run the display method
    48.                 Debug.Log("running next sentence method");
    49.             }
    50.        
    51.         }
    52.  
    53.     }
    54.  
    55.     public void DisplayNextSentence()
    56.     {
    57.         if (sentences.Count == 0) //if no more sentences
    58.         {
    59.             EndDialog(); //end the dialog
    60.             return;
    61.         }
    62.  
    63.         string sentence = sentences.Dequeue(); //otherwise, dequeue the sentences (FIFO order)
    64.         StopAllCoroutines(); //stop any coroutines that are running so that they don't double up
    65.         StartCoroutine(TypeSentence(sentence)); //start coroutine
    66.     }
    67.  
    68.     IEnumerator TypeSentence (string sentence)
    69.     {
    70.         dialogText.text = "";
    71.         foreach (char letter in sentence.ToCharArray())
    72.         {
    73.             dialogText.text += letter;
    74.             yield return new WaitForSeconds(0.02f);
    75.         }
    76.     }
    77.  
    78.     private void EndDialog()
    79.     {
    80.         dialogStarted = false;
    81.         PlayerBroker.CallPlayerMove();
    82.         Debug.Log("Dialog over");
    83.         //here is where any end dialog animation can go
    84.     }
    85.  
    86. }
    And this is where the problem shows up. The Debug Log shows "running next sentence method" but it never actually gets past the first sentence. I have tried so many things to fix this, but must be missing something (probably obvious). I'm hoping someone can help!

    Again sorry to post so much code but the issue could be in any one of these, since there are a lot of events getting raised as part of the process. I really appreciate anyone who takes the time to read through this whole thing and help me out :)

    Edit: Figured it out with some help from the discord...I wasn't using Update to check for the player input :oops:
     
    Last edited: Jul 17, 2020