在我們工作中,可能經常有這樣的需求,就是需要圖文混排,因為這個對于原生或web都是比較容易的事情。但是我們用unity的話,首先unity最開始隻想做純遊戲側的引擎,一開始甚至還沒有一個商業化的ui工具,後面才結合了ngui成為ugui,當然現在也出現了uielement。但要做到圖文混排一開始還是不容易的,需要四處找插件,甚至需要自己想辦法文字和圖檔自己做結合來實作。
經過了一段時間後unity出現了textmesh,他可以實作圖文混排,他圖文混排的方式相當于是多一個材質,然後再文法上用類似<quad material=1>來實作。實際上他也能實作圖文混排的方式,隻需要打個圖集,把圖集放到材質上,材質放到textmesh的第二個材質上就好了。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2csUnVzMWdGJzYzhnMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4ETN0MzNxAjM1AzMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
這個圖集材質是長這樣的:
實作的效果是:
看上去沒問題,能實作效果。但是他有幾個問題:
第一就是他的設定圖檔的方式:<quad material=1 x=0.001953125 y=0.244140625 width=0.25 height=0.125/>
注意這裡的x,y,width,height都是0到1的,也就是你需要自己把圖檔的位置和圖檔的寬高通過圖集的寬高換算出來(實際上就是算偏移)。
比如x=250;圖集的寬是1024;那麼真正的x就是250/1024。
這裡如果你的表情多,就會有很多這種除法運算,整體來說效率不高。
第二就是你用在輸入框或者表情清單下的話你可能就很難做了。
因為輸入框我們如果用ugui的話,他已經幫我們關聯好相關輸入的資訊,我們貌似沒辦法給他增加TextMesh方式來實作圖文混排的效果(如果這個不重要用标記代替也行)
但是緻命的是你可能沒辦法再一個drawcall下用TextMesh來實作表情清單。因為ugui裡面的材質都不支援多材質。
當然如果你說不用ugui或者自己改造,用mesh自己實作也是可以的。但是你就要做很多适配的工作了。
也就衍生出以下說的一種比較适合上面我說的情況的,需要圖文混排,需要文字輸入中帶圖檔,需要清單隻有一個drawcall。
那就是TextMeshPro了。
這個是後面unity引進來的TextMesh的更新版。unity甚至把他接入到了各種text裡面。
用Tmp實作圖文混排就簡單了。
我們用的是spriteasset的方式。
使用<sprite="DefaultSprites" name="Unity">的方式顯示一個表情, sprite是textmeshpro集的命,name是具體的圖檔,也可以用index。
另外textmeshpro集要放在“TextMesh Pro\Resources\Sprite Assets”下(除非你改了他的路徑),改路徑的地方是
如果我們要支援中文或其他語言,我們就修改下fontasset的字型就好:
點選:
選擇這個fontasset,然後修改下面這裡:
一般不需要自己做字型,除非你有特殊字型。
但是我們現在隻有預設的表情
我們當然像要自己的表情,那就需要自己來制作一下表情圖集了。
我用的是TexturePacker來把圖集打出來。但是要注意不要讓他支援旋轉,讓他正常排列就好。
然後在圖集上選擇sprite和spritemode選擇multiple,這樣才能編輯圖檔
選擇sprite editor
這裡注意錨點一定要放在左下角,然後儲存。
然後需要制作具體的fontasset了,右鍵這個圖集:
制作好的圖集放在我們設定的spriteasset的目錄下:
放到這裡就可以在項目中用這些表情。
最終展示效果
這個文本時這樣出來的:
然後其他的展示效果如下:
這裡說以下表情清單需要更改下他們的render queue,讓相同的材質在一個queue下,不同的不要在一個queue下,這樣才能讓他們合批。以下時其中一個示例
好了,對比下一排和兩排的效果,可以看到他們沒有drawcall的增加,我們的需求解決了。
下面是兩排的示例:
但是這裡要注意的是不支援gif,gif圖檔可以用序列幀的方式來播放。建議發gif動畫就單發,不要連着文字一起發,也就是點選gif的表情就發出去把,不讓他帶文字了。