1. 程式人生 > >【Unity3D遊戲開發】基於NGUI的表情圖文混排解決方案 (二二)

【Unity3D遊戲開發】基於NGUI的表情圖文混排解決方案 (二二)

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

  1. protectedvoid CalculateExpressionPos(refstring 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指令碼可實現動態表情。最終效果如下:                                                                                          

相關推薦

Unity3D遊戲開發基於NGUI表情圖文解決方案 ()

使用unity3d也有兩年時間了,最近比較閒,有功夫梳理一下去年一年來學到以及用到的知識,分享給大家,順便方便自己查閱。如有錯誤以及不當的地方,歡迎各位指正。謝謝。     去年五月份的時候,剛加入專案不久,老大交給我一個關於聊天系統任務,期初覺得應該很容易,但是看了文

Unity3d遊戲開發遊戲中的貝塞爾曲線以及其在Unity中的實現

轉載收藏:原文連結https://www.cnblogs.com/msxh/p/6270468.html 閱讀目錄 一、簡介 二、公式 三、實現與應用   RT,馬三最近在參與一款足球遊戲的開發,其中涉及到足球的各種運動軌跡和路徑,比如射門的軌跡,高吊球

Unity3D遊戲開發material與sharedMaterial的區別 (三八)

如果你需要修改模型材質的顏色,或者是修改材質Shader的一些屬性, 通常情況是用獲取模型的Renderer元件,然後獲取它的material屬性。 舉個簡單的例子,修改顏色或者直接更換shader material.color = Color.red; material.shader = Resources

Unity3D遊戲開發App遊戲名字本地化 (二七)

開發環境 Unity5.3 XCode7.2 目標 遊戲名字需要多語言處理 過程 1.新增多語言 2.用CFBundleDisplayName來處理名字多語言 失敗嘗試流程 1.未成功 info.plist裡, 新增Appl

UNITY3D 遊戲開發之七C# 中的委託、事件、匿名函式、Lambda 表示式

"委託是一個類,它定義了方法的型別,使得可以將方法當作另一個方法的引數來進行傳遞,這種將方法動態地賦給引數的做法,可以避免在程式中大量使用If-Else(Switch)語句,同時使得程式具有更好的可擴充套件性。" from: http://www.himigame.com/

Unity3D遊戲開發學習筆記(四)一切都動起來—Animator元件的應用

一、Animation簡介 動畫原本是指由許多連續的圖片在人眼前面快速播放,肉眼因視覺殘像產生錯覺,而誤以為畫面活動的作品。 但在 Unity3D 中的“ Animation”【動畫】 系統應該這樣理解——用於為遊戲者自動播放人物動作或自動演示物體運動路徑、色

Unity3D遊戲開發學習筆記(六)上帝之手—GameObject的操作

在Unity中,所有實體都屬於遊戲物件(GameObject),比如外部匯入到場景中的模型,Unity自帶的立方體等等,而要將這些GameOject進行管理,互動等操作,則需要用到指令碼來實現,上一節我們已經學習瞭如何建立一個指令碼並繫結到一個物體上,現在我們將

UNITY3D 遊戲開發之五Google-protobuf與FlatBuffers資料的序列化和反序列化

★protobuf有啥缺陷?前幾天剛剛在“光環效應 ”的帖子裡強調了“要同時評估優點和缺點”。所以俺最後再來批判一下這玩意兒的缺點。◇應用 不夠廣由於protobuf剛公佈沒多久,相比XML而言,protobuf還屬於初出茅廬。因此,在知名度、應用廣度等方面都遠不如XML。由於這個原因,假如你設計的系統需要提

UNITY3D 遊戲開發之五Google-protobuf與FlatBuffers資料的序列化和反序列化

 關於Protobuf 通過本文的轉載和分享的相關連結,足夠了解使用了,所以這裡不贅述了。但是這裡Himi順便提一下“FlatBuffers” ,它是 Protocol Buffers升級版,其主要區別在於FlatBuffers在訪問資料前不需要解析/拆包這一步。

Unity3D遊戲開發學習筆記(七)上帝之眼—第三人稱攝像機的簡單實現(跟隨視角,自由視角)

陸陸續續又開始更新自己的部落格,看來自我驅動能力還是不夠啊= =,廢話不多說了,之前的內容大概說了一下Unity的一些基礎知識,接下來我們將要對一些基本功能做一些學習。大家都知道,一個遊戲,少不了攝像機的參與(這不是廢話麼!沒攝像機怎麼玩!畫面都不呈現了好伐!)

Unity遊戲開發淺談Unity遊戲開發中的單元測試

可靠 屬於 sin 自定義類型 允許 ogr 兩個 階段 ast 一、單元測試的定義與作用   單元測試定義:單元測試在傳統軟件開發中是非常重要的工具,它是指對軟件中的最小可測試單元進行檢查和驗證,一般情況下就是對代碼中的一個函數去進行驗證,檢查它的正確性。一個單元測試是

Unity遊戲開發AssetBundle雜記--AssetBundle的三事

比較 streaming 指定 但是 chunk 加載 公司 prefab 方法 一、簡介   馬三在公司大部分時間做的都是遊戲業務邏輯和編輯器工具等相關工作,因此對Unity AssetBundle這塊的知識點並不是很熟悉,自己也是有打算想了解並熟悉一下AssetBun

Unity遊戲開發tolua之wrap文件的原理與使用

nop 微信 attr hiera n) 接下來 system 作者 prim   本文內容轉載自:https://www.cnblogs.com/blueberryzzz/p/9672342.html 。非常感謝原作者慷慨地授權轉載,比心!@blueberryzzz

