
【Unity3D脚本与系统设计5】简单实现音频控制器和字幕控制器
在 Unity 中实现一个 音频控制器&字幕控制器(VoiceController&SubtitleController),可以用于管理角色对话、旁白等语音播放,并同步显示对应的字幕。
·
在 Unity 中实现一个 音频控制器&字幕控制器(VoiceController&SubtitleController),可以用于管理角色对话、旁白等语音播放,并同步显示对应的字幕。
实现步骤
音频控制器 VoiceController
基本组件结构
- 音频组件:使用 AudioSource 播放语音
public class VoiceController : MonoBehaviour
{
public static VoiceController Instance;
[Header("音频源")]
public AudioSource audioSource;
public bool playing;
[Header("对应的英文语音文件")]
public List<AudioClip> audioFileEng;
}
核心逻辑
- 获取目标文件(中文或者英文)
/// <summary>
/// 播放音频文件
/// </summary>
/// <param name="targetClip"></param>
public void playTargetAudio(AudioClip targetClip)
{
Debug.Log(targetClip.name);
audioSource.Stop();
if (targetClip == null)
{
return;
}
if (PlayerPrefs.GetString("Language") == "ENG")
{
try
{
targetClip = Enumerable.First(Enumerable.Where(audioFileEng, (AudioClip textA) => textA.name == targetClip.name.Replace("CHI", "ENG")));
}
catch
{
Debug.Log("Eng Audio File not find");
}
}
audioSource.clip = targetClip;
StopCoroutine("playAudio");
StartCoroutine("playAudio");
}
- 播放语音
/// <summary>
/// 播放音频协程
/// </summary>
/// <returns></returns>
private IEnumerator playAudio()
{
playing = true;
audioSource.Play();
while (audioSource.isPlaying)
{
yield return new WaitForEndOfFrame();
}
playing = false;
yield return new WaitForEndOfFrame();
}
字幕控制器 VoiceController
基本组件结构
- 字幕UI:UnityEngine.UI.Text 显示字幕
- 数据管理:用TextAsset
public class VoiceController : MonoBehaviour
{
public static SubtitleController Instance;
[Header("当前字幕文件")]
public TextAsset suptitleFile;
[Header("显示UIText")]
public Text suptitleUI;
[Header("当前字幕数组")]
public string[] suptitleByTime;
/// <summary>
/// 当前播放时间
/// </summary>
private int currentSec;
/// <summary>
/// 播放状态
/// </summary>
public bool playing;
[Header("对应的英文字幕文件")]
public List<TextAsset> subtitleFileEng;
}
核心逻辑
- 获取目标文件(中文或者英文)
/// <summary>
/// 播放字幕文件
/// </summary>
/// <param name="file"></param>
public void PlayTargetFile(TextAsset file)
{
StopCoroutine("autoPlay");
suptitleFile = file;
if (PlayerPrefs.GetString("Language") == "ENG")
{
try
{
suptitleFile = Enumerable.First(Enumerable.Where(subtitleFileEng, (TextAsset textA) => textA.name == file.name.Replace("CHI", "ENG")));
}
catch
{
Debug.Log("Eng Suptitle File not find");
}
}
readAllString();
StartCoroutine("autoPlay");
}
- 读取TextAsset目标文件
/// <summary>
/// 读取当前字幕文件中分段字幕
/// </summary>
private void readAllString()
{
suptitleByTime = suptitleFile.ToString().Split("|"[0]);
}
- 播放字幕
/// <summary>
/// 播放字幕协程
/// </summary>
/// <returns></returns>
private IEnumerator autoPlay()
{
currentSec = 0;
playing = true;
for (int i = 0; i < suptitleByTime.Length; i++)
{
string[] timeAndSuptitle = suptitleByTime[i].Split("\n"[0]);
string[] array = timeAndSuptitle[0].Split(new string[1] { " --> " }, StringSplitOptions.None);
if (array[0] == "")
{
continue;
}
int num = timeToint(array[0]) - currentSec;
int playTime = timeToint(array[1]) - timeToint(array[0]);
currentSec += num + playTime;
yield return new WaitForSecondsRealtime(num);
suptitleUI.text = "";
for (int j = 1; j < timeAndSuptitle.Length; j++)
{
suptitleUI.text += timeAndSuptitle[j];
if (j != timeAndSuptitle.Length - 1)
{
suptitleUI.text += "\n";
}
}
if (Enumerable.Last(suptitleUI.text) == "\n"[0])
{
suptitleUI.text = suptitleUI.text.Remove(suptitleUI.text.Length - 1);
}
yield return new WaitForSecondsRealtime(playTime);
suptitleUI.text = "";
}
playing = false;
yield return new WaitForEndOfFrame();
}
- 字符串转换播放时间
/// <summary>
/// 字符串转换播放时间
/// </summary>
/// <param name="timeString"></param>
/// <returns></returns>
private int timeToint(string timeString)
{
string[] array = timeString.Split(":"[0]);
return int.Parse(array[0]) * 60 * 60 + int.Parse(array[1]) * 60 + int.Parse(array[2]);
}
- 关闭字幕
/// <summary>
/// 结束字幕
/// </summary>
public void stopAll()
{
StopCoroutine("autoPlay");
suptitleUI.text = "";
}
案例测试
字幕文件
# GAME1_CHI_SCRIPT1.txt
|00:00:01 --> 00:00:05
陳師傅,開工前記得跟足規矩戴好安全裝備。
|00:00:05 --> 00:00:10
黃色標記嘅係必須品,㩒實扳機掣睇清楚點用
# GAME1_ENG_SCRIPT1.txt
|00:00:01 --> 00:00:05
Master Chen, remember to wear safety equipment in full order before starting work.
|00:00:05 --> 00:00:10
The yellow mark is a must, and the trigger is clearly used.
项目配置
- 字幕控制器
- 音频控制器
- 播放事件
最终效果
以上我们就完成了这个简单的实现,我们可以在这个基础上再设计一个结构清晰、可扩展的集成控制器类,利用Unity的音频和UI系统,结合协程和事件,实现语音和字幕的同步播放,同时提供必要的用户配置选项和扩展点。
更多推荐
所有评论(0)