Developing a subtitle shower

There are many ways of narrating different parts of a game. We may use audio and sometimes visuals, such as text, in order to explain what characters are trying to communicate to us. However, one of the easiest ways to explain to a player what a character is saying is through subtitles. Subtitles not only allow players to read what is sometimes also narrated by voice, but can also improve the accessibility of a game for people who may not be able to hear or may have difficulties hearing. Subtitles are always a useful addition to any game when there are things that need to be communicated to the player properly.

How to do it...

  1. As we have done previously, the first thing to do is create an UI element. In this example, we will create a panel. To do this, right-click on the Hierarchy panel, then go to UI | Panel, and rename it SubtitleShowerPanel. We should resize it and place it in the bottom part of the screen. It is also possible to change the Source Image in order to personalize the UI.
  2. The next step is to create the real UI text element that will allow us to show subtitles to the player. To do this, we right-click on SubtitleShowerPanel so that we can nest it in our panel. Then we go to UI | Text and rename it SubtitleShowerText. Again, we can tweak all its properties to fit our needs, such as Font, Font Size, Alignment, or Color.

    Tip

    While setting Font Size, keep in mind how much text will be on the subtitle shower. At the same time, this depends on what kind of game we are developing.

  3. Now it's time to start writing our script. Select SubtitleShowerPanel, and in the Inspector, navigate to Add Component | New Script. Name it SubtitleShowerScript, and then click on Create and Add.
  4. Double-click on SubtitleShowerScript in order to edit the script. Again, since we are dealing with the UI and we will be using the Text class, we have to add the using UnityEngine.UI; statement at the beginning of the script.
  5. We need a variable to store SubtitleShowerText. It's also possible to assign its value in SubtitleShowerScript itself. So, we set it to private and also static:
      private static Text uiText;
  6. In fact, we can set it in the Start() function. By doing this, we can automatize the setting of the variable by searching in the children of SubtitleShowerPanel. We also have make sure that we have just one text between all the children:
      void Start () {
        uiText = GetComponentInChildren<Text> ();
      }
  7. Before we can continue, we also require a constant. Feel free to change its value according to the kind of game that you are intending to develop. If you don't want to specify it when the coroutine is called, it will store the default duration, that is, the duration of that specific line of the subtitle:
      const float defaultDuration = 5f;
  8. Next, we have to create our coroutine, and it has to be public. This is because we want to call it from other scripts. We will also make it static so that we can get access to it without the reference to SubtitleShowerPanel. Furthermore, it should take three parameters. The first is the text that our subtitle shower has to show, the second one is how long the duration of the subtitle should be, and finally the third is AudioClip, in order to play a sound. The subtitle parameter is not an optional parameter, whereas duration and clip have default values. The defaultDuration constant we have declared before null. So, the structure of the function is as follows:
      public static IEnumerator show (string subtitle, float duration = defaultDuration, AudioClip clip = null){
      }
  9. As the first step inside the function, we will set the text to uiText so that it is immediately displayed to the player:
        uiText.text = subtitle;
  10. The next step is to check whether clip is null or not. If it isn't, we have to play the clip and wait until the audio stops. This means that we wait for a specified amount of time, which is equal to the length of clip. Otherwise, we just wait for the duration amount of time:
        if (clip) {
          AudioSource.PlayClipAtPoint (clip, Input.mousePosition);
          yield return new WaitForSeconds (clip.length);
        } else {
          yield return new WaitForSeconds (duration);
        }
  11. Finally, after we have waited for the specified time, we want the subtitle to disappear. To do this, set uiText.text to an empty string:
        uiText.text = "";
  12. Save the code, and now everything is ready to be used.
    How to do it...

How it works...

In this recipe, we created a static coroutine so that it can be called from anywhere in the game with the following function:

StartCoroutine(SubtitleShowerScript.show(subtitle,duration, clip);

But in order to keep it static, we had to set the variable as static. This is fine, as long as there is only one Subtitle Shower in the scene that it is supposed to be in. As a result, when the coroutine begins, it will handle everything. This includes setting the text and removing it after the right amount of time.

We need to pay attention when we call this coroutine. For instance, we shouldn't create more than one instance at a time, or else the two instances will overlap in controlling the components, especially because all the variables are static. Refer to the first part of the There's more... section of this recipe; it demonstrates that every time the coroutine is called, we need to wait until it is finished before it is called again.

This waiting can be done by yielding on the show() coroutine with the following instruction:

yield return StartCoroutine(SubtitleShowerScript.show(subtitle,duration, clip);

There's more...

The subtitle shower created in this recipe does the job, but it could be improved by displaying more information to the player, such as the name of character who is talking along with the avatar picture. Hence, the following sections will guide us through implementing these features.

Testing the script

In order to test the script, we need another function that calls our subtitle shower. So, let's create another script and add these variables:

public string line1, line2, line3;
public AudioClip clip;
public duration;

Then this line in the Start() function:

StartCoroutine (test ());

So, we call the following coroutine:

IEnumerator test () {
  yield return StartCoroutine(SubtitleShowerScript.show(line1));
  yield return StartCoroutine(SubtitleShowerScript.show(line2,duration));
  yield return StartCoroutine(SubtitleShowerScript.show(line3, 0f, clip));
}

Here, we have triggered our subtitle shower three times. However, before we trigger the next one, we have to wait until the previous one has finished. Furthermore, we used the public variables just to show something on the screen. Finally, we attached the script somewhere in the scene and filled the public variables. By doing this, it is possible to see our subtitle shower in action.

Tip

If we look at the last line of the script, we can see that we are passing the audio clip as a parameter. Therefore, the value of the duration doesn't matter. So every value that we pass doesn't affect Subtitle Shower.

Adding a picture of the character who is talking

When we play games, we have what is known as an avatar. It represents our character within a game. There are many different ways in which our character can be represented during a game, such as the actual itself that we control, or as an image within the HUD. During moments in the game when two characters are interacting or even conversing, having a picture of our avatar and the characters that we are engaging with can often make it easier to understand what is happening. This is especially true in moments when there is a lot of text, such as in a conversation. In such moments, a picture of our avatar next to the text that we are saying helps to distinguish between who is saying what.

If we want to implement this in our subtitle shower, we can do so by adding an Image (Script) component to SubtitleShowerPanel. Let's rename it SubtitleShowerCharacterIcon.

It is also important to place SubtitleShowerCharacterIcon inside SubtitleShowerPanel such that it is coherent with the game we are developing.

Now, we have to add a new variable to store it in our script:

private static Image uiImage;

Then we set the reference in the Start() function:

uiImage = GetComponentInChildren<Image> ();

Furthermore, the coroutine has to be changed to take a new parameter in this way:

public static IEnumerator show(string subtitle, float duration = defaultDuration, AudioClip clip = null, Sprite icon = null)

Finally, we have to set the picture at the beginning of the coroutine:

uiImage.sprite = icon;

As the last instruction, take it off:

uiImage.sprite = null;
Adding a picture of the character who is talking

Adding the name of the character who is talking

Much like our avatars, which visually represent who we are in a game, names also add another layer of personalization to our experience. Furthermore, in some games, the quality of the graphics may not be very detailed because of either their resolution or their size, as is the case with a number of mobile games. As a result, it may be hard to distinguish between different avatars, especially when they are able to be customized. Including the names of our character as well as other characters within the game can make it easier to distinguish between different characters, as opposed to visual representations alone.

We can add this feature into our Subtitle Shower. First, we need to create another Text (Script) component inside SubtitleShowerPanel and rename it SubtitleShowerCharactername.

Again, it is important to place it inside SubtitleShowerPanel so that it suits the game that we are developing.

Next, we have to add a new variable to store it in our script:

private static Image uiName;

Set the reference in the Start() function. This time, however, we need to change the way in which we refer to the two Text variables, uiName and uiText, since they both are children of SubtitleShowerPanel. We need to call the Find() function to find the game object to which they are attached before we get the actual components:

uiName = GameObject.Find("SubtitleShowerCharactername").GetComponent<Text> ();
uiText = GameObject.Find("SubtitleShowerText").GetComponent<Text> ();

Furthermore, the coroutine has to be changed to take a new parameter:

public static IEnumerator show(string subtitle, float duration = defaultDuration, AudioClip clip = null, Sprite icon = null, string name = "")

Finally, we have to show the name at the beginning of the coroutine:

uiName.text = name;

At the end, as the last instruction, take it off:

uiName.text = "";
Adding the name of the character who is talking
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.22.71.106