Unity遊戲開發tolua之wrap檔案的原理與使用

    本文內容轉載自:https://www.cnblogs.com/blueberryzzz/p/9672342.html 。非常感謝原作者慷慨地授權轉載,比心!@blueberryzzz 是位大神,歡迎大家關注他的部落格。馬三對原文的排版與結構做了微調,以便更合適閱讀。

Unity遊戲開發用C#和Lua實現Unity中的事件分發機制EventDispatcher

一、簡介   最近馬三換了一家大公司工作,公司制度規範了一些,因此平時的業餘時間多了不少。但是人卻懶了下來,最近這一個月都沒怎麼研究新技術,部落格寫得也是拖拖拉拉,週六周天就躺屍在家看帖子、看小說,要麼就是吃雞,唉!真是罪過罪過。希望能從這篇部落格開始有些改善吧,儘量少玩耍

IOS遊戲開發之IPA破解原理

IPHONE,ITOUCH和IPAD 需要安裝蘋果的IPA軟體,我們向AppStore釋出IPA軟體的時候蘋果會給我們的IPA軟體添加簽名認證 Appstore上的應用都採用了DRM(digitalrights management)數字版權加密保護技術,直接的表現是A帳號

Lua遊戲開發os庫-時間函式

一、時間的三種格式 1、用數值表示時間值  用數字值來表示時間值, 實際上時間值的本質就是一個數字值。 例如: d = 1131286477  這裡的 1131286477 是一個以秒為單位的 格林威志時間(gmt),注意不同時區的時差2、用字串表示時間  用字串來來表

Unity遊戲開發你真的了解UGUI中的IPointerClickHandler嗎?

ali rev public 觸摸事件 proc potential 接下來 unity3 哪裏 一、引子   馬三在最近的開發工作中遇到了一個比較有意思的bug:“TableViewCell上面的某些自定義UI組件不能響應點擊事件,並且它的父容器TableV

Unity遊戲開發不接SDK也能在遊戲內拉起加QQ群操作?

一、引子   一般在遊戲進行對外測試的時候都會有一個玩家QQ群,方便玩家反饋問題、交流遊戲心得等。那麼為了增加玩家加QQ群的慾望,可能會在遊戲裡面設計一個小功能,點選一下可以直接拉起手Q加群的操作,加了QQ群以後,也會自動下發一些小獎勵刺激玩家。原本我以為要拉起手Q加QQ群的操作一定要接入相關平臺的SDK才

Unity遊戲開發SpriteAtlas與AssetBundle最佳食用方案

一、簡介   在Unity步入2019.4以後,新版的SpriteAtlas日趨完善,已經完全可以在商業專案中使用了。但是縱觀網路平臺上,許多關於SpriteAtlas的文章還停留在2018的初版時期,其中許多解釋在現在看來都是過時的,甚至近期UWA問答上的一篇Q&A也是錯誤的結論,傳送門。(筆者文章