Unity動態字體在手機上出現字體丟失問題解決


      在我們游戲的開發過程中,在部分手機上運行游戲的時候,出現了字體丟失的問題,出問題的手機似乎用的都是高通芯片。

      使用的unity是4.2.0版本,ngui是3.4.9版本。

      在unity的論壇及unity answer中尋找問題的原因及解決辦法許久未果,后來在csdn里偶然找到一篇博文,里面講到的問題出現的原因以及相應的解決辦法。根據文中的辦法,我試驗后證實的確可以解決問題。

      博文地址:http://blog.csdn.net/langresser_king/article/details/22095235

      在unity editor中可以看到,使用的字體ttf文件下,會生成一個texture文件及material文件。當需要顯示文字的時候,會通過RequestCharactersInTexture函數向Font請求更新文字信息,然后使用GetCharacterInfo獲取文字信息來渲 染。在調用GetCharacterInfo的時候要保證所有文字都通過RequestCharactersInTexture請求過了。

      如果請求的時候,Font內部維護的texture不夠用了,就會觸發textureRebuildCallback的回調,通知外部使用Font的對象,其內部的texture被更新了,外部應該重新刷新。

      原文中提到,是因為texture的大小沒有被及時擴大而導致字體丟失。但是在我多次測試之后,猜測問題的原因應該不是這一點。因為在PC上或者其他手機上並不會出現字體丟失的問題,問題並不是出現在unity動態字體的策略上。但是這個問題是可以通過在最開始的時候使用方法將texture尺寸擴大的做法來規避掉。真正的原因實在未能找出。

      下面提供規避掉這個問題的做法,供參考:

private void FixBrokenWord()
    {
        if (chineseText == null)
        {
            var wordFileRes = ResMngr.GetInstance().LoadSync("ui", "UI/font/chineseWords");
            if (wordFileRes != null)
            {
                TextAsset worldFile = wordFileRes.GetObject() as TextAsset;
                chineseText = worldFile.text;
                Debug.Log(string.Format("chinese font size: {0}", chineseText.Length));
            }
        }
        var fontRes = ResMngr.GetInstance().LoadSync("ui", "UI/font/font_FZCYJW_28");
        if (fontRes != null)
        {
            GameObject fontPrefab = fontRes.GetObject() as GameObject;
            baseFont = fontPrefab.GetComponent<UIFont>().dynamicFont;
        }
        if (baseFont != null)
        {
            baseFont.RequestCharactersInTexture(chineseText, 28);
            Texture texture = baseFont.material.mainTexture;
            Debug.Log(string.Format("Texture size: {0}, {1}", texture.width, texture.height));
        }
        fontRes = ResMngr.GetInstance().LoadSync("ui", "UI/font/font_STXINGKA_54");
        if (fontRes != null)
        {
            GameObject fontPrefab = fontRes.GetObject() as GameObject;
            baseFont = fontPrefab.GetComponent<UIFont>().dynamicFont;
        }
        if (baseFont != null)
        {
            baseFont.RequestCharactersInTexture(chineseText, 54);
            Texture texture = baseFont.material.mainTexture;
            Debug.Log(string.Format("Texture size: {0}, {1}", texture.width, texture.height));
        }
    }

這個可以在游戲開始的時候調用一次,通過RequestCharactersInTexture函數,傳入一個較大的字符串來使得unity擴大texture的大小。

另外如果游戲里所使用到的文字都是通過配置表來加入的,附送一個函數,來統計游戲中所有用到的文字,並生成上一函數需要的文字文本文件。

[MenuItem("Custom/Statistic Words")]
    public static void StatisticWords()
    {
        //用於統計字符
        Dictionary<char, int> wordMap = new Dictionary<char, int>();
        string[] txtFiles = Directory.GetFiles("Assets/Resources/Data/", "*.txt");
        for (int i = 0; i < txtFiles.Length; ++i)
        {
            Debug.Log("> open file: " + txtFiles[i]);
            string textContent = File.ReadAllText(txtFiles[i], System.Text.Encoding.UTF8);
            Debug.Log("> file " + txtFiles[i] + " size: " + textContent.Length);
            for (int wordIndex = 0; wordIndex < textContent.Length; ++wordIndex)
            {
                int useCount = 0;
                wordMap.TryGetValue(textContent[wordIndex], out useCount);
                wordMap[textContent[wordIndex]] = useCount + 1;
            }
        }
        
        Dictionary<char, int> sortedWordMap = new Dictionary<char, int>();
        sortedWordMap = (from entry in wordMap
                         orderby entry.Value descending
                         select entry).ToDictionary(pair => pair.Key, pair => pair.Value);
        IEnumerator enumerator = sortedWordMap.Keys.GetEnumerator();
        StringBuilder sBuilder = new StringBuilder();
        
        while (enumerator.MoveNext())
        {
            sBuilder.Append(string.Format("{0}:\t{1}\n", enumerator.Current,
                sortedWordMap[(char)enumerator.Current]));
        }
        File.WriteAllText("Assets/Resources/UI/Font/sortedChineseWords.txt",
            sBuilder.ToString(), Encoding.UTF8);
        sBuilder = new StringBuilder();
        enumerator = sortedWordMap.Keys.GetEnumerator();
        int wordCount = 0;
        while (enumerator.MoveNext()&&wordCount<800)
        {
            wordCount++;
            sBuilder.Append(enumerator.Current);
        }
        Debug.Log("> Total word: " + sBuilder.ToString().Length);
        File.WriteAllText("Assets/Resources/UI/Font/chineseWords.txt", sBuilder.ToString(),
            Encoding.UTF8);
    }

 如果有知道unity這個丟失字體真正原因的,歡迎告知。

 

ps: 上文中從Resources目錄里取得文本文件及font文件,用的是我們自己實現的ResMngr,可自行更換成unity原來的方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM