Survival Shooter Link:

Unity Version:

  • Unity 2018.1.5f1

NOTE:

  • This tutorial is stand alone, but it is also part 1 of the Objective Based Tutorial System.

Uses:

  • You can use this to talk to the Player
  • A conversation between two or more characters.
  • A quick way of sending a message to the player. (ex. in-game instructions)
  • Substituting / Testing NPC Questing.

Setting up the Scene

  1.  To Follow Along, Download the Survival Shooter Tutorial.
    • NOTE:
      • This is not required to create, the dialog box, we are just using it as a sandbox project to test our dialog box.
      • If you don’t need the survival shooter, skip to Create DialogBox Update.
  2. Store the Survival Shooter Project in a 0 – Game Folder. This will allow us to create our Demo project in a separate folder, and allow us to use it in any project.

    • SceneSetup-2-Project
  3. Then, create a Demo Folder at the top level. This will be separate from the survival shooter project.

  4. Open up the Survival Shooter Project, Located here:

    • 0 – Game/_Complete-Game/_Complete-Game

      NOTE: Normally, we would create a UI Canvas from scratch, by right clicking anywhere in the ‘Hierarchy’, going to UI, then Canvas. However, there’s already a canvas available in this Project, named HUD Canvas. We will use that instead.


Create DialogBox Object

  1. Right Click HUD Canvas in the Hierarchy, and select Create Empty. Name it DialogBox
    • This will function as our container for anything related to the Dialog Box.CreateDialogBox-1-CanvasGrp

      NOTE: Enable interactable, and Blocks Raycast in the HUDCanvas object, under Canvas Group. If this is not enabled, your buttons will NOT work on trigger, as the raycast will not trigger the buttons (ie. Canvas Events).

  2. Right Click HUD Canvas in the Hierarchy, and select Panel.
    • Set Width: 350
    • Set Height: 200
    • For the Panel, go to Rect Transform / Anchor Points / Center. This will center the anchor points.CreateDialogBox-2-RectTransform
  3. Create a new Text object, by right clicking our DialogBox object, in the Hierarchy, go to UI/Text.
    • Set it over the Panel, and rename it Content
      • Set Width: 325
      • Set Height: 150
  4. Create a new Text object, by right clicking our DialogBox object, in the Hierarchy, go to UI/Text.
    • Set it to the bottom Left of the panel, and name it Page Counter.
  5. Create a new Button by right clicking our DialogBox object in the Hierarchy. Go to UI/Button.
    • Set the button to the bottom right of the Panel, and name it Next_btn.
    • Duplicate the Next_btn, set it to the Left of Next_btn, and name it Previous_btn
    • Your scene, and Hierachy should look like this:
    • CreateDialogBox-5-FullImage
  6. Create two additional Folders within the Demo Project, and a DialogBox Folder within Scripts.
  7. Now create 2 scripts within Demo/Scripts/DialogBox called:
        • Content.cs
        • DialogBox.cs
        • You will end up with the following:CreateDialogBox-7-ProjFolder
  8. Now store the DialogBox Object we just made, as a Prefab within:
    1. Demo/Prefabs/

Starting our Scripts:

We need to create a few references in our DialogBox.cs script, so we can update the appropriate objects for our DialogBox.

public class DialogBox : MonoBehaviour {
   public Content dialogContent;
   public Text displayText;
   public Text pageCounter;
}

The three references are used to update different sections in our DialogBox.

  • dialogContent: the content used for our DialogBox. This needs to be updated, whenever we want to initialize our content piece.
  • displayText: Main content piece that is displayed to the user.
  • pageCounter: displays the currentPage and max number of pages to the player.

Next, we need to add [Serializable] to our Content.cs Class.

[Serializable]
public class Content {

This will allow the DialogBox to serialize the Content class in the inspector.

Next, we will add a line to the Content.cs Class.

[TextArea(3, 10)]
public List content;

This will allow us to add some content  to the DialogBox.

Now, add the DialogBox.cs class to our DialogBox GameObject within the Hierachy, and add some content in the inspector so we can test it.

For Example:

StartingOurScript-Example


Buttons!

We need to add some button functionality, whenever the Next Button is triggered.

Pseudo Code:
When Next button is triggered…
Get the Next Content Piece…
Update the PageCounter…

public void NextButton()
{
   displayText.text = dialogContent.NextContentPiece();
   UpdateText();
}

Now, the pseudo code above states “Get the Next Content Piece

In Content.cs we also need to find a way to return the next content piece to the dialog box, where the Content.cs piece still has full control of what content is delivered.

We can do that by adding an Index to keep track of which content to display, and adding a NextContentPiece() method inside the Content.cs class.

public string NextContentPiece()
{
   index++;
   currentContent = content.ElementAt(index);
   return currentContent;
}

The content.ElementAt(index) uses a System.Linq reference. This will return the specified element at the ‘index’ value. If ‘index’ = 0, it returns the first element within the content list.

Now, if you’ve noticed, in the DialogBox.NextButton(), there is an DialogBox.UpdateText() method. This is updated to Update the PageCounter. But The reason it is its own method is that we will use this same call in the PreviousButton().

Also, there is an issue. The NextButton can be called endlessly. This gives us an error later on in the Editor, when the Current Page Count == the Max Page Count. We need to add a check to Check if we have reached the Max Number of Pages, and if we have, disable the DialogBox as we no longer need it.

We can fix this by adding a new boolean called IsAtMaxPages, and adding a check in our DialogBox.UpdateText() method.

public void UpdateText()
{
   pageCounter.text = string.Format("{0} / {1}", dialogContent.index + 1, dialogContent.totalAmount);
   if(dialogContent.index + 1 == dialogContent.totalAmount)
   {
      IsAtMaxPages = true;
   }
   else
   {
      IsAtMaxPages = false;
   }
}

This will allow us to alter our DialogBox.NextButton() by checking if we have reached the max number of pages.

The code below checks if we are at max, and if we are, disable the dialogbox, and end it there.


public void NextButton()
{
   if(IsAtMaxPages)
   {
      this.gameObject.SetActive(false);
      return;
   }
   //Update the displayText.
   displayText.text = dialogContent.NextContentPiece();
   UpdateText();
}

Now, we need to do the same thing for our PreviousButton. Except, we need to check the ‘First’ Element, instead of the ‘Last’ element in the index.


public string PreviousButton()
{
   if(dialogContent.index == 0)
   {
      return;
   }
   displayText.text = dialogContent.PreviousContentPiece();
   UpdateText();
}
In the Content.PreviousContentPiece(), we need to do the same thing, except we're decrementing the index, instead of incrementing.

public string PreviousContentPiece()
{
   index--;
   currentContent = content.ElementAt(index);
   return currentContent;
}

Initialize!

Now, this works all well and good, however, we still don’t have a way to ‘Start’ or ‘Initialize’ our DialogBox. We need an entrance, or some event to Start our DialogBox. Typically in regular business development, you would do this with the constructor. However, MonoBehaviour isn’t constructor friendly, so we can do the next best thing and create our own.

Start by Creating a DialogBox.Initialize(Content content) method.

Then assign the dialogContent to the content, and get the first displayText from the Content.

public void Initialize(Content content)
{
   dialogContent = content;
   displayText.text = dialogContent.InitialContent();
   UpdateText();
}

Now create Content.InitialContent(), get the first element in the list, assign, and return it.

public string InitialContent()
{
   index = 0;
   currentContent = content.ElementAt(index);
   return currentContent;
}

This will take care of our Initialization.

NOTE: Be sure to call the Initialize(content) method to invoke the dialogBox whenever you want the character to interact with it.


Wrap Up!

Now, we want to update the Next Button Text, from Next to OK, when the player reaches the final content page

We can do this easily by adding a reference to the DialogBox.cs class, to the Next Button, and updating the Text in the DialogBox.UpdateText() method.

public Button nextButton;

public void UpdateText() 
{
   //Update the page Counter.
   pageCounter.text = string.Format("{0} / {1}", dialogContent.index + 1, dialogContent.totalAmount);
   if(dialogContent.index + 1 == dialogContent.totalAmount)
   {
      IsAtMaxPages = true;
      nextButton.GetComponentInChildren().text = "OK";
   }
   else
   {
      IsAtMaxPages = false;
      nextButton.GetComponentInChildren().text = "Next";
   }
}

Now, switch back to Unity, and assign the references to the corresponding objects in the DialogBox prefab.

WrapUp-1
WrapUp-2.png

Happy Coding!