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 文字破碎的主要内容,如果未能解决你的问题,请参考以下文章

NGUI中UILabel用省略号替换超出显示区域的内容

关于Unity中的NGUI字体

NGUI -- UILabel

Unity-NGUI-UILable文字超链接

MGD 调试 Lives2d 文字破碎问题 (MX2)

旁白朗读标签的文字两次