使用 unity3d也有兩年時間了,最近比較閑,有功夫梳理一下去年一年來學到以及用到的知識,分享給大家,順便友善自己查閱。如有錯誤以及不當的地方,歡迎各位指正。謝謝。 去年五月份的時候,剛加入項目不久,老大交給我一個關于聊天系統任務,期初覺得應該很容易,但是看了文檔之後,瞬間頭都大了_(:з」∠)_,因為需要支援表情!當時Unity3D版本4.3.x,NGUI版本3.5x,當時版本的NGUI已經支援動态字型,我們的項目也不例外,趕忙就用上了。但是,表情的 問題要怎麼解決?總不能用顔文字吧(╯‵□′)╯︵┻━┻。如果不用動态字型而使用自己制作的圖集字型,倒是可以将表情圖檔打進字庫解決。但是既然我們已經用了動态字型,我就隻能另想辦法了。 經過兩天的研究實踐,最終找到一個能夠實作的解決辦法。主要思路是: 1.定義一個标準行寬度,以此作為基準對文字以及表情進行分行處理; 2.使用特殊符号标記表情(例如:#e001),周遊字元串,凡遇到表情标記則将之與位置記錄下來,并使用“ ”(空格,具體數量視表情大小而定)将特殊标記替換。 3.使用Vector3記錄以上資訊,x為表情的橫坐标,y為表情所在行數(即縱坐标),z為表情的ID,即剛才的001,以此确定是哪個表情。使用一個List将所有表情資訊存放起來,顯示時周遊List即可。 有了以上基本思路,下面隻要編碼實作,但是在編碼過程中還是不可避免的問題——如何得到一段文字的長度?這時,就需要用到一個NGUI封裝的一個方法NGUIText.CalculatePrintedSize傳入參數為string,傳回一個Vector2,表示這段文字的長和寬。下面是核心代碼。
[code]csharpcode:
[csharp] view plain copy
- protected void CalculateExpressionPos(ref string text)
- {
- NGUIText.finalSize = m_chatInput.label.defaultFontSize;//設定目前使用字型大小
- lineList.Clear();
- int row = 0;
- int textWidth = 0;
- int lastStartIndex = 0;
- string curLine = "";
- int length = text.Length;
- for (int i = 0; i < length; i++)
- {
- if (text[i] == '#' && i + 4 < length && text[i + 1] == 'e')
- {
- string eName = text.Substring(i + 2, 3);
- int eIndex = 0;
- Vector3 ePos = Vector3.zero;
- if (int.TryParse(eName, out eIndex))
- {
- float fx = 0;
- text = text.Remove(i, 5);
- text = text.Insert(i, space);//space = " ";
- length = text.Length;
- //這裡的CalculatePrintedSize是重載過的,
- //與原本方法相比多的一個參數自定義行款,替換原方法中的rectWidth即可
- textWidth = Mathf.RoundToInt(
- NGUIText.CalculatePrintedSize(
- text.Substring(lastStartIndex, i - lastStartIndex),
- BASELINEWIDTH + 30).x);
- //BASELINEWIDTH為标準行寬度,30是根據表情大小确定的,
- //這裡的表情大小是30*30
- if (textWidth > BASELINEWIDTH - 30)
- {
- curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);
- lineList.Add(curLine);
- if (textWidth <= BASELINEWIDTH - 15 ||
- textWidth >= BASELINEWIDTH)//行末尾不夠需換行
- {
- fx = 0;
- row++;
- lastStartIndex = i;
- ePos.x = fx - m_offsetX;
- ePos.y = row;
- ePos.z = eIndex;
- }
- else //行末尾足夠不需換行
- {
- fx = textWidth;
- lastStartIndex = i + space.Length;
- ePos.x = fx - m_offsetX;
- ePos.y = row;
- ePos.z = eIndex;
- row++;
- }
- }
- else
- {
- fx = textWidth;
- ePos.x = fx - m_offsetX;
- ePos.y = row;
- ePos.z = eIndex;
- }
- }
- if (eIndex != 0)
- {
- eList.Add(ePos);
- }
- if (!expInLine.ContainsKey(row)) //有表情無表情行,以此确定行間距
- {
- expInLine.Add(row, true);
- }
- }
- else //記錄換行起始Index
- {
- if (i - lastStartIndex < 0) continue;
- float curWidth = Mathf.RoundToInt(
- NGUIText.CalculatePrintedSize(
- text.Substring(lastStartIndex, i - lastStartIndex + 1),
- BASELINEWIDTH + 30).x);
- if (curWidth > BASELINEWIDTH)
- {
- curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);
- lineList.Add(curLine);
- lastStartIndex = i + 1;
- row++;
- }
- if (i == length - 1)
- {
- if (i - lastStartIndex < 0) continue;
- curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);
- lineList.Add(curLine);
- }
- }
- }
- }
經過以上處理,輸出的lineList即為聊天内容,eList為表情資訊,expInLine字典存放每行是否存在表情資訊。将表情圖示打入一個圖集,命名為001_1、001_2。。。在顯示表情時使用UISpriteAnimation腳本可實作動态表情。最終效果如下: