LayaAir引擎與IDE提供了豐富的文本組件,適用於各種文本應用場景。發現一些用LayaAir引擎開發過項目的開發者,也對引擎與IDE的各個文本組件的區分不是太了解。所以本篇分別就IDE中的顯示文本組件、HTML文本組件、位圖文本組件、可輸入文本組件,這幾個類型的組件進行介紹,讓大家全面了解一下LayaAir引擎的各個文本組件。
一、顯示文本組件顯示文本就是只能看,不能編輯修改的基礎文本。LayaAirIDE中提供了Text、FillText、Label這三種基礎的顯示文本組件。
1.1、文本的底層渲染機制LayaAir引擎在文本的底層渲染上,有兩種方式。
分別是Text文本類的文本統一提交方式,和Graphics類的fillText文本單字符繪製提交方式。
如果採用了Text文本,那每一個Text文本對象中的文本字符會一起形成小圖集提交到大圖合集中,比如遊戲中某個文本對象有300字,其中一個字符發生改變,也會對該文本對象的300字整段文本圖集重新提到大圖合集中。
又假如,在一個劇情遊戲中,兩人在對話。那其中一個文本對象,要不斷的重新取值和賦值操作,使得該文本對象的顯示內容頻繁發生改變。此時,Text文本對象,就會不斷的向大圖合集進行文本圖集的提交,佔滿大圖集後,又需要創建一個新的圖集繼續提交,而不用的舊圖集,如果沒達到GC條件,也會一直存在,所以如果此次查看內存佔用統計信息,就可以看到會一直在漲內存,直到GC條件達到之後,才會被銷毀。並且GC在清空垃圾內存的時候,還有可能會導致瞬間的卡頓。
而採用Graphics類的fillText文本繪製,則是按單個字符向大圖合集中進行提交,並且大圖合集中已經存在的字符不會重複提交。所以對於圖集的利用率比較好,即便是發生文本改變的時候,也不會向Text文本那樣,創建很多垃圾圖集。
這樣看來,是不是fillText就是最好用的呢?
如果文本不需要改變,那按單字提交圖集的效率是不如一次性直接提交的。
所以,我們還是要看文本的類型,對應文本使用時的類型,選用相應的引擎API,才會更好。
1.2、靜態文本與動態文本基於上一小節的文本渲染提交的機制,以及文本僅用於展示或用於交互的區別,我們分成兩種概念,就是把僅用於顯示,文本內容無需改變的文本叫靜態文本。對於文本內容需要改變的文本叫動態文本。
Text和Label都屬於處理靜態文本的類,它們都是把文本的每次改動都統一提交大圖集的渲染機制。
fillText、fillBorderText、strokeText等,都是Graphics類中用於單字符提交的文本繪製方法。
在LayaAirIDE中,Text和Label屬於靜態文本組件,FillText屬於動態文本組件。而LayaAir引擎中Graphics類的fillBorderText、strokeText等文本繪製方法,在IDE中是沒有封裝為組件的,需要在項目代碼中直接使用引擎的API。
1.3、不同的文本組件使用區別與選擇如果我們已經理解了什麼是靜態文本和動態文本,那使用起來的選擇就比較簡單了,例如,一些導航和標籤按鈕等,他在UI上完全沒有必要進行改變,完全可以使用靜態文本。文字劇情和任務等,就需要動態文本了。
那靜態文本組件有Text和Label兩種,那是怎麼選擇呢。
其中Text是最基礎的文本組件,他直接繼承於Sprite,而Label繼承於UIComponent再往上才是Sprite,從原理上,路徑越短,性能自然越好。所以,比較簡單的文本,當Text可以滿足時,原則上優先使用Text,而Label由於屬性非常豐富,適用於相對布局等等Text無法滿足的應用場景。
而對於FillText組件,我們不僅要了解它的優勢,也要了解他的不足。FillText文本由於是引擎自己繪製的,目前只適用於中英文等主流國家語言,對於泰國語、阿拉伯語等複雜的語言,顯示可能會有異常。所以對於這些排版複雜的國際語言遊戲,那只能是採用靜態文本組件的系統字或者是位圖字,儘可能減少文本動態修改的產品需求。
1.4、使用時要注意的靜態的文本優先使用Text組件,因為只顯示靜態文本的時候性能最好。動態文本優先使用FillText,除非是國際化等需求不能滿足的時候。
靜態文本,對於有相對布局等複雜需求時,Label組件的功能比較強大。
具體的屬性使用特別簡單,IDE中的屬性面板中都有說明,不需要寫代碼也可以直接運行查看效果,另外在官網的文檔和視頻教學中,對於每個組件的使用與屬性效果也都有介紹,就不逐一介紹了,重點介紹一下FillText中font屬性與其它幾個文本font屬性區別。
在Text與Label中,font僅僅是指系統字體,例如該文本是Microsoft YaHei或是Arial,選擇或者輸入對應的字體就可以。而FillText中,font是字體與字體大小的設置值,也可以把所有相關的文本樣式(大小、字體、斜體、加粗)也在這裡指定。
例如,當值為 60px simHei ,是將文本大小設置為60像素大小,採用simHei字體。如下圖所示:
值為60px simHei italic 增加了斜體效果。如下圖所示:
值為bold 60px simHei italic 增加了文本加粗效果。如下圖所示:
Tips:
二、位圖顯示文本組件位圖顯示文本,是一種基於位圖的文本,雖然顯示的是文本的內容,其本質還是位圖。通常用於系統上不通用的字體或者美術設計的個性字體,通過位圖的方式可以保障字體的兼容性與美觀。對於文本效果與位置要求比較嚴格的遊戲,建議採用位圖文本。
普通的文本,在不同運行環境下,可能會存在像素級的位置偏移。比如Chrome低版本和高版本也存在位置偏移。所以要求高的靜態UI文本,可以採用位圖顯示文本。
位圖文本適用於文本單字總量不大需求,常用於第X關,X連擊等標題性文本。對於文字劇情這種遊戲,就不太適合。
1、FontClip字體剪輯組件FontClip組件是LayaAir基於等份切割原理將完整的位圖切分成一個個獨立的文本單元,然後任意剪輯拼接起來。效果如下圖所示,
上圖的0-9是美術原圖效果的展示,999是FontClip組件效果。
在上圖右側的屬性面板上,sheet值對應位圖的9個數字,此時數字要完全對應起來,因為這個值不僅是引擎切割份數的參考依據,更是文本映射關係。只有對應起來,屬性value中輸入什麼值就會顯示什麼值,例如上圖的999。並且FontClip組件還可以控制切割後的位圖文本間距等效果。
如果位圖文本不是數字,是字母或者中文等,內容比較多,美術出圖時也可以將文本多行排行,但是每個文本之間必須要等高等寬等距進行排列。此時用於映射的sheet值,要在每行結束位置加一個空格,讓引擎知道這個位圖文本是多行排行的。效果如下圖所示:
通過上圖,我們可以看出sheet屬性值鼠牛虎兔龍蛇馬羊 猴雞狗豬年快樂對應了位圖上的文本,並且在羊後加了一個空格,此時就可以在value輸入位圖上的文本字符了,而且我們還展示了豎向排版的效果,說明切割後的文本還可以排版控制的。
如果細心的開發者會發現,位圖字是繁體的,sheet的值是簡體的,但展示的效果並沒有受到影響。這是因為sheet值只是起到映射關係的作用,哪怕這十二生肖的文本對應的就是生肖圖片,那也會顯示對應的生肖圖。但是映射的文本與位圖上的數量一定要是完整的,否則切片的份數不對,就會導致位圖剪輯後的顯示錯誤。
最後再說一下空格,當前的FontClip組件是面向單行的整句文本,是不支持空格的,如果在Value值裡加一個空格,我們可以從上圖中看出,空出一個完整的文本位置。其實不止是空格,所有sheet值中不存在的文本,都會以空的完整字符佔位。
未來的版本,有計劃支持空格與換行
2、BitmapFont位圖字體類通常FontClip已經可以滿足關卡、特效等單行位圖文本的需求。如果有特殊情況,就是想要空格,那也可以通過BitmapFont位圖字體類來實現,在LayaAir 2.x IDE裡,當前的版本還不能可視化使用BitmapFont位圖字體,可以通過代碼調用實現,具體的使用方式,要描述的內容太多,就不在這裡展開了,大家可以查看官網的位圖字體技術文檔。
BitmapFont不僅可以滿足位圖空格的需求,當使用那些需要在系統安裝的商業或者免費字體時(例如:漢鼎字體、思源字體、站酷字體等等),也可以很方便的通過Bitmap Font Generator這個第三方的免費工具導出,然後在LayaAir中直接使用。
Tips:
Bitmap Font Generator 只有windows版,對於沒有windows系統的,複雜度不高的需求,儘可能通過FontClip實現。
三、HTML文本組件HTML文本是用於圖文混排的文本組件,組件名為HTMLDivElement。該組件通常用於聊天室等動態文本場景需求,所以引擎也是採單字符提交圖集的模式,與Graphics的文本繪製有些類似,但又不太一樣,因為繪製採用的是系統字,並支持常見的HTML標籤。
目前引擎支持的常見HTML標籤如下:
(點擊查看大圖)
具體到style標籤的屬性支持如下:
(點擊查看大圖)
下圖的代碼是運用的示例代碼,
(點擊查看大圖)
當我們將以上代碼複製到HTMLDivElement組件的innerHTML屬性裡,運行效果如下圖所示。
四、可輸入文本組件可輸入文本組件為單行輸入組件TextInput和多行文本域組件TextArea。
從組件名字其實上就可以看出區別,
一個是不能換行,用於單行輸入。比如註冊信息上的那些單行輸入框用TextInput。
另一個是能換行的多行文本組件TextArea,比如個人簡介,備註說明等等。而且TextArea文本組件支持右側的垂直滾動條,和底部的水平滾動條。
由於可輸入文本組件的用法比較簡單,組件也比較容易理解。這裡就不詳細介紹了,具體在使用過程中,可以看提示進行嘗試或者直接看對應的組件屬性說明文檔。
五、關於文本的性能優化1、靜態顯示文本的優化靜態顯示文本,上文介紹過,分別是Text與Label組件。
這兩個組件,如果都是比較簡單的單行文本,並且除了文本內容發生變化外,不對文本的屬性(例如大小、顏色、粗細、斜體、對齊等等)作出任何改變的話。那我們可以使用changeText()來替換文本,這個方法會跳過排版直接修改該文本繪製的最後一條指令,從而優化了渲染效率。
示例代碼如下:
this.text.text="原text文本";
Laya.stage.addChild(this.text);
//不優化的寫法是:this.text.text="替換的text文本";
this.text.changeText("替換的text文本");
2、儘可能使用對應的文本組件每個不同的組件都是有自己獨特的作用,所以一定要充分了解組件的作用,對應特點來使用。
上文中也講到過,靜態顯示文本Text組件的性能是最好的,所以,在項目開發時,能用Text儘可能要用Text組件。當Text組件不滿足的時候再用Label。
對於無需改變內容的靜態文本,當文本組件節點較多時,我們可以開啟cacheAs,設置normal可以優化節點數,設置bitmap可以優化DrawCall數。
而當文本內容需要改變時,哪怕只改變一個字符,如果FillText可以滿足需求的話,那儘可能優先使用FillText文本組件。FillText不能滿足時,其次考慮位圖文本組件是否可以滿足,最後再考慮靜態文本組件。
3、儘可能避免使用文本描邊在運行時,設置了描邊的文本比沒有描邊的文本多調用一次繪圖指令。此時,文本對CPU的使用量和文本的數量成正比。因此,儘量使用替代方案來完成同樣的需求。例如,字符量較少的時候,可以使用位圖文本。
4、被文本打斷的DrawCall優化在2D的UI布局時,如果開發者將文本與其它UI節點混合排列,那麼必然會打斷圖集的合併渲染,增加DrawCall數量,產生不必要的性能開銷。所以,有兩個方案來優化。
一是,LayaAir IDE編輯布局時,將所有文本組件在節點中順序排列,不要與其它UI組件穿插。如下圖所示:
二是,LayaAir IDE中的組件中有一個drawCallOptimize屬性,我們為所有文本的父級節點drawCallOptimize屬性設置true值。當這樣設置之後,引擎會自動啟用文本合併優化,將所有的文本提取到最上層,而開發者無需再刻意調整圖集資源和文本的排序,即可實現drawCall自動優化的目標,而且優化的更加乾脆徹底。
需要提醒的是,drawCallOptimize優化方案由於會自動將文本提升顯示層級,不適用於必須要將文本半遮擋的特殊需求。當然,絕大多數情況下文本是要處於全文顯示的,如果有全隱藏的情況,可以直接設置隱藏屬性。所以,建議開發者開啟該優化方案。
引擎版本更新說明: