天天看點

unity聊天系統 圖文混排

使用 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

  1. protected void CalculateExpressionPos(ref string text)  
  2. {  
  3.    NGUIText.finalSize = m_chatInput.label.defaultFontSize;//設定目前使用字型大小  
  4.    lineList.Clear();  
  5.    int row = 0;  
  6.    int textWidth = 0;  
  7.    int lastStartIndex = 0;  
  8.    string curLine = "";  
  9.    int length = text.Length;  
  10.    for (int i = 0; i < length; i++)  
  11.    {   
  12.       if (text[i] == '#' && i + 4 < length && text[i + 1] == 'e')  
  13.       {  
  14.          string eName = text.Substring(i + 2, 3);  
  15.          int eIndex = 0;  
  16.          Vector3 ePos = Vector3.zero;  
  17.          if (int.TryParse(eName, out eIndex))  
  18.          {  
  19.             float fx = 0;  
  20.             text = text.Remove(i, 5);  
  21.             text = text.Insert(i, space);//space = "       ";  
  22.             length = text.Length;  
  23.             //這裡的CalculatePrintedSize是重載過的,  
  24.             //與原本方法相比多的一個參數自定義行款,替換原方法中的rectWidth即可  
  25.             textWidth = Mathf.RoundToInt(  
  26.                NGUIText.CalculatePrintedSize(  
  27.                text.Substring(lastStartIndex, i - lastStartIndex),  
  28.                BASELINEWIDTH + 30).x);  
  29.              //BASELINEWIDTH為标準行寬度,30是根據表情大小确定的,  
  30.              //這裡的表情大小是30*30  
  31.              if (textWidth > BASELINEWIDTH - 30)           
  32.              {  
  33.                 curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);  
  34.                 lineList.Add(curLine);  
  35.                 if (textWidth <= BASELINEWIDTH - 15 ||  
  36.                     textWidth >= BASELINEWIDTH)//行末尾不夠需換行  
  37.                 {  
  38.                    fx = 0;  
  39.                    row++;  
  40.                    lastStartIndex = i;  
  41.                    ePos.x = fx - m_offsetX;  
  42.                    ePos.y = row;  
  43.                    ePos.z = eIndex;  
  44.                 }  
  45.                 else   //行末尾足夠不需換行  
  46.                 {  
  47.                    fx = textWidth;  
  48.                    lastStartIndex = i + space.Length;  
  49.                    ePos.x = fx - m_offsetX;  
  50.                    ePos.y = row;  
  51.                    ePos.z = eIndex;  
  52.                    row++;  
  53.                 }  
  54.              }  
  55.              else  
  56.              {  
  57.                 fx = textWidth;  
  58.                 ePos.x = fx - m_offsetX;  
  59.                 ePos.y = row;  
  60.                 ePos.z = eIndex;  
  61.              }  
  62.          }  
  63.          if (eIndex != 0)  
  64.          {  
  65.             eList.Add(ePos);  
  66.          }  
  67.          if (!expInLine.ContainsKey(row))        //有表情無表情行,以此确定行間距  
  68.          {  
  69.             expInLine.Add(row, true);  
  70.          }  
  71.       }  
  72.       else      //記錄換行起始Index  
  73.       {  
  74.          if (i - lastStartIndex < 0) continue;  
  75.          float curWidth = Mathf.RoundToInt(  
  76.             NGUIText.CalculatePrintedSize(  
  77.             text.Substring(lastStartIndex, i - lastStartIndex + 1),  
  78.             BASELINEWIDTH + 30).x);  
  79.          if (curWidth > BASELINEWIDTH)  
  80.          {  
  81.             curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);  
  82.             lineList.Add(curLine);  
  83.             lastStartIndex = i + 1;  
  84.             row++;  
  85.          }  
  86.          if (i == length - 1)  
  87.          {  
  88.             if (i - lastStartIndex < 0) continue;  
  89.             curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);  
  90.             lineList.Add(curLine);  
  91.          }  
  92.       }  
  93.    }  
  94. }  

      經過以上處理,輸出的lineList即為聊天内容,eList為表情資訊,expInLine字典存放每行是否存在表情資訊。将表情圖示打入一個圖集,命名為001_1、001_2。。。在顯示表情時使用UISpriteAnimation腳本可實作動态表情。最終效果如下:                                                                                          

unity聊天系統 圖文混排