Reminder, this uses the same configuration of the SimpleDialogPrefab for the version that doesn't use SpeakerImage. Remember to add the DialogText as the first child of the DialogPanel.
DialogPrefab with Image
You have a choice of using the Simple DialogPrefab for your project, which does not include a UI image with a sprite to allow display of an image of each conversation entry's speaker. Otherwise, follow steps to create DialogPrefab wImg on the subsequent page.
NextPanelToOpen
The DialogManager script has a public reference variable that can be set in the Inspector allows for the nextPanelToOpen to be populated. After all of the dialog entries has been displayed, the dialogPanel is closed, and then the nextPanelToOpen will be opened. If not populated, no error will occur because the code first checks to see if that variable contains a valid object reference (memory address).
Add the linked script to the DecisionPanel so it will stay closed at the start of the scene, if desired Hide_Show_Panel Script
A coroutine is like a function that has the ability to pause execution and return control to Unity but then to continue where it left off on the following frame.
OpenDialogBtn
The OpenDialogBtn public obj-reference variable in the Inspector should be populated if a button will be used to open the dialog. Otherwise, the ShowOnStart checkbox in the Inspector should be selected, it will make the panel visible at the beginning of the scene.
For example, set OpenDialogBtn to a StartDialog Button
The image below shows that the public ConversationList variable: convList has been set in the inspector by selecting the circle-icon to the right of the ConvList item
DialogManager.cs
Below is the full code for the DialogManager.cs. You can paste this code into a script in your project.
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;/// <summary>/// Dialog manager. F20/// Put this script on a panel with canvasGroup, /// Important: remove SpriteRenderer from Panel/// required child objects: dialogText, speakerName, nextDialogBtn/// </summary>publicclassDialogManager : MonoBehaviour{publicCanvasGroup nextPanelToOpenCG; //next panel to open, set in InspectorpublicButton openDialogBtn; //Button that will open Dialogpublic bool showOnStart =false;privateButton nextBtn;privateCanvasGroup dialogPanelCG;privateText dialogText, speakerName; //speakerName;privateImage speakerImage;publicConversationList convList; //attach scriptable object in InspectorprivateQueue<ConversationEntry> conversationsQueue =newQueue<ConversationEntry>();// Use this for initializationvoidStart() { dialogPanelCG =GetComponent<CanvasGroup>(); //used to show/hide panelText[] textChildren =GetComponentsInChildren<Text>();Image[] imageChildren =GetComponentsInChildren<Image>(); dialogText = textChildren[0]; speakerName = textChildren[2];if (imageChildren.Length>4 ) { //means there is a speakerImageDebug.Log("childImages"+imageChildren.Length); speakerImage = imageChildren[4]; //fifth child image - in SpeakerPanel } nextBtn =GetComponentInChildren<Button>();nextBtn.onClick.AddListener(GetNextDialog);if( convList !=null) {InitializeDialog(); //call once in Start }//checkbox that can be set in inspector, if checked, then this is not exectedif (!showOnStart) {Utility.HideCG(dialogPanelCG);if (openDialogBtn !=null) //if opening dialog with a Button, Populate OpenDialogButton in the Inspector {openDialogBtn.onClick.AddListener(ShowDialogPanel); } }else { //if showing on scene load, get first Dialog Utility.ShowCG(dialogPanelCG); } } //end of Start//Populates the Queue with ConversationEntries //from the ConvList scriptableObject's Conversation variable.//Also calls GetNextDialog to populate initial conversation data for first conversationvoidInitializeDialog() {foreach (ConversationEntry item in convList.Conversation) {conversationsQueue.Enqueue(item); //put each string -item in the queue }GetNextDialog(); //get first item } //end method/// <summary>/// Opens the dialog./// this method is called if there is an /// openDialog button set in the Inspector/// otherwise, select checkbox showOnStart /// </summary>publicvoidShowDialogPanel() {Utility.ShowCG(dialogPanelCG);if (openDialogBtn !=null){openDialogBtn.gameObject.SetActive(false); } } //end method/// <summary>/// Nexts the dialog./// Sets UI elements: speakerName, speakerImage, dialogText/// </summary>/// <returns><c>true</c>, if dialog there is more dialog, <c>false</c> otherwise.</returns>publicvoidGetNextDialog() {if (conversationsQueue.Count>0) {ConversationEntry item =conversationsQueue.Dequeue();speakerName.text=item.speakerName;if (speakerImage !=null) { //if not using SpritespeakerImage.sprite=item.speakerImg; }StopAllCoroutines(); string curSentence =item.dialogTxt;StartCoroutine(TypeSentence(curSentence)); }else//no more conversations {Utility.HideCG(dialogPanelCG); // close panelif (nextPanelToOpenCG !=null) //check to see if valid gameObject was set in inspector {Utility.ShowCG(nextPanelToOpenCG); } } } //end GetNextDialog method//this allows single characters to be added to look like typed textIEnumeratorTypeSentence(string sentence) {dialogText.text=""; //clear previous sentanceforeach (char letter in sentence.ToCharArray()) {dialogText.text+= letter;yieldreturnnewWaitForSeconds(0.05f); ; } }//end TypeSentence method//can be executed to pass in a conversationList from some triggering eventpublicvoidTriggeredDialog( ConversationList conversation) { convList = conversation;InitializeDialog();Utility.ShowCG(dialogPanelCG);//see if there is a next panel to openGameObject nextPanelGameObj =GameObject.Find(convList.nextPanelName);if (nextPanelGameObj !=null) { nextPanelToOpenCG =nextPanelGameObj.GetComponent<CanvasGroup>(); }Debug.Log("DialogManager, startDialog"); }} // end class