概要
表现优化
纹理优化
在游戏中,纹理是占用大量内存和显存的重要资源。为了优化性能,我们可以考虑以下措施:
压缩纹理:使用适当的纹理压缩格式,如ETC、ASTC或BC等,以减少纹理占用的内存和显存。
减小纹理尺寸:根据实际需求,将纹理的分辨率调整到合适的大小,避免使用过大的纹理。
使用纹理压缩工具:借助工具对纹理进行压缩,以减小纹理文件的大小。
程序圆角
在UI设计中,常常需要使用圆角效果来增加界面的美观度。为了提高性能,我们可以考虑以下改进:
从Vertex FilletImage到Alpha FilletImage的升级:使用Alpha FilletImage可以在渲染时更高效地实现圆角效果,减少额外的顶点计算开销。
多语言跑马效果
多语言跑马效果是指在游戏中显示多种语言的滚动文字效果。为了优化表现,我们可以采取以下措施:
动态Drawcall分配:通过动态分配Drawcall,只在需要更新的时候才重新绘制跑马文字,减少不必要的绘制开销。
UI亮边优化
UI亮边效果可以增加UI元素的可视性和立体感。为了优化性能,我们可以考虑以下改进:
使用Shader进行亮边效果:通过编写自定义Shader,在渲染过程中实现亮边效果,减少额外的渲染开销。
瀑布流效果(无限滚动ScrollRect)
瀑布流效果是指在有限的空间内展示大量内容,并支持无限滚动的功能。为了提高性能,我们可以采取以下措施:
数据预处理和封面延迟加载队列:在滚动过程中,提前加载下一页的数据,并延迟加载封面图片,减少网络交互的频率,提高滚动的流畅性。
Text->TMP
Text组件是Unity中常用的UI文本显示组件,但在性能方面存在一些问题。为了优化性能,我们可以考虑以下改进:
使用TextMeshPro(TMP):TextMeshPro是Unity的一个高性能文本组件,相比于Text组件,它具有更好的性能和功能,可以提供更好的文本显示效果。
性能优化
程序圆角从Vertex FilletImage到Alpha FilletImage升级
程序圆角效果的优化已在表现优化部分进行了说明。
跑马组件的动态Drawcall分配
跑马组件的动态Drawcall分配可以通过以下方式进行优化:
使用对象池:通过对象池管理跑马组件的创建和回收,避免频繁的创建和销毁操作,减少性能开销。
批量更新:将多个跑马组件的更新操作合并为一个批量更新,减少Drawcall的数量。
瀑布流之数据预处理和封面延迟加载队列降低网络交互
瀑布流效果的数据预处理和封面延迟加载队列已在表现优化部分进行了说明。
TMP多语言问题及备用字库导致的性能问题分析及优化
在使用TextMeshPro组件进行多语言显示时,可能会遇到性能问题。为了优化性能,我们可以考虑以下改进:
字体子集化:根据实际使用的字符集,将字体进行子集化处理,减少字体文件的大小和加载时间。
字体缓存:对常用的字体进行缓存,避免重复加载和创建字体资源。
CurvedUI性能问题及JobSystem多线程加持
CurvedUI是一个用于创建弯曲UI效果的插件,但在性能方面可能存在一些问题。为了优化性能,我们可以考虑以下改进:
使用JobSystem进行多线程处理:将CurvedUI的计算任务分配给多个线程进行并行处理,提高计算效率和渲染性能。
减少顶点数量:通过减少CurvedUI的顶点数量,降低渲染开销。
以上是关于Unity优化的需求文档,包括表现优化和性能优化的内容。通过这些优化措施,我们可以提高游戏的性能和用户体验。
基础性能优化:
纹理处理
降低最大尺寸
降低最大大小,这个过程是无损的,可以快速减少纹理内存。不需要读写操作的纹理,取消勾选Read/Write选项,UI纹理避免使用MipMaps
使用压缩格式。
将原先ETC压缩格式转变为ASTC;ASTC由于出色的压缩率,更接近原图的画质,适应更多平台而成为首选的纹理压缩格式。因此,只要可能,尽量使用ASTC。除非部分古老的设备,无法支持ASTC,才考虑使用ETC、PVRTC等纹理压缩格式。(https://www.cnblogs.com/timlly/p/15546797.html#12414-adaptive-scalable-texture-compression)
尽量使用Mipmaps。
纹理Mipmaps提供提升内存占用来达到降低采样纹理时的数据量,从而降低带宽,提升缓冲命中率,同时还能提升画质效果。鱼和熊掌皆可得,何乐而不为?具体地说表现在以下方面:
1、极大地提高纹理缓存效率来提高图形渲染性能,特别是在强烈缩小的情况下,纹理数据更有可能装在Tile Memory。
2、通过减少不使用mipmapping的纹理采样不足而引起的走样来提高图像质量。但是,使用Mipmaps会提升33%的内存占用。
以下情况需要避免使用:
1、过滤不能被合理地应用,例如对于包含非图像数据的纹理(索引或深度纹理)。
2、永远不会缩小的纹理,比如UI元素,其中texel总是一对一地映射到像素。
尺寸保持2的N次方。
尽管目前的图形API都已经支持非2N的次方尺寸(NPOT)的纹理,但有充分的理由建议保持纹理尺寸在2的N次方(POT):
在大多数情况下,POT纹理应该比NPOT纹理更受青睐,因为这为硬件和驱动程序的优化工作提供了最好的机会。(例如纹理压缩、Mimaps生成、缓存行对齐等)
3、保证长和宽都是32像素倍数的纹理,以便纹理上传可以让硬件优化。
最小化纹理尺寸。
最小化纹理位深。
最小化纹理组件数量。
利用纹理通道打包多张贴图。例如将材质的粗糙度、高光度、金属度、AO等贴图打包到同一张纹理的RGBA通道上。
Launcher中的其他性能优化
1、程序圆角:
代码切圆角
重写Graphic类的OnPopulateMesh(VertexHelper vh)
主要思路就是将图片分割成左中右三个矩形和四个角,然后再对四个角进行三角分割,优点是相较于UGUI传统的Mask圆角少暂用一个DrawCall(详细参考文章:https://www.tapd.cn/51810242/markdown_wikis/show/#1151810242001000139和https://zhuanlan.zhihu.com/p/662841521)缺点也很明显,需要圆角越平滑,需要的顶点就会越多,三角面也就越多,如果有大量图片需要程序圆角,就会造成性能开销。
顾后期又做了进一步的优化,使用UGUI系统Shader在frag片元着色函数中对圆角区域外的像素Alpha值赋0实现图片圆角,这样就不改变图片原有三角结构,不增加顶点,不会造成性能开销问题。
//左下角
if (x < r && y < r)
{
arc_size = (x - r) * (x - r) + (y - r) * (y - r);
if (arc_size > r * r)
color.a = 0;
}
//左上角
if (x < r && y >(height - r))
{
arc_size = (x - r) * (x - r) + (y - (height - r)) * (y - (height - r));
if (arc_size > r * r)
color.a = 0;
}
//右下角
if (x > (width - r) && y < r)
{
arc_size = (x - (width - r)) * (x - (width - r)) + (y - r) * (y - r);
if (arc_size > r * r)
color.a = 0;
}
//右上角
if (x > (width - r) && y > (height - r))
{
arc_size = (x - (width - r)) * (x - (width - r)) + (y - (height - r)) * (y - (height - r));
if (arc_size > r * r)
color.a = 0;
}
2.跑马优化
传统跑马效果
float length = GlobalVariable.CalculateLengthOfText(mTextComponent);
mTextComponent.rectTransform.anchoredPosition = Vector3.zero;
overLength = length > widgetsize;
if (overLength)
{
if (image != null) image.enabled = true;
stripedString = StripLengthWithSuffix(mText, widgetsize);
mTextComponent.text = stripedString;
mTextComponent.rectTransform.sizeDelta = new Vector2(widgetsize, mTextComponent.rectTransform.sizeDelta.y);
}
else
{
if (image != null) image.enabled = false;
mTextComponent.rectTransform.sizeDelta = new Vector2(length, mTextComponent.rectTransform.sizeDelta.y);
mTextComponent.rectTransform.anchoredPosition = Vector2.zero;
}
4、瀑布流
对象池:
对象池(Object Pool)是一种用于存储和维护多个可重用对象实例的设计模式。在对象池中,一些预先创建好的对象被存储起来,当需要使用对象时,直接从对象池中取出一个空闲的对象,使用完毕后再将其放回池中,而不是创建新的对象。这样可以减少对象的创建和销毁操作,提高系统的性能。
对象池可以用于提高系统的性能,特别是在频繁地创建和销毁对象的场景下,如网络连接池、线程池等。通过重复利用已创建的对象,可以避免不必要的内存分配和回收开销,节约系统资源。
对象池的实现可以采用不同的方式,如使用链表、队列或数组等数据结构存储对象实例。当需要获取一个对象时,首先检查池中是否有空闲的对象,如果有,则直接返回一个空闲对象;如果没有,则根据需求动态创建一个新对象并返回。
需要注意的是,对象池的大小是有限的,当池中的对象都被使用时,如果再次需要对象,可能需要等待其他对象被释放。在设计对象池时,需要根据实际需求合理设置池的大小,避免出现过多的等待和资源浪费。
数据预加载:
数据预加载是指在页面加载过程中,提前加载和缓存页面所需要的数据,以提高页面加载速度和用户体验。通常,在用户访问页面之前,预加载就已经开始进行,使得用户在访问页面时,能够快速获取所需的数据,减少等待时间和数据加载时间。
数据预加载的目的是为了减少页面加载时间和提高用户体验。通过提前加载数据,可以避免在用户访问页面时,才开始加载数据的延迟,减少等待时间,提高页面加载速度。预加载也可以帮助减少页面闪烁和加载中的空白现象,使用户可以更快地浏览网页内容。
数据预加载需要根据具体的页面和应用场景进行调整和优化。需要考虑的因素包括页面的大小、数据的大小和复杂度、用户的网络环境等。在进行数据预加载时,需要权衡数据的大小和加载时间,确保页面加载的同时,不会过度占用用户的带宽和资源。
总之,数据预加载是一种优化页面加载速度和用户体验的方法,通过提前加载和缓存页面所需的数据,减少等待时间和数据加载时间,提高页面加载速度和用户体验。
5、Text->TMP
TextMeshPro是一种文本渲染引擎,相比传统文本渲染方法,它具有以下优势:
文本渲染质量更高:TextMeshPro使用了基于矢量的渲染技术,可以实现更高的分辨率和更细致的字形渲染,使得文本在各种分辨率下都能保持清晰和平滑。
支持多语言和特殊字符:TextMeshPro支持各种语言和特殊字符的渲染,包括支持艺术字体、字符间距调整、文字倾斜和旋转等功能。
动态文本渲染:TextMeshPro可以实时更新文本内容,无需重新渲染整个文本对象,大大提高了性能。
易于使用和扩展:TextMeshPro提供了一套易于使用的API和编辑器工具,使得开发人员可以轻松地创建和修改文本样式。同时,它还支持富文本和文本样式的自定义,可以根据需求进行扩展。
总的来说,TextMeshPro相比传统文本渲染方法具有更高的渲染质量、更灵活的功能和更好的性能,使得开发人员可以更好地呈现和控制文本内容。
TextMeshProUGUI文本:
1、Static和Dynamic字体资源区别
TextMeshProUGUI 是 Unity 中用于创建富文本的组件,它支持两种类型的字体资源:Static(静态)和 Dynamic(动态)。
Static 字体资源是一种为每个字符创建一个纹理的字体资源。这意味着每个字符的纹理都在游戏开始时被创建,并且在运行时不能更改。Static 字体资源适用于不需要动态修改文本内容的场景,比如游戏标题、菜单文字等。
Dynamic 字体资源是一种在运行时根据需要动态生成字符纹理的字体资源。这意味着在游戏运行时可以动态修改文本内容,并且每次修改文本时都会重新生成相应的字符纹理。Dynamic 字体资源适用于需要实时更新文本内容的场景,比如显示玩家得分、倒计时等。
在选择 Static 还是 Dynamic 字体资源时,需要考虑文本内容是否需要动态修改。如果文本内容固定不变,则可以使用 Static 字体资源,这样可以减少运行时的计算和内存使用。如果文本内容需要实时更新,则应选择 Dynamic 字体资源,这样可以动态生成并更新字符纹理。
2、FallbackFontAssets资源及多语言情况下对性能的影响
TextMeshProUGUI组件在多语言情况下可以通过设置FallbackFontAssets属性来实现字体的自动切换。FallbackFontAssets是一个字体资产数组,用于定义当当前字体无法显示当前字符时要使用的备用字体。
在多语言情况下,如果某个字符在当前字体中不存在,TextMeshProUGUI组件会自动查找FallbackFontAssets数组中的字体,逐个进行判断,直到找到可以显示该字符的字体为止。因此,当需要显示多种语言时,建议在FallbackFontAssets中添加包含对应字符的备用字体。
然而,需要注意的是,使用FallbackFontAssets属性会带来一定的性能影响。每次TextMeshProUGUI组件绘制文本时,都需要对FallbackFontAssets数组中的字体进行遍历判断。因此,如果FallbackFontAssets数组中包含大量的字体,或者某个备用字体包含大量字符,都会导致性能下降。
为了降低性能影响,可以采取以下措施:
限制FallbackFontAssets数组的长度,只添加必要的备用字体。
优化备用字体,减少包含的字符数量,只包含必要的字符。
尽量使用支持多语言的统一字体,而不是每种语言都使用不同的字体。
总而言之,TextMeshProUGUI组件的FallbackFontAssets属性在多语言情况下可以实现字体的自动切换,但需要注意性能影响,合理配置备用字体以提高性能。