NGUI UILabel 文字破碎
Posted _Captain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NGUI UILabel 文字破碎相关的知识,希望对你有一定的参考价值。
项目使用NGUI,最近碰到 Loading界面的提示文字破碎的Bug。
参考了以下文章
http://blog.csdn.net/langresser_king/article/details/22095235
转自http://blog.csdn.net/huutu http://www.liveslives.com
下面先来了解一下为什么会出现这种问题。
需要了解的是 NGUI的UILabel使用的是Unity 提供的Font 来作为字体的输入。
Unity对字体的生成是很节约的,这是很正常的,引擎应该都是这样。
(1) 在Loading界面的 UILabel 上显示 加载中 这三个字,那么Unity就会生成这三个字的纹理,128x128 的FontTexture应该够了。然后UILabel根据Font 去取每个字的图形。
(2)然后 再打开一个界面,而这个界面上有很多字时,128x128的FontTexture 就不够了,Unity会产生一张新的FontTexture,并且扔出一个回调。
(3)然后 NGUI的UILabel中处理这个回调,遍历所有UILabel,把UILabel的内容全部Push到Font里面去生成新的文字图形到FontTexture。
static BetterList<UILabel> mList = new BetterList<UILabel>();
protected override void OnInit ()
base.OnInit();
mList.Add(this);
SetActiveFont(trueTypeFont);
//每次新建一个UILabel,都会读取UILabel上面的内容,在FontTexture上添加一块字体纹理。当FontTexture超过了原来的大小时,就会抛弃原来的FontTexture,用一个新的FontTexture,然后遍历所有的UILabel,往新的FontTexture上添加字体纹理。
static void OnFontTextureChanged ()
for (int i = 0; i < mList.size; ++i)
UILabel lbl = mList[i];
if (lbl != null)
Font fnt = lbl.trueTypeFont;
if (fnt != null)
fnt.RequestCharactersInTexture(lbl.mText, lbl.mPrintedSize, lbl.mFontStyle);
//这段代码让UILabel重新读取UV 重新渲染,下一帧文字就是正常的了
for (int i = 0; i < mList.size; ++i)
UILabel lbl = mList[i];
if (lbl != null)
Font fnt = lbl.trueTypeFont;
if (fnt != null)
lbl.RemoveFromPanel();
lbl.CreatePanel();
(4)最后UILabel被重新渲染。
字体破碎的情况,就出现在 (2) 这里,UILabel 已经在渲染 进行时,然后Unity生成了一个新的FontTexture,这样 当前帧 显示出来的图形肯定是有问题的。
那么解决方法就是,在一开始的时候,就给Font 足够多的文字,包括游戏里面所有的字都Push进去,这样以后游戏里面都不用再Push了,FontTexture就可以用到老。
转自http://blog.csdn.net/huutu http://www.liveslives.com
在UILabel 中新增函数
private static void DynamicFontBrokenFix(Font fnt)
if(fnt==null)
return;
if(fnt.characterInfo.Length<500)
string tmpStr = Resources.Load<TextAsset>("DynamicFontBrokenFix").text;
fnt.RequestCharactersInTexture(tmpStr, 32);
然后在设置字体的时候调用
protected void SetActiveFont (Font fnt)
if (mActiveTTF != fnt)
if (mActiveTTF != null)
int usage;
if (mFontUsage.TryGetValue(mActiveTTF, out usage))
usage = Mathf.Max(0, --usage);
if (usage == 0)
mActiveTTF.textureRebuildCallback = null;
mFontUsage.Remove(mActiveTTF);
else mFontUsage[mActiveTTF] = usage;
else mActiveTTF.textureRebuildCallback = null;
mActiveTTF = fnt;
DynamicFontBrokenFix(mActiveTTF);
if (mActiveTTF != null)
int usage = 0;
// Font hasn't been used yet? Register a change delegate callback
if (!mFontUsage.TryGetValue(mActiveTTF, out usage))
mActiveTTF.textureRebuildCallback = OnFontTextureChanged;
#if UNITY_FLASH
mFontUsage[mActiveTTF] = usage + 1;
#else
mFontUsage[mActiveTTF] = ++usage;
#endif
DynamicFontBrokenFix 是一个文本,里面存放游戏中所有的字。
转自http://blog.csdn.net/huutu http://www.liveslives.com
意识到 这也是一个优化点,避免多次生成 FontTexture 。
以上是关于NGUI UILabel 文字破碎的主要内容,如果未能解决你的问题,请参考以下文章