Skip to main content

Play audio with a subtitle

You need to be able to create a trigger that plays audio when entering a collider as well as have a basic understanding of UI canvases in order to complete this lesson.

Setup a Unity Scene with a player object and a trigger that plays a sound when you enter it. You can find a guide for that here.

Add a Canvas to your scene.

If using the new Input System click on the EventSystem and click the Replace with InputSystemUIModule.

Add Text to the canvas.

Rename this SubtitleBox or similar. This is the text box that will display our subtitle.

\

Note that by default it it in the bottom left of the screen.

We need to change its position.

In the transform set an anchor point. Middle bottom is quite good.

Now reset the Pos X and Pos Y values to 0.

You'll now see the Text Box in the middle at the bottom.

It's still quite small we need to adjust the canvas so that it scales with the window size by default.

Click on the Canvas.

In the Canvas Scaler component change form Constant Pixel Size to Scale with Screen Size.

Set the reference (default resolution). x 1920 by y 1080 is useful as full HD is a common default resolution.

You'll notice the text box is even smaller now.

Change its width and height to something more suitable. 1000 x 100 is often suitable.

We also want to move the text box up on the screen. Change the Pos Z value to 150.

Change the Text settings so the text is readible. This usually involves increasing the font size and changing the text colour and alignment.

Note is we use white text we cannot see it here.

A solution is to add a background behind the text.

Add a UI panel and resize it to be the same size as the text box.

When we test this the scene permanently shows the canvas. This isn't what we want.

Uncheck the canvas in the inspector to turn it off.

Now the canvas doesn't appear at all.

Now we have to link it up to the trigger.

Open the AudioTriggerScript.

It should look like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayAudioAndSubtitleOnTriggerEnter : MonoBehaviour
{

[SerializeField]
AudioSource _soundEffect;

void OnTriggerEnter(Collider other) {
if(other.CompareTag("Player")) {
Debug.Log("Player in range");
_soundEffect.Play();
}
}
}

We want to add another serialized field for the Canvas.

Add this below the _soundEffect variable.

	[SerializeField]
Canvas _subtitleCanvas;

Now after we play the sound effect we want to display the Canvas by activating it.

Modify the OnTriggerEnter function to:

	void OnTriggerEnter(Collider other) {
if(other.CompareTag("Player")) {
Debug.Log("Player in range");
_soundEffect.Play();
_subtitleCanvas.gameObject.SetActive(true);
}
}

Now link the Canvas to the script in the inspector.

Test your program. The canvas should now appear when you enter the trigger.

Finally we want the canvas to disappear after a set amount of time.

There are two ways shown here we could achieve this.

  1. When we exit the trigger turn off the canvas.
  2. Turn off the canvas after a set period of time.

Option 1: Turn off the canvas when we exit the trigger

Add the following function to your script:

	void OnTriggerExit(Collider other) {
if(other.CompareTag("Player")) {
Debug.Log("Player out of range");

_subtitleCanvas.gameObject.SetActive(false);
}
}

This will remove the canvas when we leave the trigger.

If you wanted to you could also include a Stop function call to the sound effect to stop the sound immediately when you exit.

_soundEffect.Stop();

Option 2: Turn off the canvas after a set period of time

To achieve this we will use an IEnumerator and a CoRoutine which will wait for a set number of seconds and then set the canvas to not being active.

First create the IEnumerator function. In this example it is called RemoveSubtitle(). For the CoRoutine to be able to run these functions cannot have any parameters.

	IEnumerator RemoveSubtitle() {
yield return new WaitForSeconds(2);
_subtitleCanvas.gameObject.SetActive(false);
}

Inside the OnTriggerEnter function we need to place a call to start the CoRoutine.

This line of code is:

StartCoroutine(RemoveSubtitle());

We give the name of the function to run as a parameter to StartCoroutine.

Test your code.

You now have a working subtitle for a sound effect. We could also use Coroutines to queue up different pieces of a subtitle and display them in order.

Below is the completed script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayAudioAndSubtitleOnTriggerEnter : MonoBehaviour
{

[SerializeField]
AudioSource _soundEffect;
[SerializeField]
Canvas _subtitleCanvas;

void OnTriggerEnter(Collider other) {
if(other.CompareTag("Player")) {
Debug.Log("Player in range");
_soundEffect.Play();
_subtitleCanvas.gameObject.SetActive(true);
StartCoroutine(RemoveSubtitle());
}


}

void OnTriggerExit(Collider other) {
if(other.CompareTag("Player")) {
Debug.Log("Player out of range");
_soundEffect.Stop();
_subtitleCanvas.gameObject.SetActive(false);
}
}

IEnumerator RemoveSubtitle() {
yield return new WaitForSeconds(2);
_subtitleCanvas.gameObject.SetActive(false);
}
}