這篇文章主要介紹了Unity實(shí)現(xiàn)卡拉OK歌詞過渡效果的方法,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
創(chuàng)新互聯(lián)是一家專業(yè)提供石龍企業(yè)網(wǎng)站建設(shè),專注與成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、html5、小程序制作等業(yè)務(wù)。10年已為石龍眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)的建站公司優(yōu)惠進(jìn)行中。
演示效果 ↓
實(shí)現(xiàn)歌詞動態(tài)調(diào)整功能
實(shí)現(xiàn)動態(tài)讀取歌詞文件功能
實(shí)現(xiàn)歌曲快進(jìn)快退功能
實(shí)現(xiàn)歌曲單字時間匹配功能
實(shí)現(xiàn)可動態(tài)更換歌詞前景色背景色功能
注:
這里為實(shí)現(xiàn)精準(zhǔn)過渡效果使用的是KSC歌詞文件, 并不是LRC文件哦 .
這其中我認(rèn)為就是如何實(shí)現(xiàn)歌詞部分的前景色向后景色過渡的效果了, 開始的時候我想的也是很復(fù)雜 , 使用Shader的形式實(shí)現(xiàn) ,網(wǎng)上找了一些相關(guān)代碼 , 發(fā)現(xiàn)不是特別理想 , 最終還是自己嘗試著用Mask來實(shí)現(xiàn)的, 發(fā)現(xiàn)效果還不錯 !
因?yàn)榻裉煜掳嗑瓦^年回家啦! 其他細(xì)節(jié)之后會完善的 , 今天把工程文件先上傳了 .
歌詞效果類 ↓
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System; using DG.Tweening; using DG.Tweening.Core; ////// 用于顯示歌詞過渡的效果 /// 1. 獲得路徑加載并解析歌詞文件信息 /// 2. 判斷當(dāng)前歌曲是否播放( 歌曲暫停的時候歌詞效果也暫停 , 歌曲停止的時候歌詞效果消失 ) /// 3. 判斷歌曲快進(jìn)或快退事件 /// public class LayricPanelEffect : MonoSingleton{ #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)度 ( 糾錯 ) // [HideInInspector] public float lyricAdjust = -5f; //歌詞文本信息 // [HideInInspector] [SerializeField,HideInInspector] public Text _lyricText; public Text _textContentLyric, _textLogMessage; private Vector2 tempFrontSizeDelta, tempBackSizeDelta; //用于訪問歌詞正文部分的內(nèi)容在KscWord類中 private KSC.KscWord kscword = new KSC.KscWord (); private KSC.KscWord curKscword = new KSC.KscWord (); //內(nèi)部定時器( 由外部傳入?yún)?shù)來控制 , 用來記錄歌曲播放的當(dāng)前時間軸 ) private float _timer = 0.00f; #endregion /// /// 初始化一些變量 /// void InitSomething () { //堅(jiān)持對歌詞文件進(jìn)行賦值操作 if (_lyricText == null || rectFrontLyricText.GetComponent() == null) { if (rectFrontLyricText.GetComponent () == null) { _lyricText = rectFrontLyricText.gameObject.AddComponent (); } _lyricText = rectFrontLyricText.GetComponent (); //保持歌詞實(shí)現(xiàn)自適應(yīng) rectFrontLyricText.GetComponent ().horizontalFit = ContentSizeFitter.FitMode.PreferredSize; rectFrontLyricText.GetComponent ().verticalFit = ContentSizeFitter.FitMode.PreferredSize; } rectBackLyricMask.GetComponentInChildren ().text = _lyricText.text; //歌詞顏色的更改初始化 rectBackLyricMask.GetComponentInChildren ().color = backTextColor; rectBackLyricMask.GetComponentInChildren ().effectColor = outlineColor; rectFrontLyricText.GetComponent ().color = frontTextColor; //歌詞過渡的前景部分 ( 用于判斷過度遮罩的長度范圍 ) tempFrontSizeDelta = rectFrontLyricText.sizeDelta; tempBackSizeDelta = rectBackLyricMask.sizeDelta; //是否開始當(dāng)前歌詞行播放標(biāo)志位 isStartLyricEffectTransition = true; } void Awake () { //初始化 InitSomething (); } /// /// 控制歌詞面板的顯示 /// 1. 僅僅顯示歌詞面板信息 , 沒有過渡效果! /// /// 歌詞正文部分行號. /// If set totrue 顯示面板歌詞 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 = _lyricText.text = ""; if (isPanelView) { //根據(jù)時間得到當(dāng)前播放的是第i行的歌詞 //處理歌詞面板信息 , 顯示歌詞 foreach (var item in curRowInfo.PerLineLyrics) { _lyricText.text += item; rectBackLyricMask.GetComponentInChildren ().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 = _lyricText.text = string.Empty; } } /// /// 開始實(shí)現(xiàn)歌此過渡效果, 僅僅效果實(shí)現(xiàn) /// 1. 使用Dotween的doSizedata實(shí)現(xiàn) /// 2. 動態(tài)調(diào)整蒙板的sizedata寬度 /// 3. 根據(jù)歌曲當(dāng)前播放的時間進(jìn)度進(jìn)行調(diào)整 /// ///The panel controller effect. /// If set totrue is panel effect. public IEnumerator LyricPanelControllerEffect (KSC.KscWord curRowInfo, bool isPanelEffect) { //當(dāng)前時間歌詞播放進(jìn)度的百分比比例 int curWordIndex = 0; if (isPanelEffect) { rectBackLyricMask.DORewind (); yield return null; rectBackLyricMask.sizeDelta = new Vector2 (0f, rectFrontLyricText.sizeDelta.y); //開始效果過渡 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 + "個歌詞時間"); yield return new WaitForSeconds (curKscword.PerLinePerLyricTime [i] / 1000f); } } else { Debug.LogError ("歌曲沒有播放 ?。。。?); } } else { yield return null; rectBackLyricMask.DOSizeDelta (new Vector2 (0f, rectFrontLyricText.sizeDelta.y), 0f, true); } } ////// 開始播放音樂的時候調(diào)用 /// /// 歌詞文件路徑. /// Audiosource用于判斷播放狀態(tài). /// 前景色. /// 后景. /// 如果設(shè)置為true 則使用系統(tǒng)配置的默認(rèn)顏色. 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 ****************************************************輸出歌詞文件信息 //對初始化完成后的信息進(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 ("歌曲編號=======>" + 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 ("語言種類=======>" + KSC.Instance.LangClass); } //一般是獨(dú)唱歌曲的時候使用全Tag標(biāo)簽展現(xiàn)參數(shù)信息 foreach (var item in KSC.Instance.listTags) { print (item); } #endregion //顯示整個歌詞內(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"; } } ////// 停止播放按鈕 /// public void StopPlayMusic () { Debug.Log ("停止播放按鈕"); } ////// 主要用于歌詞部分的卡拉OK過渡效果 /// 1. 動態(tài)賦值歌詞框的長度 /// 2. 支持快進(jìn)快退同步顯示 /// int row = 0, tempRow = 0; void FixedUpdate () { #region *********************************************************播放過渡效果核心代碼 //如果是播放狀態(tài)并且沒有快進(jìn)或快退 , 獲得當(dāng)前播放時間 , 如果都下一句歌詞了 , 則切換到下一句歌詞進(jìn)行過渡效果 //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 = rectFrontLyricText.GetComponent ().text = string.Empty; } //實(shí)時計(jì)時 _timer = audioSource.time; //歌曲開始播放的時間 _textLogMessage.text = _timer.ToString ("F2"); for (int i = 0; i < KSC.Instance.Add.Count; i++) { KSC.Instance.Add.TryGetValue (i, out kscword); //根據(jù)時間判斷當(dāng)前播放的是哪一行的歌詞文件 ( 減去0.01可保證兩句歌詞銜接太快的時候的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ù)時間判斷當(dāng)前播放的是哪一行的歌詞文件 ( 減去0.01可保證兩句歌詞銜接太快的時候的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; ////// KSC歌詞文件解析屬性, 單例工具類 ( 解析解析解析解析解析解析解析解析解析!!!!!!重要的事情多說幾遍 ) /// 1. 歌詞部分標(biāo)題信息用單例instance訪問 /// 2. 正文信息部分使用KSCWord對象訪問( 每句開始時間\結(jié)束時間\每句歌詞文字的數(shù)組\每句歌詞文件時間的數(shù)組 ) /// public class KSC : Singleton{ /// /// 歌曲 歌名 /// public string SongName { get; set; } ////// 歌名字?jǐn)?shù) 歌名字?jǐn)?shù) /// public int WordCount{ get; set; } ////// 歌名字?jǐn)?shù) 歌名的拼音聲母 /// public string Pinyin{ get; set; } ////// 歌名字?jǐn)?shù) 歌曲語言種類 /// public string LangClass{ get; set; } ////// 歌類,如男女樂隊(duì)等 /// public string SongClass{ get; set; } ////// 藝術(shù)家 演唱者,對唱則用斜杠"/"分隔 /// public string Singer { get; set; } ////// 歌曲編號 歌曲編號 /// public int InternalNumber{ get; set; } ////// 歌曲風(fēng)格 /// public string SongStyle{ get; set; } ////// 視頻編號 /// public string VideoFileName{ get; set; } ////// 前景顏色 /// public Color Mcolor{ get; set; } ////// 后景顏色 /// public Color Wcolor{ get; set; } ////// 偏移量 /// public string Offset { get; set; } ////// 各類標(biāo)簽 /// public ListlistTags = new List (); /// /// 歌詞正文部分信息 ( key = 行號 value = 解析出來的歌詞正文部分的每句歌詞信息 ) /// public DictionaryAdd = new Dictionary (); /// /// 獲得歌詞信息 /// /// 歌詞路徑 ///返回歌詞信息(Lrc實(shí)例) public static KSC InitKsc (string LrcPath) { int row = 0; //KscWord對象 //清除之前的歌曲歌詞, 保持當(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)新建一個對象用于存儲不同行數(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) { //行號 ( 從0行開始 ) //獲取每句歌詞部分的開始時間 kscWord.PerLineLyricStartTimer = SplitLyricStartTime (line); //獲取每句歌詞部分的結(jié)束時間 kscWord.PerLintLyricEndTimer = SplitLyricEndTime (line); //獲取每行歌詞的內(nèi)容,并存儲到KSCWord中 ( 歌詞文字的數(shù)組信息 左 → 右 ) kscWord.PerLineLyrics = SplitPerLineLyrics (line); //獲取每行中單個文字的過渡時間數(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á)式部分 需更新 ////// 處理信息(私有方法) /// /// ///返回基礎(chǔ)信息 public static string SplitStrInfo (string line) { // char[] ch = new char[]{ '\0', '\0' }; // return line.Substring (line.IndexOf ("'") + 1).TrimEnd (ch); string pattern = @"'\S{1,20}'"; //獲取歌曲標(biāo)簽信息 Match match = Regex.Match (line, pattern); //去除兩端的小分號 string resout = string.Empty; resout = match.Value.Replace ("\'", string.Empty); return resout; } ////// 處理參數(shù)是數(shù)字的情況 /// ///The int info. /// Line. public static int SplitIntInfo (string line) { string pattern = @"\d+"; //獲取歌曲標(biāo)簽參數(shù)為數(shù)字的信息 Match match = Regex.Match (line, pattern); //去除兩端的小分號 int result = 0; result = Int32.Parse (match.Value); return result; } ////// 處理參數(shù)顏色色值的情況 如: mcolor :=rgb(0, 0, 255); /// ///The color info. /// Line. 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 ())); } ////// 獲取歌曲的標(biāo)簽部分信息 如 : karaoke.tag('語種', '國語'); // 國語/粵語/臺語/外語 /// ///The tag info. 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; } ////// 獲取每句歌詞正文部分的開始時間 (單位 : 秒) /// ///The lyric start time. /// Line. public static float SplitLyricStartTime (string line) { float time = 0f; Regex regex = new Regex (@"\d{2}:\d{2}\.\d{2,3}", RegexOptions.IgnoreCase); //匹配單句歌詞時間 如: karaoke.add('00:29.412', '00:32.655' MatchCollection mc = regex.Matches (line); time = (float)TimeSpan.Parse ("00:" + mc [0].Value).TotalSeconds; return time; } ////// 獲取每句歌詞正文部分的結(jié)束時間 (單位 : 秒) /// ///The lyric start time. /// Line. public static float SplitLyricEndTime (string line) { Regex regex = new Regex (@"\d{2}:\d{2}\.\d{2,3}", RegexOptions.IgnoreCase); //匹配單句歌詞時間 如: 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; } ////// 獲取每句歌詞部分的每個文字 和 PerLinePerLyricTime相匹配 (單位 : 秒) /// ///The line lyrics. /// Line. public static string[] SplitPerLineLyrics (string line) { ListlistStrResults = new List (); string pattern1 = @"\[[\w|\W]{1,}]{1,}"; //獲取歌曲正文每個單詞 如 : karaoke.add('00:25.183', '00:26.730', '[五][十][六][個][星][座]', '312,198,235,262,249,286'); string pattern2 = @"\'(\w){1,}\'"; //獲取歌曲正文每個單詞 如 : karaoke.add('00:28.420', '00:35.431', '夕陽底晚風(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ú)唱類型的歌詞文件 ( 尚未測試英文歌詞文件!!!!!!!!!!!!!!!!!!!!!!! ) char[] tempChar = match.Value.Replace ("'", string.Empty).ToCharArray (); foreach (var item in tempChar) { listStrResults.Add (item.ToString ()); } } return listStrResults.ToArray (); } /// /// 獲取每句歌詞部分的每個文字需要的過渡時間 和 PerLineLyrics相匹配 (單位 : 秒) /// ///The line per lyric time. /// Line. public static float[] SplitPerLinePerLyricTime (string line) { string pattern = @"\'((\d){0,}\,{0,1}){0,}\'"; //獲取歌曲正文每個單詞過渡時間 如 : karaoke.add('00:25.183', '00:26.730', '[五][十][六][個][星][座]', '312,198,235,262,249,286'); string str = null; Listlistfloat = new List (); //刪除掉 多余項(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 ********************************************************************歌詞正文部分的時間與文字信息 /// /// 用單獨(dú)的類來管理歌詞的正文部分 ( 在KSC類下 )主要用來存儲每句歌詞和每個歌詞的時間信息 /// 1. 每句歌詞的時間的 ( 開始 - 結(jié)束 ) /// 2. 每句歌詞中單個文字的時間信息 (集合的形式實(shí)現(xiàn)) /// public class KscWord { ////// 每行歌詞部分開始的時間 (單位 : 秒) (key=行號,value=時間) /// public float PerLineLyricStartTimer { get; set; } ////// 每行歌詞部分結(jié)束時間 (單位 : 秒) (key=行號,value=時間) /// public float PerLintLyricEndTimer { get; set; } ////// 每行歌詞的單個文字集合 /// public string[] PerLineLyrics{ get; set; } ////// 每行歌詞中單個文字的速度過渡信息 (單位 : 毫秒) /// public float[] PerLinePerLyricTime{ get; set; } } #endregion }
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Unity實(shí)現(xiàn)卡拉OK歌詞過渡效果的方法”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!