zoukankan      html  css  js  c++  java
  • 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}:	{1}
    ", 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原来的方法

  • 相关阅读:
    七、Vue Cli+ApiCloud
    六、取消eslint 校验代码
    六、匿名方法
    五、vue中export和export default的使用
    四、Vue CLI-异步请求(axios)
    接口自动化测试(7)
    selenium 封装
    flask 动手写的接口平台
    flask入门篇
    python 自动化接口测试(6)
  • 原文地址:https://www.cnblogs.com/bicker/p/3669176.html
Copyright © 2011-2022 走看看