查看: 2618|回复: 3
打印 上一主题 下一主题

[其他] Unity动态字体文字破碎的解决方法(Dynamic Font Broken) 使用Unit...

[复制链接]

2317

主题

54

听众

2万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
20645
精华
62

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2014-9-30 02:27:58 |只看该作者 |倒序浏览

Unity动态字体文字破碎的解决方法(Dynamic Font Broken)

使用Unity的动态字体绘制文字的时候,打开两个ui界面的时候,后面的文字会显示破碎(完全乱掉)。我使用的ui插件是Daikon Forge,由于其label的更新机制问题,最终表现的结果可能比一个文本显示破碎更加糟糕。很可能文本控件会不停的刷新,要打开的新界面也显示不出来。

这个从根本上说,是由于Unity的Dynamic Font实现的不够智能。理论上NGUI也会有这样的问题。只要你使用的是动态字体,并且渲染的文字构多。

NGUI和Daikon Forge内部在绘制文字的时候使用了Unity 的Font,这个就是动态字体。通过RequestCharactersInTexture函数向Font请求更新文字信息,然后使用GetCharacterInfo获取文字信息来渲染。在调用GetCharacterInfo的时候要保证所有文字都通过RequestCharactersInTexture请求过了。

如果请求的时候,Font内部维护的texture不够用了,就会触发textureRebuildCallback的回调,通知外部使用Font的对象,其内部的texture被更新了,外部应该重新刷新。

Unity的Font默认的texture大小是256x256,在纯英文字体的情况下,是完全够用了。但是汉字、日文等东方字体就完全不够了。而之前说的那两个插件的使用方式都是绘制文字的时候请求一段,如果unity的刷新回调触发,则重新刷新所有的文本控件。这样就非常容易出现字体破碎的情况。因为一般情况下我们一次请求的文字不会很多,使用的texture不会超过256x256,unity不会自动扩展texture大小。而我们在回调函数中重新刷新字体的时候,又很容易出现texture不够的情况,这样就触发了另一次刷新回调。于是就会发文本控件显示破碎而且不停刷新的情况。

直到了问题的起因,解决方法也就出来了。只要我们请求的文字足够多,那么unity就会内部自动扩展texture大小,于是就可以避免不停刷新的情况。我准备了2000个汉字的文本,在请求文字信息后,内部texture被扩展成1024x1024大小,这样游戏过程中就基本够用了。如果哪天发现这样也不够的话,再多准备一些汉字,把texture扩展成2048x1024就ok了。

  1. static string chineseTxt = null;  
  2. public UnityEngine.Font baseFont;  
  3.     public void FixBrokenWord()  
  4.     {  
  5.         if (chineseTxt == null) {  
  6.             TextAsset txt = Resources.Load("config/chinese") as TextAsset;  
  7.             chineseTxt = txt.ToString();  
  8.         }  
  9.    
  10.         baseFont.RequestCharactersInTexture(chineseTxt);  
  11.         Texture texture = baseFont.material.mainTexture;    // Font的内部纹理  
  12.         Debug.Log(string.Format("texture:{0}   {1}", texture.width, texture.height);   // 纹理大小  
  13.     }
复制代码

其中baseFont就是NGUI或者是Daikon Forge的文本渲染控件中使用的UnityEngine.Font,在初始化baseFont的时候调用一下FixBrokenWord函数就可以了 (只需要调用一次)。它会读取一个含有常用汉字表的文本(随意从网上的常用字表用copy一下就可以了),然后请求一下这段文本的信息,然后内部纹理就会 自动被扩展。

NGUI】移动设备上使用动态字体Label显示不正确

方法1:

升级Unity到4.3版本以上

方法2:

首先,需要一个文本,这个文本就是你项目的字典(如果没有,自己研究下)
之后,在游戏启动的时候实现以下步骤:
1、载入字典txt,所有的文字放到一个string里面(暂且叫做languageString)
(3.0以前版本)
2、通过全局配置或者其他任何方式,找到你的UIFont变量font(可以在任意的label上直接取得)
3、调用font.dynamicFont.RequestCharactersInTexture(languageString, font.dynamicFontSize, font.dynamicFontStyle)
(3.0(含)以后版本)
2、通过全局配置或者其他任何方式,找到你的动态字体Font变量font
3、调用NGUIText.RequestCharactersInTexture(font, languageString)
应该就可以了。
问题的根本原因不是很了解,但是我想问题应该出现在动态字体创建的texture大小上。
一般问题是出现在切换界面的时候,所以应该是这个时候,如果texture大小不够用,重新调整了texture,导致之前的texture的uv对应不上。

通过上面的方法,在游戏最开始就会创建一个2048*1024大小的texture(我用的是3000多个常用汉字只有不到2M,因为是纯色的图)

所以不会浪费太多内存,也比使用bitmap子图省。
提供一个3.0.7的脚本。之前版本的自己看着改吧。

  1. using UnityEngine;  
  2. using System.Collections;  
  3.    
  4.    
  5. /// <summary>  
  6. /// SZUI dynamic font problem fix.   
  7. /// Usage : attach this to a gameobject or use SZUIDynamicFontProblemFix.DynamicFontProblemFix  
  8. /// </summary>  
  9. public class SZUIDynamicFontProblemFix : MonoBehaviour {  
  10.       
  11.     /// <summary>  
  12.     /// The font. your ttf  
  13.     /// </summary>  
  14.     public Font font;  
  15.       
  16.     /// <summary>  
  17.     /// The text. your language file  
  18.     /// </summary>  
  19.     public TextAsset text;  
  20.       
  21.     private static bool isFixed = false;  
  22.       
  23.     private static SZUIDynamicFontProblemFix inst;  
  24.     private static SZUIDynamicFontProblemFix Inst  
  25.     {  
  26.         get  
  27.         {  
  28.             if (inst == null)  
  29.             {  
  30.                 GameObject go = new GameObject(typeof(SZUIDynamicFontProblemFix).Name);  
  31.                 inst = go.AddComponent<SZUIDynamicFontProblemFix>();  
  32.             }  
  33.             return inst;  
  34.         }  
  35.     }  
  36.       
  37.     void Awake()  
  38.     {  
  39.         if (inst == null)  
  40.         {  
  41.             inst = this;  
  42.         }  
  43.         if (inst != null && inst != this)  
  44.         {  
  45.             Destroy(this.gameObject);  
  46.             return;  
  47.         }  
  48.         DynamicFontProblemFix();  
  49.     }  
  50.       
  51.     public static void DynamicFontProblemFix()  
  52.     {  
  53.         if (!isFixed)  
  54.         {  
  55.             isFixed = true;  
  56.             NGUIText.RequestCharactersInTexture(Inst.font, Inst.text.text);  
  57.         }  
  58.     }  
  59. }
复制代码
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

115

主题

3

听众

5676

积分

高级设计师

Rank: 6Rank: 6

纳金币
7268
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2014-9-30 09:22:31 |只看该作者
Thanks for sharing thí one !
回复

使用道具 举报

0

主题

2

听众

1346

积分

助理设计师

Rank: 4

纳金币
505
精华
0
板凳
发表于 2014-9-30 10:44:44 |只看该作者
好实用   謝謝指导
回复

使用道具 举报

hyui    

1

主题

2

听众

6671

积分

高级设计师

Rank: 6Rank: 6

纳金币
2715
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2014-10-2 05:40:46 |只看该作者
Great article thanks              
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-10 21:22 , Processed in 0.177272 second(s), 32 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部