Unity 场景中动态文字,图文混排,头顶文字等优化方案: HubUI

HubUI优化

问题点:

  1. 不管是使用NGUI还是UGUI,控件的刷新都会导致面板的重绘制。如果面板已经做过优化,这个开销就会小一-些
  2. 角色显示或隐藏,以及HUD的显示或隐藏,都需要调用SetActive函数, 而这个函数有一定开销, 对性能会产生影响,尤其在调用频繁的时候。(一般进行移出场景方式处理)
  3. HUD的频繁创建和释放,特别是伤害数字,会导致垃圾回收(Garbage Collect)频繁
  4. 如果HUD使用对象池,大量伤害数字对象的激活与释放,也会有很大的开销

Canvas.SendWillRenderCanvases 如果占用比较高,那就说明Canvas消耗性能较高。

Text文字显示原理

  • CPU先是加载字库文件(通常是ttf) 然后在内存中生成对应文字的位图数据,再将文字的位图数据更新到GPU支持的纹理中,并记录下该文字在纹理中的坐标与UV信息,进而构造这个字符的三角形数据,最后将这些三角形提交到GPU进行渲染

这里涉及到一一个文字的缓存算法,因为无法将所有的文字预先生成,那样开销太大,基本上是不可能的:

在Unty中字体对应的对象是font,它在首次请求文字的纹理缓存时,会生成一个256x256文小的
贴图,当这个贴图中装不下新的文字时,会扩大这个贴图的大小,最大可以到1024x1024,同时
通知上层"贴图变化了“(通过TextureRebulldcallback委托通知)。
如果当前贴图已经满了,又有新的文字请求时,font同样会通知上层贴图变化了。这样就会导致所
有文字重新绘制。Unity这里其实是在愉懒,它只是简单地通知上层“你们所占的位置都已经无效
了,请重新排队申请。“因为这时有可能很多文字并不渲染了,所以这样做并没有什么问题,
说到底,文字与图片其实都是纹理贴图,都是通过四边形(两个三角形)来注染,它们对于GPU来说 是没有区别的。

优化方案:自建Mesh(不采用Unity的文字和图片)

建立图元信息(HUDCharInfo)数据结构:

  • 区分是文字或图片,用一-个bool变量表示 字符内容用char表示 (string 在堆上,有GC开销)

  • 图片ID,用int来表示(之所以不用string,是因为string的开销较大)d)

  • 纹理ID或名字

  • UV信息 (文字的4个顶点在UV中的位置)

  • 颜色信息

  • 相对坐标(混排的关键) 相对于HUD面板的坐标

  • Unity 场景中动态文字,图文混排,头顶文字等优化方案: HubUI_第1张图片

  • 其他

  • 注意: HudVertex的类名实际是抽象的顶点,或者可称之为“图元"

从文本获得图元信息:文本解析

自己定义文本格式,然后进行解析

  • 颜色表示:[f0000]
  • 图片表示:一张图片
  • 表情动画:多张图片构成帧动画
  • 从文本获得图元信息 文本解析 超链接 占位符(空格) 转义字符

特效

  • 描边: 一个面片 上下左右偏移绘制多次
  • 阴影: 往右下角偏移绘制多次
  • 渐变: 顶点颜色插值 GPU本身具备顶点颜色插值功能

消除GC

使用BatterList 替代C# List

大批量文字渲染(头顶和伤害飘字)

  • 将多个HUD面板合批
  • 使用对象池
  • 分成静态UI和动态UI两个图元列表 动静分离与转换规则:
    • 所有对象首次添加时,默认是运动的(也可是静止的)
    • 对象移动,就记录一下移动时间 (标记), 并通知所属Mesh刷新
      每隔一定时间(如:2秒),扫描所有对象
    • 如果对象在静止批,对象有移动,就从静止批移除,添加到动态批
    • 如果对象在动态批,对象没有移动,就从动态批移除,添加到静态批
    • 不管是动态批,还是静态批,只要所属子对象有移动,就需要更新整个Mesh;没有变化,就不用更新。当然,也可以在对象移动时,立即从静止批转换到动态批,这个实际优化策略要结合自身项目来分析

正确处理3D环境下UI前后关系:

  • 半透明必须保证从后到前绘制
  • 通过CommandBuffer手动提交(绕过引擎)
  • 如何保证尽量合批渲染:
    • 一次绘制传入多个纹理 (图片、表情、文字)
    • 为文字图片制作动态图集
    • 在一个Shader和一个Material中进行图文混排绘制

你可能感兴趣的:(Unity,unity,游戏开发)