中文裏帶半角空格致使的Text換行問題[Unity]

0x01 問題

最近策劃反映了個問題,遊戲裏的多行文本會出現提早換行的問題,以下圖所示:佈局

 
文本錯誤地提早換行,致使第一行文本後面有大塊空白區域ui

經過觀察能夠發現,當字符串中帶有半角空格,且半角空格後面的字符串內容超過文本剩餘顯示寬度時,Text組件會將後面的整段文字作換行。這個並非bug,而是Text組件按照拉丁西語的分詞習慣作line break,半角空格至關於分隔符,分隔空格先後的內容,並視之爲單詞。這種分詞規則在西語中是正確的,但用在中文就水土不服了:整段的中文內容,粗暴地按半角空格分紅了3部分,第一行空格後面的大段文字被斷定爲一個單詞,剩餘寬度沒法顯示,就被整個換到了第二行。this

0x02 解決方案v1

稍做思考,嘗試使用中文全角空格替換半角空格,換行正常,也就是說,分詞規則只對半角空格作處理。然而中文全角空格比半角空格要寬,致使文字間隙過大,顯示效果不好。google

0x03 解決方案v2

那有沒有長得跟半角空格同樣,而又不會被底層分詞的字符呢?google一下,找到了答案不換行空格(Non-breaking Space)編碼

咱們平時所使用的空格(即鍵盤Sapce鍵輸出的空格),Unicode編碼爲/u0020,是換行空格(Breaking Space),空格先後的內容是容許自動換行的;與之對應的不換行空格(Non-breaking space),Unicode編碼爲/u00A0,顯示與換行空格同樣,主要用途用於禁止自動換行,在英文中主要用於避免相似(100 KM)這種文字被錯誤地分詞排版成兩行。能夠說,Breaking Space的存在讓西語得以分隔單詞,從而正確地分詞排版,但放在中文裏是多餘的存在,中文沒有單詞概念,不須要作分隔。spa

那這下問題就好解決了,咱們只需在Text組件設置text時,將字符串的換行空格統一更換成不換行空格,就能解決換行錯誤問題。新建一個NonBreakingSpaceTextComponent類,作文本替換處理:code

/* ==============================================================================
 * 功能描述:將Text組件的space(0x0020)替換爲No-break-space(0x00A0),避免中文使用半角空格致使的提早換行問題
 * 創 建 者:shuchangliu
 * ==============================================================================*/

using UnityEngine.UI;
using UnityEngine;

[RequireComponent(typeof(Text))]
public class NonBreakingSpaceTextComponent : MonoBehaviour
{
    public static readonly string no_breaking_space = "\u00A0";

    protected Text text;
    // Use this for initialization
    void Awake ()
    {
        text = this.GetComponent<Text>();
        text.RegisterDirtyVerticesCallback(OnTextChange);
    }

    public void OnTextChange()
    {
        if (text.text.Contains(" "))
        {
            text.text = text.text.Replace(" ", no_breaking_space);
        }
    }

}

將NoBreakingSpaceTextComponent掛在Text組件上,每當Text設置text文字,準備從新繪製Text網格時,NoBreakingSpaceTextComponent會檢查並替換text文字裏的換行空格。
效果如圖所示,Mission Complete!blog

0x04 後記

從這個小問題能夠看出Text的分詞規則是針對西語而言的,對中文分詞支持並很差,好比中文的標點符號不該該出如今行首。若是遊戲對中文排版要求比較高,就要考慮本身動手作Text的佈局實現了。遊戲

相關文章
相關標籤/搜索