溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Unity中怎么實(shí)現(xiàn)卡拉OK歌詞過(guò)渡效果

發(fā)布時(shí)間:2021-08-11 13:52:45 來(lái)源:億速云 閱讀:130 作者:Leah 欄目:編程語(yǔ)言

今天就跟大家聊聊有關(guān)Unity中怎么實(shí)現(xiàn)卡拉OK歌詞過(guò)渡效果,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

歌詞效果類 ↓

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;using System;using DG.Tweening;using DG.Tweening.Core;/// <summary>/// 用于顯示歌詞過(guò)渡的效果/// 1. 獲得路徑加載并解析歌詞文件信息/// 2. 判斷當(dāng)前歌曲是否播放( 歌曲暫停的時(shí)候歌詞效果也暫停 , 歌曲停止的時(shí)候歌詞效果消失 )/// 3. 判斷歌曲快進(jìn)或快退事件/// </summary>public class LayricPanelEffect : MonoSingleton<LayricPanelEffect>{ #region *********************************************************************字段 //由外部傳入的聲音資源 [HideInInspector,SerializeField] public AudioSource audioSource; //歌詞前景顏色;歌詞后景顏色 [SerializeField] public Color32 frontTextColor = Color.white, backTextColor = Color.black, outlineColor = Color.white; //歌詞面板的前景部分和后景部分 public RectTransform rectFrontLyricText, rectBackLyricMask; public Slider slider; //歌詞文件路徑 [HideInInspector,SerializeField] public string lyricFilePath; //是否開始播放當(dāng)前行歌詞內(nèi)容 public bool isStartLyricEffectTransition = true; //歌詞調(diào)整進(jìn)度 ( 糾錯(cuò) ) // [HideInInspector] public float lyricAdjust = -5f; //歌詞文本信息 // [HideInInspector] [SerializeField,HideInInspector] public Text _lyricText; public Text _textContentLyric, _textLogMessage; private Vector2 tempFrontSizeDelta, tempBackSizeDelta; //用于訪問(wèn)歌詞正文部分的內(nèi)容在KscWord類中 private KSC.KscWord kscword = new KSC.KscWord (); private KSC.KscWord curKscword = new KSC.KscWord (); //內(nèi)部定時(shí)器( 由外部傳入?yún)?shù)來(lái)控制 , 用來(lái)記錄歌曲播放的當(dāng)前時(shí)間軸 ) private float _timer = 0.00f; #endregion /// <summary> /// 初始化一些變量 /// </summary> void InitSomething () { //堅(jiān)持對(duì)歌詞文件進(jìn)行賦值操作 if (_lyricText == null || rectFrontLyricText.GetComponent <ContentSizeFitter> () == null) { if (rectFrontLyricText.GetComponent <Text> () == null) { _lyricText = rectFrontLyricText.gameObject.AddComponent <Text> (); } _lyricText = rectFrontLyricText.GetComponent <Text> (); //保持歌詞實(shí)現(xiàn)自適應(yīng) rectFrontLyricText.GetComponent <ContentSizeFitter> ().horizontalFit = ContentSizeFitter.FitMode.PreferredSize; rectFrontLyricText.GetComponent <ContentSizeFitter> ().verticalFit = ContentSizeFitter.FitMode.PreferredSize; } rectBackLyricMask.GetComponentInChildren <Text> ().text = _lyricText.text; //歌詞顏色的更改初始化 rectBackLyricMask.GetComponentInChildren <Text> ().color = backTextColor; rectBackLyricMask.GetComponentInChildren <Outline> ().effectColor = outlineColor; rectFrontLyricText.GetComponent <Text> ().color = frontTextColor; //歌詞過(guò)渡的前景部分 ( 用于判斷過(guò)度遮罩的長(zhǎng)度范圍 ) tempFrontSizeDelta = rectFrontLyricText.sizeDelta; tempBackSizeDelta = rectBackLyricMask.sizeDelta; //是否開始當(dāng)前歌詞行播放標(biāo)志位 isStartLyricEffectTransition = true; } void Awake () {  //初始化 InitSomething (); } /// <summary> /// 控制歌詞面板的顯示 /// 1. 僅僅顯示歌詞面板信息 , 沒(méi)有過(guò)渡效果! /// </summary> /// <param name="row">歌詞正文部分行號(hào).</param> /// <param name="isPanelView">If set to <c>true</c> 顯示面板歌詞</param> public void LyricPanelControllerView (KSC.KscWord curRowInfo, bool isPanelView) {// Debug.Log ("當(dāng)前行是否開始=====>" + isPanelView.ToString ()); _textLogMessage.text = isStartLyricEffectTransition.ToString (); rectBackLyricMask.sizeDelta = new Vector2 (0f, rectFrontLyricText.sizeDelta.y); rectBackLyricMask.GetComponentInChildren <Text> ().text = _lyricText.text = ""; if (isPanelView) { //根據(jù)時(shí)間得到當(dāng)前播放的是第i行的歌詞 //處理歌詞面板信息 , 顯示歌詞 foreach (var item in curRowInfo.PerLineLyrics) { _lyricText.text += item; rectBackLyricMask.GetComponentInChildren<Text> ().text = _lyricText.text; } StartCoroutine (LyricPanelControllerEffect (curRowInfo, isPanelView)); } else { StopAllCoroutines (); rectBackLyricMask.sizeDelta = new Vector2 (0f, rectFrontLyricText.sizeDelta.y);// StartCoroutine (LyricPanelControllerEffect (curRowInfo, isPanelView)); //當(dāng)前歌詞結(jié)束以后將歌詞框初始化成0 rectBackLyricMask.GetComponentInChildren <Text> ().text = _lyricText.text = string.Empty; } } /// <summary> /// 開始實(shí)現(xiàn)歌此過(guò)渡效果, 僅僅效果實(shí)現(xiàn) /// 1. 使用Dotween的doSizedata實(shí)現(xiàn) /// 2. 動(dòng)態(tài)調(diào)整蒙板的sizedata寬度 /// 3. 根據(jù)歌曲當(dāng)前播放的時(shí)間進(jìn)度進(jìn)行調(diào)整 /// </summary> /// <returns>The panel controller effect.</returns> /// <param name="isPanelEffect">If set to <c>true</c> is panel effect.</param> public IEnumerator LyricPanelControllerEffect (KSC.KscWord curRowInfo, bool isPanelEffect) { //當(dāng)前時(shí)間歌詞播放進(jìn)度的百分比比例 int curWordIndex = 0; if (isPanelEffect) { rectBackLyricMask.DORewind (); yield return null; rectBackLyricMask.sizeDelta = new Vector2 (0f, rectFrontLyricText.sizeDelta.y); //開始效果過(guò)渡 if (audioSource.isPlaying) { for (int i = 0; i < curKscword.PerLinePerLyricTime.Length; i++) { rectBackLyricMask.DOSizeDelta ( new Vector2 (((float)(i + 1) / curKscword.PerLinePerLyricTime.Length) * rectFrontLyricText.sizeDelta.x, rectFrontLyricText.sizeDelta.y) , curKscword.PerLinePerLyricTime [i] / 1000f , false).SetEase (Ease.Linear);// Debug.Log ("第" + i + "個(gè)歌詞時(shí)間"); yield return new WaitForSeconds (curKscword.PerLinePerLyricTime [i] / 1000f); } } else { Debug.LogError ("歌曲沒(méi)有播放 ?。。?!"); } } else { yield return null; rectBackLyricMask.DOSizeDelta (new Vector2 (0f, rectFrontLyricText.sizeDelta.y), 0f, true); } } /// <summary> /// 開始播放音樂(lè)的時(shí)候調(diào)用 /// </summary> /// <param name="lyricFilePath">歌詞文件路徑.</param> /// <param name="audioSource">Audiosource用于判斷播放狀態(tài).</param> /// <param name="frontColor">前景色.</param> /// <param name="backColor">后景.</param> /// <param name="isIgronLyricColor">如果設(shè)置為 <c>true</c> 則使用系統(tǒng)配置的默認(rèn)顏色.</param> public void StartPlayMusic (string lyricFilePath, AudioSource audioSource, Color frontColor, Color backColor, Color outlineColor, bool isIgronLyricColor) { _timer = 0f; //初始化ksc文件 KSC.InitKsc (lyricFilePath); this.lyricFilePath = lyricFilePath; this.audioSource = audioSource; _textContentLyric.text = string.Empty; if (!isIgronLyricColor) { //歌曲顏色信息 this.frontTextColor = frontColor; this.backTextColor = backColor; this.outlineColor = outlineColor; } #region ****************************************************輸出歌詞文件信息 //對(duì)初始化完成后的信息進(jìn)行輸出 if (KSC.Instance.SongName != null) { print ("歌名==========>" + KSC.Instance.SongName); } if (KSC.Instance.Singer != null) { print ("歌手==========>" + KSC.Instance.Singer); } if (KSC.Instance.Pinyin != null) { print ("拼音==========>" + KSC.Instance.Pinyin); } if (KSC.Instance.SongClass != null) { print ("歌類==========>" + KSC.Instance.SongClass); } if (KSC.Instance.InternalNumber > 0) { print ("歌曲編號(hào)=======>" + KSC.Instance.InternalNumber); } if (KSC.Instance.Mcolor != Color.clear) { print ("男唱顏色=======>" + KSC.Instance.Mcolor); } if (KSC.Instance.Mcolor != Color.clear) { print ("女唱顏色=======>" + KSC.Instance.Wcolor); } if (KSC.Instance.SongStyle != null) { print ("風(fēng)格==========>" + KSC.Instance.SongStyle); } if (KSC.Instance.WordCount > 0) { print ("歌名字?jǐn)?shù)=======>" + KSC.Instance.WordCount); } if (KSC.Instance.LangClass != null) { print ("語(yǔ)言種類=======>" + KSC.Instance.LangClass); } //一般是獨(dú)唱歌曲的時(shí)候使用全Tag標(biāo)簽展現(xiàn)參數(shù)信息 foreach (var item in KSC.Instance.listTags) { print (item); } #endregion //顯示整個(gè)歌詞內(nèi)容 for (int i = 0; i < KSC.Instance.Add.Values.Count; i++) { KSC.Instance.Add.TryGetValue (i, out kscword); for (int j = 0; j < kscword.PerLineLyrics.Length; j++) { _textContentLyric.text += kscword.PerLineLyrics [j]; } _textContentLyric.text += "\n"; } } /// <summary> /// 停止播放按鈕 /// </summary> public void StopPlayMusic () { Debug.Log ("停止播放按鈕"); } /// <summary> /// 主要用于歌詞部分的卡拉OK過(guò)渡效果 /// 1. 動(dòng)態(tài)賦值歌詞框的長(zhǎng)度 /// 2. 支持快進(jìn)快退同步顯示 /// </summary> int row = 0, tempRow = 0; void FixedUpdate () { #region *********************************************************播放過(guò)渡效果核心代碼 //如果是播放狀態(tài)并且沒(méi)有快進(jìn)或快退 , 獲得當(dāng)前播放時(shí)間 , 如果都下一句歌詞了 , 則切換到下一句歌詞進(jìn)行過(guò)渡效果 //1. 是否是暫停; //2. 是否開始播放 //3. 是否播放停止 if (audioSource != null && audioSource.isPlaying) { //進(jìn)度條 slider.value = _timer / audioSource.clip.length; //快進(jìn)快退快捷鍵 if (Input.GetKey (KeyCode.RightArrow)) { audioSource.time = Mathf.Clamp ((audioSource.time + 1f), 0f, 4.35f * 60f); } else if (Input.GetKey (KeyCode.LeftArrow)) { audioSource.time = Mathf.Clamp ((audioSource.time - 1f), 0f, 4.35f * 60f);// } else if (Input.GetKeyUp (KeyCode.LeftArrow)) { isStartLyricEffectTransition = true; rectBackLyricMask.GetComponentInChildren <Text> ().text = rectFrontLyricText.GetComponent <Text> ().text = string.Empty; } //實(shí)時(shí)計(jì)時(shí) _timer = audioSource.time; //歌曲開始播放的時(shí)間 _textLogMessage.text = _timer.ToString ("F2"); for (int i = 0; i < KSC.Instance.Add.Count; i++) { KSC.Instance.Add.TryGetValue (i, out kscword); //根據(jù)時(shí)間判斷當(dāng)前播放的是哪一行的歌詞文件 ( 減去0.01可保證兩句歌詞銜接太快的時(shí)候的bug ) if ((_timer >= (kscword.PerLineLyricStartTimer + lyricAdjust + 0.1f) && _timer <= (kscword.PerLintLyricEndTimer + lyricAdjust - 0.1f)) && isStartLyricEffectTransition) { tempRow = i; KSC.Instance.Add.TryGetValue (tempRow, out curKscword); isStartLyricEffectTransition = false; Debug.Log ("當(dāng)前播放====>" + i + "行"); //歌詞面板顯示當(dāng)前播放內(nèi)容 LyricPanelControllerView (curKscword, !isStartLyricEffectTransition); } else if ((_timer >= (curKscword.PerLintLyricEndTimer + lyricAdjust)) && !isStartLyricEffectTransition) { isStartLyricEffectTransition = true; //設(shè)置不顯示歌詞內(nèi)容 LyricPanelControllerView (curKscword, !isStartLyricEffectTransition); }  }// KSC.Instance.Add.TryGetValue (row, out kscword);//// //根據(jù)時(shí)間判斷當(dāng)前播放的是哪一行的歌詞文件 ( 減去0.01可保證兩句歌詞銜接太快的時(shí)候的bug )// if ((_timer >= (kscword.PerLineLyricStartTimer + lyricAdjust + 0.1f) && _timer <= (kscword.PerLintLyricEndTimer + lyricAdjust)) && isStartLyricEffectTransition) {// tempRow = row;// KSC.Instance.Add.TryGetValue (tempRow, out curKscword);// isStartLyricEffectTransition = false;// Debug.Log ("當(dāng)前播放====>" + row + "行");// //歌詞面板顯示當(dāng)前播放內(nèi)容// LyricPanelControllerView (curKscword, !isStartLyricEffectTransition);// } else if ((_timer >= (curKscword.PerLintLyricEndTimer + lyricAdjust)) && !isStartLyricEffectTransition) {// isStartLyricEffectTransition = true;// //設(shè)置不顯示歌詞內(nèi)容// LyricPanelControllerView (curKscword, !isStartLyricEffectTransition);// row = (row + 1) % KSC.Instance.Add.Count;// }  #endregion } }}

###KSC文件解析類 ↓

using System.Collections;using System.Collections.Generic;using UnityEngine;using System.IO;using System.Text;using UnityEngine.UI;using System;using System.Text.RegularExpressions;using System.Runtime.InteropServices;/// <summary>/// KSC歌詞文件解析屬性, 單例工具類 ( 解析解析解析解析解析解析解析解析解析!!!!!!重要的事情多說(shuō)幾遍 )/// 1. 歌詞部分標(biāo)題信息用單例instance訪問(wèn)/// 2. 正文信息部分使用KSCWord對(duì)象訪問(wèn)( 每句開始時(shí)間\結(jié)束時(shí)間\每句歌詞文字的數(shù)組\每句歌詞文件時(shí)間的數(shù)組 )/// </summary>public class KSC : Singleton<KSC>{ /// <summary> /// 歌曲 歌名 /// </summary> public string SongName { get; set; } /// <summary> /// 歌名字?jǐn)?shù) 歌名字?jǐn)?shù) /// </summary> public int WordCount{ get; set; } /// <summary> /// 歌名字?jǐn)?shù) 歌名的拼音聲母 /// </summary> public string Pinyin{ get; set; } /// <summary> /// 歌名字?jǐn)?shù) 歌曲語(yǔ)言種類 /// </summary> public string LangClass{ get; set; } /// <summary> /// 歌類,如男女樂(lè)隊(duì)等 /// </summary> public string SongClass{ get; set; } /// <summary> /// 藝術(shù)家 演唱者,對(duì)唱?jiǎng)t用斜杠"/"分隔 /// </summary> public string Singer { get; set; } /// <summary> /// 歌曲編號(hào) 歌曲編號(hào) /// </summary> public int InternalNumber{ get; set; } /// <summary> /// 歌曲風(fēng)格 /// </summary> public string SongStyle{ get; set; } /// <summary> /// 視頻編號(hào)  /// </summary> public string VideoFileName{ get; set; } /// <summary> /// 前景顏色 /// </summary> public Color Mcolor{ get; set; } /// <summary> /// 后景顏色 /// </summary> public Color Wcolor{ get; set; } /// <summary> /// 偏移量 /// </summary> public string Offset { get; set; } /// <summary> /// 各類標(biāo)簽 /// </summary> public List<string> listTags = new List<string> (); /// <summary> /// 歌詞正文部分信息 ( key = 行號(hào) value = 解析出來(lái)的歌詞正文部分的每句歌詞信息 ) /// </summary> public Dictionary<int,KscWord> Add = new Dictionary<int, KscWord> (); /// <summary> /// 獲得歌詞信息 /// </summary> /// <param name="LrcPath">歌詞路徑</param> /// <returns>返回歌詞信息(Lrc實(shí)例)</returns> public static KSC InitKsc (string LrcPath) { int row = 0; //KscWord對(duì)象 //清除之前的歌曲歌詞, 保持當(dāng)前 KSC.Instance.Add.Clear (); using (FileStream fs = new FileStream (LrcPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { string line = string.Empty; using (StreamReader sr = new StreamReader (fs, Encoding.Default)) {  while ((line = sr.ReadLine ()) != null) { //每次循環(huán)新建一個(gè)對(duì)象用于存儲(chǔ)不同行數(shù)內(nèi)容 KSC.KscWord kscWord = new KSC.KscWord (); #region ######################################合唱歌曲格式 if (line.StartsWith ("karaoke.songname := '")) { Instance.SongName = SplitStrInfo (line); } else if (line.StartsWith ("karaoke.internalnumber := ")) { if (SplitIntInfo (line) != 0) { Instance.InternalNumber = SplitIntInfo (line); } } else if (line.StartsWith ("karaoke.singer := '")) { Instance.Singer = SplitStrInfo (line); } else if (line.StartsWith ("karaoke.wordcount := ")) { if (SplitIntInfo (line) != 0) { Instance.WordCount = SplitIntInfo (line); } } else if (line.StartsWith ("karaoke.pinyin := '")) { Instance.Pinyin = SplitStrInfo (line); } else if (line.StartsWith ("karaoke.langclass := '")) { Instance.LangClass = SplitStrInfo (line); } else if (line.StartsWith ("karaoke.songclass := '")) { Instance.SongClass = SplitStrInfo (line); } else if (line.StartsWith ("karaoke.songstyle := '")) { Instance.SongStyle = SplitStrInfo (line); } else if (line.StartsWith ("karaoke.videofilename :='")) { Instance.VideoFileName = SplitStrInfo (line); } else if (line.StartsWith ("mcolor :=rgb(")) { if (SplitColorInfo (line) != Color.clear) { Instance.Mcolor = SplitColorInfo (line); } } else if (line.StartsWith ("wcolor :=rgb(")) { if (SplitColorInfo (line) != Color.clear) { Instance.Wcolor = SplitColorInfo (line); } #endregion #region ##################################################獨(dú)唱歌曲風(fēng)格 } else if (line.StartsWith ("karaoke.tag('")) { //獲取tag標(biāo)簽的參數(shù)信息 KSC.Instance.listTags.Add (SplitTagInfo (line)); #endregion  #region ################################################歌詞正文部分解析 } else if (line.StartsWith (("karaoke.add"))) {   //表示歌詞正文部分 if (SplitLyricStartTime (line) != null) { //行號(hào) ( 從0行開始 ) //獲取每句歌詞部分的開始時(shí)間 kscWord.PerLineLyricStartTimer = SplitLyricStartTime (line); //獲取每句歌詞部分的結(jié)束時(shí)間 kscWord.PerLintLyricEndTimer = SplitLyricEndTime (line); //獲取每行歌詞的內(nèi)容,并存儲(chǔ)到KSCWord中 ( 歌詞文字的數(shù)組信息 左 → 右 ) kscWord.PerLineLyrics = SplitPerLineLyrics (line); //獲取每行中單個(gè)文字的過(guò)渡時(shí)間數(shù)組 ( 歌詞文字過(guò)渡時(shí)間數(shù)組 左 → 右 ) kscWord.PerLinePerLyricTime = SplitPerLinePerLyricTime (line); KSC.Instance.Add.Add (row, kscWord); row++; } } else { //忽略ksc文件中的其他部分 if (line != "" && !line.Contains ("CreateKaraokeObject") && !line.Contains ("karaoke.rows") && !line.Contains ("karaoke.clear;") && !Regex.IsMatch (line, @"^\//")) { Debug.LogWarning ("歌詞含有不能解析的部分 ===> " + line); } } #endregion } } }  Debug.Log ("LyricFileInitialized" + " Path : \n" + LrcPath); return Instance; } #region ****************************************************************解析歌詞用的正則表達(dá)式部分 需更新 /// <summary> /// 處理信息(私有方法) /// </summary> /// <param name="line"></param> /// <returns>返回基礎(chǔ)信息</returns> public static string SplitStrInfo (string line) {// char[] ch = new char[]{ '', '' };// return line.Substring (line.IndexOf ("'") + 1).TrimEnd (ch); string pattern = @"'\S{1,20}'"; //獲取歌曲標(biāo)簽信息 Match match = Regex.Match (line, pattern); //去除兩端的小分號(hào) string resout = string.Empty; resout = match.Value.Replace ("\'", string.Empty); return resout; } /// <summary> /// 處理參數(shù)是數(shù)字的情況 /// </summary> /// <returns>The int info.</returns> /// <param name="line">Line.</param> public static int SplitIntInfo (string line) { string pattern = @"\d+"; //獲取歌曲標(biāo)簽參數(shù)為數(shù)字的信息 Match match = Regex.Match (line, pattern); //去除兩端的小分號(hào) int result = 0; result = Int32.Parse (match.Value); return result; } /// <summary> /// 處理參數(shù)顏色色值的情況 如: mcolor :=rgb(0, 0, 255); /// </summary> /// <returns>The color info.</returns> /// <param name="line">Line.</param> public static Color32 SplitColorInfo (string line) { string pattern = @"[r,R][g,G][b,G]?[\(](2[0-4][0-9])|25[0-5]|[01]?[0-9][0-9]?"; //獲取歌曲標(biāo)簽參數(shù)為顏色值的信息 MatchCollection matches = Regex.Matches (line, pattern); return new Color (float.Parse (matches [0].ToString ()), float.Parse (matches [1].ToString ()), float.Parse (matches [2].ToString ())); } /// <summary> /// 獲取歌曲的標(biāo)簽部分信息 如 : karaoke.tag('語(yǔ)種', '國(guó)語(yǔ)'); // 國(guó)語(yǔ)/粵語(yǔ)/臺(tái)語(yǔ)/外語(yǔ) /// </summary> /// <returns>The tag info.</returns> public static string SplitTagInfo (string line) { string temp; string pattern = @"\([\W|\w]+\)"; //獲取歌曲標(biāo)簽參數(shù)為顏色值的信息 Match match = Regex.Match (line, pattern); temp = match.Value.Replace ("(", string.Empty).Replace (")", string.Empty).Replace ("'", string.Empty).Replace (",", ":"); return temp; } /// <summary> /// 獲取每句歌詞正文部分的開始時(shí)間 (單位 : 秒) /// </summary> /// <returns>The lyric start time.</returns> /// <param name="line">Line.</param> public static float SplitLyricStartTime (string line) { float time = 0f; Regex regex = new Regex (@"\d{2}:\d{2}\.\d{2,3}", RegexOptions.IgnoreCase); //匹配單句歌詞時(shí)間 如: karaoke.add('00:29.412', '00:32.655' MatchCollection mc = regex.Matches (line); time = (float)TimeSpan.Parse ("00:" + mc [0].Value).TotalSeconds; return time; } /// <summary> /// 獲取每句歌詞正文部分的結(jié)束時(shí)間 (單位 : 秒) /// </summary> /// <returns>The lyric start time.</returns> /// <param name="line">Line.</param> public static float SplitLyricEndTime (string line) { Regex regex = new Regex (@"\d{2}:\d{2}\.\d{2,3}", RegexOptions.IgnoreCase); //匹配單句歌詞時(shí)間 如: karaoke.add('00:29.412', '00:32.655' MatchCollection mc = regex.Matches (line); float time = (float)TimeSpan.Parse ("00:" + mc [1].Value).TotalSeconds; return time; } /// <summary> /// 獲取每句歌詞部分的每個(gè)文字 和 PerLinePerLyricTime相匹配 (單位 : 秒) /// </summary> /// <returns>The line lyrics.</returns> /// <param name="line">Line.</param> public static string[] SplitPerLineLyrics (string line) { List<string> listStrResults = new List<string> (); string pattern1 = @"\[[\w|\W]{1,}]{1,}"; //獲取歌曲正文每個(gè)單詞 如 : karaoke.add('00:25.183', '00:26.730', '[五][十][六][個(gè)][星][座]', '312,198,235,262,249,286'); string pattern2 = @"\'(\w){1,}\'"; //獲取歌曲正文每個(gè)單詞 如 : karaoke.add('00:28.420', '00:35.431', '夕陽(yáng)底晚風(fēng)里', '322,1256,2820,217,1313,1083'); Match match = (line.Contains ("[") && line.Contains ("]")) ? Regex.Match (line, pattern1) : Regex.Match (line, pattern2); //刪除掉 [ ] ' if (match.Value.Contains ("[") && match.Value.Contains ("]")) { //用于合唱類型的歌詞文件 string[] resultStr = match.Value.Replace ("][", "/").Replace ("[", string.Empty).Replace ("]", string.Empty).Split ('/'); foreach (var item in resultStr) { listStrResults.Add (item); } } else if (match.Value.Contains ("'")) {  //用于獨(dú)唱類型的歌詞文件 ( 尚未測(cè)試英文歌詞文件!!!!!!!!!!!!!!!!!!!!!!! ) char[] tempChar = match.Value.Replace ("'", string.Empty).ToCharArray (); foreach (var item in tempChar) { listStrResults.Add (item.ToString ()); } } return listStrResults.ToArray (); } /// <summary> /// 獲取每句歌詞部分的每個(gè)文字需要的過(guò)渡時(shí)間 和 PerLineLyrics相匹配 (單位 : 秒) /// </summary> /// <returns>The line per lyric time.</returns> /// <param name="line">Line.</param> public static float[] SplitPerLinePerLyricTime (string line) { string pattern = @"\'((\d){0,}\,{0,1}){0,}\'"; //獲取歌曲正文每個(gè)單詞過(guò)渡時(shí)間 如 : karaoke.add('00:25.183', '00:26.730', '[五][十][六][個(gè)][星][座]', '312,198,235,262,249,286'); string str = null; List<float> listfloat = new List<float> (); //刪除掉 多余項(xiàng) str = Regex.Match (line, pattern).Value.Replace ("'", string.Empty);// Debug.Log (str); foreach (var item in str.Split (',')) { listfloat.Add (float.Parse (item)); } return listfloat.ToArray (); } #endregion #region ********************************************************************歌詞正文部分的時(shí)間與文字信息 /// <summary> /// 用單獨(dú)的類來(lái)管理歌詞的正文部分 ( 在KSC類下 )主要用來(lái)存儲(chǔ)每句歌詞和每個(gè)歌詞的時(shí)間信息 /// 1. 每句歌詞的時(shí)間的 ( 開始 - 結(jié)束 ) /// 2. 每句歌詞中單個(gè)文字的時(shí)間信息 (集合的形式實(shí)現(xiàn)) /// </summary> public class KscWord { /// <summary> /// 每行歌詞部分開始的時(shí)間 (單位 : 秒) (key=行號(hào),value=時(shí)間) /// </summary> public float PerLineLyricStartTimer { get; set; } /// <summary> /// 每行歌詞部分結(jié)束時(shí)間 (單位 : 秒) (key=行號(hào),value=時(shí)間) /// </summary> public float PerLintLyricEndTimer { get; set; } /// <summary> /// 每行歌詞的單個(gè)文字集合 /// </summary> public string[] PerLineLyrics{ get; set; } /// <summary> /// 每行歌詞中單個(gè)文字的速度過(guò)渡信息 (單位 : 毫秒) /// </summary> public float[] PerLinePerLyricTime{ get; set; } } #endregion}

看完上述內(nèi)容,你們對(duì)Unity中怎么實(shí)現(xiàn)卡拉OK歌詞過(guò)渡效果有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI