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.
Text
class, we have to add the using UnityEngine.UI;
statement at the beginning of the script.private
and also static
:private static Text uiText;
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> (); }
const float defaultDuration = 5f;
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){ }
text
to uiText
so that it is immediately displayed to the player:uiText.text = subtitle;
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); }
uiText.text
to an empty string:uiText.text = "";
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);
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.
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.
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;
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 = "";
3.22.71.106