NGUI UILabel 文字破碎

来源:互联网 发布:安卓铃声软件 编辑:程序博客网 时间:2024/05/11 11:08

项目使用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 callbackif (!mFontUsage.TryGetValue(mActiveTTF, out usage))mActiveTTF.textureRebuildCallback = OnFontTextureChanged;#if UNITY_FLASHmFontUsage[mActiveTTF] = usage + 1;#elsemFontUsage[mActiveTTF] = ++usage;#endif}}}

DynamicFontBrokenFix 是一个文本,里面存放游戏中所有的字。

转自http://blog.csdn.net/huutu http://www.liveslives.com

意识到 这也是一个优化点,避免多次生成 FontTexture 。

0 0
原创粉丝点击