【Unity面试篇】Unity 面试题总结甄选 |Unity性能优化 | ❤️持续更新❤️

news2024/11/24 5:48:40

请添加图片描述


前言

  • 关于Unity面试题相关的所有知识点:🐱‍🏍2023年Unity面试题大全,共十万字面试题总结【收藏一篇足够面试,持续更新】
  • 为了方便大家可以重点复习某个模块,所以将各方面的知识点进行了拆分并更新整理了新的内容,并对之前的版本中有些模糊的地方进行了纠正。
  • 进阶篇中有些题目在基础篇已经有了,这里划分模块时有些会再加一遍用于加深印象学习。
  • 所以本篇文章就来整理一下Unity性能优化,说不准就会面试的时候就会遇到!

【Unity面试篇】Unity 面试题总结甄选 |Unity性能优化 | ❤️持续更新❤️

      • 前言
    • 💘优化部分
        • 1. 什么是DrawCall?DrawCall高了又什么影响?如何降低DrawCall?
        • 2. UI优化小知识
        • 3. 层消隐距离技术
        • 4. LOD是什么,优缺点是什么?
        • 5. 合批
        • 6.静态合批
        • 7.动态合批
        • 8. 动态合批跟静态合批的区别
        • 9. 如何优化内存?
        • 10. mask和rectmask2d的区别
        • 11. 贴图透明通道分离,压缩格式设为ETC/PVRTC
        • 12. 关闭贴图的读写选项
        • 13. Unity 在移动设备上的⼀些优化资源的方法
        • 14. CPU端性能优化小知识点
        • 15. GPU端性能优化小知识点
        • 16. 内存优化小知识点
        • 17. 简述⼀下对象池,你觉得在FPS里哪些东西适合使用对象池?
        • 18. UI图集的作用
        • 19. 请简述GC(垃圾回收)产生的原因,并描述如何避免?
        • 20. 简述优化脚本的方法
        • 21. 简述优化内存管理的方向
        • 22. 简述美术优化的方向
        • 23. 简述优化物理系统的方法
        • 24. 简述UI资源如何优化
  • 👥总结

请添加图片描述


💘优化部分

1. 什么是DrawCall?DrawCall高了又什么影响?如何降低DrawCall?

Unity中,CPU准备好需要绘制的元素,对底层图形程序接口进行调用的过程,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。
降低DrawCall的方法:

  1. 动态合批
  2. 静态合批
  3. 降低shader的等级特性
  4. 场景优化策略——遮挡技术。
  5. rectMask2D替代Mask

2. UI优化小知识

  1. UI动静分离
    以canvas为节点,设置动态canvas和静态canvas,实际项目静态元素较多,动态元素较少,动静分离后,CPU在重绘和合并时消耗就会减少。
  2. 拆分过重的UI
    将界面中隐藏的独立界面做一次拆分
    对二次显示内容,如部分动效图标,小窗口等做二次拆分。
  3. UI预加载
    UI实例化到场景中的过程:网格合并,组件初始化,渲染初始化,图片加载,界面逻辑调用等,消耗大量CPU
    预加载:把资源加载到内存、UI实例化和UI初始化的CPU消耗放在loading等待时间线上
  4. UI图集Alpha分离
    主要是针对NGUI方案,Unity内部已经完成了Alpha分离
    首先:TexturePacker打图集时候,改成打一张RGB888的PNG图和一张Alpha8的PNG图
    其次:修改NGUI的原始着色器,绑定主图和绑定Alpha图
    然后:将NGUI的着色器shader中相应修改为新的颜色通道和透明通道
    最后:NGUI工具类也要相应修改编辑几个类
    最终:主图和Alpha图合成新图片替换原来的图片
  5. UI字体拆分
    提取常用字体
    使用TMP,同样会生成纹理和图集,相比TEXT优势是,TMP是矢量字算法,MESH顶点数少,字体同源,各语言能同屏显示
  6. ScrollView优化
    不停滚动会导致合批网格重构、渲染裁剪
    使用对象池进行优化
  7. 网格重构优化
  8. UI展示与关闭优化
  9. 对象池运用
    当程序中有重复实例化兵不断摧毁的对象时需要使用对象池进行优化
    每个需要使用对象池的对象都需要继承对象池的基类对象
    销毁操作是通过对象池接口提供的回收接口
    场景结束时要及时销毁整个对象池
  10. UI贴图设置优化
  11. 高低端机型画质优化
    使用两套UI贴图,高清,低清,两套图,两套Prefab,NGUI和UGUI高清HD和SD切换的流程可以通过编写脚本程序一键搞定。
    模型和特效使用不同质量(三角面数)的预制体,预制体命名后缀做加载区分,区分等级
    阴影根据使用情况进行区分
    整体贴图渲染质量进行区别对待
    使用QuailtySetting的API来对阴影和贴图渲染质量做操作
    通过程序来区分机型,ios通过机型就能判断UnityEngine.IOS.Device.generation== XXXX.Iphone6;安卓通过CPU型号,内存大小,系统,平均帧率等进行综合判断
  12. UI图集拼接优化
    充分利用图集空间
    图集大小控制1024*1024
    图片的拼接归类

3. 层消隐距离技术

如果场景中存在大量小"物件”,则可以使用"层消隐距离"来优化场景;"层消隐距离"就是在比较远的距离将小物体剔除以减少绘图调用的数量(比如:可以一个大型场景中,高大型的物体任然可见,但是一些小装饰内容(小狗、车子之类的则可以隐藏))

4. LOD是什么,优缺点是什么?

LOD(Level of detail)多层次细节,是最常用的游 戏优化技术。
它按照模型的位置和重要程度决定 物体渲染的资源分配,降低非重要物体的面数和 细节度,从而获得高效率的渲染运算。

这就是说,根据摄像机与模型的距离,来决定显示哪一个模型,一般距离近的时候显示高精度多细节模型,距离远的时候显示低精度低细节模型,来加快整体场景的渲染速度。

  • 作用 : 优化GPU
  • 缺点 : 同一模型要准备多个模型,消耗内存。
  • 特点 : 以内存做消耗来优化GPU

5. 合批

一次Draw Call中批量处理多个物体。只要物体的变换和材质引用相同,GPU就可以按完全相同的方式进行处理,即可以把它们放在一个Draw Call中。

注意:简单来说在一个Canvas下,需要相同的材质,相同的纹理以及相同的Z值。
例如Ul上的字体Texture使用的是字体的图集,往往和我们自己的UI图集不一样,因此无法合批。还有UI的动态更新会影响网格的重绘,因此需要动静分离。

6.静态合批

将static的静态物体(永远不会移动、旋转和缩放) ,如果相同材质球,面数在一定范围之内。unity会自动合并成一个batch送往GPU处理。

原理:在开始阶段把需要静态批处理的GameObject进行一次网格合并操作,然后把这个合并之后的大网格保存起来,后续都是用这个网格而不需要再进行合并。
在预处理阶段,把一些材质相同的模型的顶点统一变换到世界空间坐标下,并且新构建一个大的VB把数据保存下来,在绘制时,就会把这个大的VB提交上去,只需要设置一次渲染状态,再进行多次drawcall绘画出每个子模型。 所以Static Batching是不会减少drawcall的,但由于只修改了一次渲染状态依然可以减少CPU的消耗。而且在渲染前,也可以进行视锥体剔除,减少顶点着色器对不可见的顶点的处理次数,提交GPU的效率。

操作方法:把要进行静态批处理的GameObject在Inspector面板右上角的Static勾选(实际上只需要勾选Batching Static即可)

  • 优点:因为只需要进行一次,所以性能会比动态批处理要好。
  • 缺点: 使用静态合批需要额外的内存开销来存储合并后的几何数据。
    因为需要额外维护多一份数据,所以包体会变大,占用的内存也会变多(不能有超级大量的相同模型(如:森林里的树))

7.动态合批

如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理。动态批处理操作是自动完成的,并不需要进行额外的操作。

原理:Unity会检测哪些GameObject使用了同一个共享材质,然后去合并这些使用了同一个共享材质的网格顶点数据,形成一个新的大网格,然后传给显存,直接渲染这个大网格就相当于渲染了所有的被合并的小网格,而这只需要一次DrawCall。
在每一帧运行时,计算相同材质的模型,把他合并批次进行渲染。动态合批只需要设置一次渲染状态,且能减少drawcall次数。

优点: 不用自己做任何事情,Unity会在游戏中自动进行动态批处理,只要满足下述条件。

  1. 顶点属性要小于900。例如,如果shader中需要使用顶点位置、法线和纹理坐标这三个顶点属性,那么要想让模型能够被动态批处理,它的顶点数目不能超过300。因此,优化策略就是shader的优化,少使用顶点属性,或者模型顶点数要尽可能少。(这个是《UnityShader入门精要》这本书上说到的,同时书上也说了不一定是900,可能不同版本的Unity会有所区别,这个可以自己在Unity中去手动验证得出)
  2. 多Pass的shader会中断批处理。
  3. 使用LightingMap的物体需要小心处理。为了让这些物体可以被动态批处理,需要保证它们指向LightingMap中的同一位置。

8. 动态合批跟静态合批的区别

  • 动态批处理一切都是自动的,不需要做任何操 作,而且物体是可以移动的,但是限制很多。
  • 静态批 处理自由度很高,限制很少,缺点可能会占用更多 的内存,而且经过静态批处理后的所有物体都不可以 再移动了。
  • 静态合批发生在加载场景的时候。
  • 动态合批发生在游戏运行的时候。

9. 如何优化内存?

有很多种方式,例如

  1. 压缩自带类库;
  2. 将暂时不用的以后还需要使用的物体隐藏起来而不 是直接Destroy掉;
  3. 释放AssetBundle占用的资源;
  4. 降低模型的片面数,降低模型的⻣骼数量,降低贴 图的大小;
  5. 使用光照贴图,使用多层次细节(LOD),使用着色 器(Shader),使用预设(Prefab)。

10. mask和rectmask2d的区别

Mask使用模板缓冲来实现区域切除逻辑(Stencil),会占用两个DC。它实现最初设置模板缓存会给Mask添加一个特殊的材质,并且以像素为单位存储是否需要显示最后还原模板缓存,这两次操作各增加一次DC。它可以和其他Mask子物体进行合批,如果两个mask重叠了,那就不能进行合批,会产生额外的dc。

rectmask2d继承自IClipper接口,内部主要实现的就是一个方法来实现了区域的切除逻辑,本身是不占用DC的,完全遮住的情况下不会绘制顶点和面,不参与深度运算不占用DC(和mask的最大区别)。 缺点:它无法和RectMask的子物体进行合批,只能和自身的子物体进行合批(注:如果本身带了Image组件的话是可以进行合批的)

mask2d只能矩形,要不同形状的遮罩还是得mask,所以RectMask2D并不一定完全好,他在特定情况下无法合批。

11. 贴图透明通道分离,压缩格式设为ETC/PVRTC

最初我们使用了DXT5作为贴图压缩格式,希望能减小贴图的内存占用,但很快发现移动平台的显卡是不支持的。因此对于一张1024x1024大小的RGBA32贴图,虽然DXT5可将它从4MB压缩到1MB,但系统将它送进显卡之前,会先用CPU在内存里将它解压成4MB的RGBA32格式(软件解压),然后再将这4MB送进显存。于是在这段时间里,这张贴图就占用了5MB内存和4MB显存;而移动平台往往没有独立显存,需要从内存里抠一块作为显存,于是原以为只占1MB内存的贴图实际却占了9MB!

所有不支持硬件解压的压缩格式都有这个问题。经过一番调研,我们发现安卓上硬件支持最广泛的格式是ETC,苹果上则是PVRTC。但这两种格式都是不带透明(Alpha)通道的。因此我们将每张原始贴图的透明通道都分离了出来,写进另一张贴图的红色通道里。这两张贴图都采用ETC/PVRTC压缩。渲染的时候,将两张贴图都送进显存。同时我们修改了NGUI的shader,在渲染时将第二张贴图的红色通道写到第一张贴图的透明通道里,恢复原来的颜色:

fixed4 frag (v2f i) : COLOR  
 
    fixed4 col;  
 
    col.rgb = tex2D(_MainTex, i.texcoord).rgb;  
 
    col.a = tex2D(_AlphaTex, i.texcoord).r;  
 
    return col * i.color;  
 
fixed4 frag (v2f i) : COLOR
 
{
 
    fixed4 col;
 
    col.rgb = tex2D(_MainTex, i.texcoord).rgb;
 
    col.a = tex2D(_AlphaTex, i.texcoord).r;
 
    return col * i.color;
 
}

12. 关闭贴图的读写选项

Unity中导入的每张贴图都有一个启用可读可写(Read/Write Enabled)的开关,对应的程序参数是TextureImporter.isReadable。
选中贴图后可在Import Setting选项卡中看到这个开关。只有打开这个开关,才可以对贴图使用Texture2D.GetPixel,读取或改写贴图资源的像素,但这就需要系统在内存里保留一份贴图的拷贝,以供CPU访问。
一般游戏运行时不会有这样的需求,因此我们对所有贴图都关闭了这个开关,只在编辑中做贴图导入后处理(比如对原始贴图分离透明通道)时打开它。
这样,上文提到的1024x1024大小的贴图,其运行时的2MB内存占用又可以少一半,减小到1MB。

13. Unity 在移动设备上的⼀些优化资源的方法

  1. 使⽤assetbundle,实现资源分离和共享,将内存控
    制到200m之内,同时也可以实现资源的在线更新
  2. 顶点数对渲染⽆论是cpu还是gpu都是压⼒最⼤的贡
    献者,降低顶点数到8万以下,fps稳定到了30帧左右
  3. 只使⽤⼀盏动态光,不是⽤阴影,不使⽤光照探头
    粒⼦系统是cpu上的⼤头
  4. 剪裁粒⼦系统
  5. 合并同时出现的粒⼦系统
  6. ⾃⼰实现轻量级的粒⼦系统
    animator也是⼀个效率奇差的地⽅
  7. 把不需要跟⻣骼动画和动作过渡的地⽅全部使⽤
    animation,控制⻣骼数ᰁ在30根以下
  8. animator出视ᰀ不更新
  9. 删除⽆意义的animator
  10. animator的初始化很耗时(粒⼦上能不能尽ᰁ不⽤
    animator)
  11. 除主⻆外都不要跟⻣骼运动apply root motion
  12. 绝对禁⽌掉那些不带刚体带包围盒的物体(static
    collider )运动
    NUGI的代码效率很差,基本上runtime的时候对cpu的
    贡献和render不相上下
  13. 每帧递归的计算finalalpha改为只有初始化和变动时
    计算
  14. 去掉法线计算
  15. 不要每帧计算viewsize 和windowsize
  16. filldrawcall时构建顶点缓存使⽤array.copy
  17. 代码剪裁:使⽤strip level ,使⽤.net2.0 subset
  18. 尽量减少smooth group
  19. 给美术定⼀个严格的经过科学验证的美术标准,并在U3D⾥⾯配以相应的检查⼯具

在这里插入图片描述

在这里插入图片描述

14. CPU端性能优化小知识点

  • 逻辑和表现尽可能分离开,这样逻辑层的更新频率可以适当降低些.
  • 对于一些热点函数,如mmo的实体更新、实例化,使用分帧处理,分摊单帧时间消耗.
  • 做好同屏实体数量、特效数量、距离显隐等优化.
  • 完善日志输出,避免没必要的日志输出,同时警惕日志字符串拼接.
  • 使用骨骼烘焙 + GPUSkinning + Instance 降低CPU蒙皮骨骼消耗和drawcall.
  • 开启模型的Optimize GameObjects减少节点数量和蒙皮更新消耗.
  • UI拼预制做好动静分离,对于像血条名字这种频繁变动的ui,做好适当的分组.
  • 减少C#和lua的频繁交互,尽量精简两者传递的参数结构.
  • 使用stringbuilder优化字符串拼接的gc问题.
  • 删除非必要的脚本功能函数,特别是Update/LateUpdate类高频执行函数,因为会产生C++到C#层的调用开销. 对于Update里需要用到的组件、节点等提前Cache好.
  • 场景里频繁使用的资源或数据结构做好资源复用和对象池.
  • 对于频繁显示隐藏的UI,可以先移出到屏幕外,如果长时间不显示再进行Deactive.
  • 合理拆分UI图集,区分共用图集和非共用图集,共用图集可以常驻内存,非共用图集优先按功能分类,避免资源冗余.
    使用IL2CPP, 编译成C++版本能极大的提升整体性能.
  • 避免直接使用Material.Setxxx/Getxxx 等调用,这些调用会触发材质实例化消耗,可以考虑使用 SharedMaterial / MaterialPropertyBlock代替.
  • 合并Shader里的Uniform变量.

15. GPU端性能优化小知识点

  • 合理规划好渲染顺序,避免不必要的overdraw,如:地形(容易被其他物件遮挡)、天空盒放到较后渲染.
  • 分辨率缩放,对于填充率出现瓶颈时,这个是最简单高效的.
  • 避免使用GrabPass抓屏,不是所有硬件都支持,加之数据回拷和没法控制分辨率性能很差,可考虑使用CommandBuffer.blit去优化.
  • 控制好地形的Blend层数,控制在4层以内,考虑到地形一般屏占面积大、贴图采样次数多,对于中低画质考虑不用normalmap.
  • 做好物件、树、角色的LOD.
  • 避免使用RenderWithShader类方式来定制DepthTexture,可以考虑Camera的 public void SetTargetBuffers(RenderBuffer colorBuffer, RenderBuffer depthBuffer);进行优化.
  • 检查Shader的VertexInput 和 VertexOutput是否存在冗余数据.如:顶点色、多套UV.
  • 警惕项目里非必要的双面材质,对于需要局部双面的地方通过加面解决.
  • Shader里使用fixed、half代替float,理论上除position、uv、一些涉及depth相关计算使用float外,其他都应该使用fixed(主要是颜色值)、half.
  • 对于角色皮肤这种不是特别明显的效果,考虑使用预积分这种低成本的方案.
  • 对于frag里的计算过程,如果可以抽出来放到CPU应用层、顶点阶段的优先放这里计算. 需要注意放到顶点阶段引起的平滑过渡问题. 如: eyeVec导致高光过渡问题.
  • 镜面反射类效果避免使用反射相机+RT的实现,考虑使用SSR、CubeMap类实现.
  • 避免使用实时阴影,如若使用要合理控制下分辨率和阴影距离. 考虑使用Projector.
  • 使用统一的后处理框架代替多个Image Effect,可以共用模糊函数,减少blit操作. 另外Unity自带的Postprocessing V2 支持Volume,性能还是不错的.
  • Shader里避免使用分支、循环,sin、tan、pow、log等复杂数学运算.
  • Unity自带的遮挡剔除因为CPU消耗和内存占用较高,加之不能Instancing,不太适合移动平台,可以考虑静态预计算(缺点是不支持动态物体)、Hi-Z等优化方案.
  • 减少alpha test材质的使用,如若使用注意减小面积、控制渲染顺序.

16. 内存优化小知识点

  • 压缩自带类库;
  • 将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉;
  • 释放AssetBundle占用的资源;
  • 降低模型的片面数,降低模型的骨骼数量,降低贴图的大小;
  • 使用光照贴图,使用多层次细节(LOD),使用着色器(Shader),使用预设(Prefab)。
  • 警惕配置表内存占用
  • 排查项目冗余的shader
  • 减少容器扩容或者利用string字符串拼接等一系列产生GC的操作
  • 警惕配置表的内存占用.
  • 检查ShaderLab内存占用:
  • 避免使用Standard材质,做好相应的variant skip.
  • 排查项目冗余的Shader.
  • 使用shader_feature替代multi_compile,这样只会收集项目里真正使用的变体组合,避免变体翻倍.
  • 检查纹理资源的尺寸、格式、压缩方式、mipmap、Read & Write选项使用是否合理.
  • 检查Mesh资源的Read & Write选项、顶点属性使用是否合理.
    代码级别的检查,如Cache预分配空间、容器的Capacity、GC等.
  • 使用Profiler定位下GC,特别是Update类函数里的. 如:字符串拼接、滥用容器等.
  • 合理控制RenderTexture的尺寸.
    优化动画Animation的压缩方式、浮点精度、去除里面的Scale曲线数据.
  • 减少场景GameObject节点的数量,最好支持工具监控.

17. 简述⼀下对象池,你觉得在FPS里哪些东西适合使用对象池?

对象池就存放需要被反复调⽤资源的⼀个空间,⽐如游戏中要常被大量复制的对象,⼦弹,敌⼈,以及任何重复出现的对象。

18. UI图集的作用

图集就是碎图合成大图 降低内存,减少DC。

UI图集有合批没有的优点,就是热更新的时候因为小文件变少了,所以会快一些。

UI图集就是UI的动态合批。

UI图集完成合批的条件:深度 贴图 材质 => 排序好的列表当前这个依次和前面对比是否贴图和材质ID相同决定是否合批。

19. 请简述GC(垃圾回收)产生的原因,并描述如何避免?

GC垃圾回收机制,避免堆内存溢出,定期回收那些没有有效引用的对象内存
GC优化,就是优化堆内存,减少堆内存,即时回收堆内存
GC归属于CLR

避免:

  1. 减少new的次数
  2. 字符串拼接使用stringbuilder,字符串比较先定义一个变量存储,防止产生无效内存
  3. list,new时候,规定内存大小
  4. 如果要射线检测,应该使用避免GC的方法XXXXNoAlloc函数
  5. foreach迭代器容易导致GC(目前Unity5.5已修复),使用For循环
  6. 使用静态变量,GC不会回收存在的对象,但静态变量的引用对象可能被回收
  7. 使用枚举替代字符串变量
  8. 调用gameobject.tag=="XXX"就会产生内存垃圾;那么采用GameObject.CompareTag()可以避免内存垃圾的产生:
  9. 不要在频繁调用的函数中反复进行堆内存分配,比如OnTriggerXXX,Update等函数
  10. 在Update函数中,运行有规律的但不需要每一帧执行的代码,可以使用计时器,比如1秒执行一次某些代码!!!

更多GC内容可查看本篇文章:
Unity零基础到进阶 ☀️| Unity中的 GC及优化 超级全面解析 ☆(ゝω・)v 建议收藏!

20. 简述优化脚本的方法

  • 减少GetComponent、find等查找函数在Update等循环函数中的调用、go.CompareTag代替go.tag 、
  • 减少SendMessage等同步函数调用;减少字符串连接;for代替foreach,5.5以后版本foreach已经优化过了;少用linq;
  • 大资源改为异步加载
  • 合理处理协程调用
  • 将AI、网络等放在单独线程
  • 发布优化:关闭log、剔除代码
  • 伪随机
  • 脚本挂载类改为Manager等全局类实现
  • lua中尽量不实现update、fixedupdate等循环函数,lua和csharp互调用的效率比较低。

21. 简述优化内存管理的方向

  • 按照不同资源、不同设备管理资源生命周期,Resources.Load和Assetbundle统一接口,利用引用计数来管理生命周期,并打印和观察生命周期。保证资源随场景而卸载,不常驻内存,确定哪些是预加载,哪些泄漏。
  • 内存泄漏(减少驻留内存):Container内资源不remove掉用Resources.UnloadUnusedAssets是卸载不掉的;对于这种情况,建议直接通过Profiler Memory中的Take Sample来对其进行检测,通过直接查看WebStream或SerializedFile中的AssetBundle名称,即可判断是否存在“泄露”情况;通过Android PSS/iOS Instrument反馈的App线程内存来查看;
  • 堆内存过大:避免一次性堆内存的过大分配,Mono的堆内存一旦分配,就不会返还给系统,这意味着Mono的堆内存是只升不降的。常见:高频调用new;log输出;
  • CPU占用高:NGui的重建网格导致UIPanel.LateUpdate(按照静止、移动、高频移动来切分);NGUI锚点自身的更新逻辑也会消耗不少CPU开销。即使是在控件静止不动的情况下,控件的锚点也会每帧更新(见UIWidget.OnUpdate函数),而且它的更新是递归式的,使CPU占用率更高。因此我们修改了NGUI的内部代码,使锚点只在必要时更新。一般只在控件初始化和屏幕大小发生变化时更新即可。不过这个优化的代价是控件的顶点位置发生变化的时候(比如控件在运动,或控件大小改变等),上层逻辑需要自己负责更新锚点。 加载用协程; 控制同一个UIPanel中动态UI元素的数量,数量越多,所创建的Mesh越大,从而使得重构的开销显著增加。比如,战斗过程中的HUD血条可能会大量出现,此时,建议研发团队将运动血条分离成不同的UIPanel,每组UIPanel下5~10个动态UI为宜。这种做法,其本质是从概率上尽可能降低单帧中UIPanel的重建开销。
  • 资源冗余:AssetBundle打包打到多份中;动态修改资源导致的Instance拷贝多份(比如动态修改材质,Renderer.meterial,Animation.AddClip)。
  • 磁盘空间换内存:对于占用WebStream较大的AssetBundle文件(如UI Atlas相关的AssetBundle文件等),建议使用LoadFromCacheOrDownLoad或CreateFromFile来进行替换,即将解压后的AssetBundle数据存储于本地Cache中进行使用。这种做法非常适合于内存特别吃紧的项目,即通过本地的磁盘空间来换取内存空间

22. 简述美术优化的方向

  • 建立资源审查规范和审查工具:PBR材质贴图制作规范、场景制作资源控制规范、角色制作规范、特效制作规范;利用AssetPostprocessor建立审查工具。
  • 压缩纹理、优化精灵填充率、压缩动画、压缩声音、压缩UI(九宫格优于拉伸);严格控制模型面数、纹理数、角色骨骼数。
  • 粒子:录制动画代替粒子、减少粒子数量、粒子不要碰撞
  • 角色:启用Optimize Game Objects减少节点,使用(SimpleLOD、Cruncher)优化面数。
  • 模型:导入检查Read/Write only、Optimize Mesh、法线切线、color、禁用Mipmap
  • 压缩纹理问题:压缩可能导致色阶不足;无透明通道用ETC1,现在安卓不支持ETC2已不足5%,建议放弃分离通道办法。
  • UI:尽可能将动态UI元素和静态UI元素分离到不同的UIPanel中(UI的重建以UIPanel为单位),从而尽可能将因为变动的UI元素引起的重构控制在较小的范围内; 尽可能让动态UI元素按照同步性进行划分,即运动频率不同的UI元素尽可能分离放在不同的UIPanel中; 尽可能让动态UI元素按照同步性进行划分,即运动频率不同的UI元素尽可能分离放在不同的UIPanel中;
  • ugui:可以充分利用canvas来切分不同元素。
  • 大贴图会导致卡顿,可以切分为多个加载。
  • iOS使用mp3压缩、Android使用Vorbis压缩

23. 简述优化物理系统的方法

  • 不需要移动的物体设为Static
  • 不要用Mesh碰撞,角色不用碰撞体
  • 触发器逻辑优化
  • 寻路频率、AI逻辑频率 、Fixed Timestep、降帧到30
  • 出现卡顿的复杂计算,例如寻路、大量资源加载 可以用分帧或者协成异步来处理

24. 简述UI资源如何优化

纹理资源优化

  1. 单个纹理尺寸为2的幂次方,最大尺寸1024*1024(内存优化)
  2. 纹理加载方式:流式纹理加载Texture Streaming
  3. 不通过增加纹理大小来增加细节,而是通过增加细节贴图DetailMap或增加高反差保留
  4. 纹理压缩:可以使用ETC1+Alpha(安卓),ETC2(安卓),PVRTC(ios),ASTC 6x6
  5. ASTC更优,内存大小相同的情况下,纹理效果最好,加载速度最快,包体最小
  6. 纹理MipMap:逐级减低分辨率来保存纹理副本,相当于纹理LOD
  7. 内存变大1//3,通过Mipmap开启可以限制不同平台加载不同level层级的贴图

UI纹理图集

  1. UI图集最大尺寸为1024*1024
  2. 重复利用的公用资源放common图集(drawcall优化)
  3. 同一个界面UI资源放一个图集(drawcall优化)
  4. 使用九宫格来减少原图大小(内存优化)
  5. 提高图集利用率,原图分辨率需要包含在1024*1024尺寸下,如果原图过大需要进行拆分,放入图集中
  6. 图集合并提升利用率,如果图集低于1/3 就要合并图集。
微信搜索:呆呆敲代码的小Y
回复:白嫖
免费获取很多的编程资料哦!

更多优化知识学习文章:【Unity 优化篇】 | 优化专栏《导航帖》,全面学习Unity优化技巧,让我们的Unity技术上升一个档次


👥总结

  • 全网最全的 Unity性能优化 面试题都在这里了,希望本篇文章能够让你在面试关卡如鱼得水得到自己想要的工作。
  • 看完觉得有用别忘了点赞收藏哦,如果觉得哪个方面的内容不够丰富欢迎在评论区指出!
  • 如果你的Unity基础知识还不够熟练,也欢迎来 『Unity精品学习专栏⭐️』『Unity 实战100例 教程⭐️』继续学习哦!
  • 如果你还有更好的面试题,欢迎在评论区提出,会整理到文章中去哦!!!

请添加图片描述


资料白嫖,技术互助
请添加图片描述

  • 🎬 博客主页:https://xiaoy.blog.csdn.net

  • 🎥 本文由 呆呆敲代码的小Y 原创 🙉

  • 🎄 学习专栏推荐:Unity系统学习专栏

  • 🌲 游戏制作专栏推荐:游戏制作

  • 🌲Unity实战100例专栏推荐:Unity 实战100例 教程

  • 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

  • 📆 未来很长,值得我们全力奔赴更美好的生活✨

  • ------------------❤️分割线❤️-------------------------

学习路线指引(点击解锁)知识定位人群定位
🧡 Unity系统学习专栏 🧡入门级本专栏从Unity入门开始学习,快速达到Unity的入门水平
💛 Unity实战类项目 💛进阶级计划制作Unity的 100个实战案例!助你进入Unity世界,争取做最全的Unity原创博客大全。
❤️ 游戏制作专栏 ❤️ 难度偏高分享学习一些Unity成品的游戏Demo和其他语言的小游戏!
💚 游戏爱好者万人社区💚 互助/吹水数万人游戏爱好者社区,聊天互助,白嫖奖品
💙 Unity100个实用技能💙 Unity查漏补缺针对一些Unity中经常用到的一些小知识和技能进行学习介绍,核心目的就是让我们能够快速学习Unity的知识以达到查漏补缺

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/754536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SOEM_1(笔记,从别的博客文章学的笔记)

目录介绍: doc:帮助文档、 osal:主要是用于符合OSADL和实时进程创建。也就是说:发送EtherCAT数据包不能抖动太大,如果直接使用linux提供的原生线程,可能实时性无法满足。需要对Linux内核打上实时补丁&…

高等数学❤️第一章~第二节~极限❤️极限的概念与性质~数列极限详解

【精讲】高等数学中的数列极限解析 博主:命运之光的主页 专栏:高等数学 目录 导言 一、数列极限的定义 二、数列极限的判定方法 三、数列极限的性质 必需记忆知识点 例题(用于熟悉数列极限) 例题1 例题2 例题3 结论 导言…

【QQ好友列表展示-设置HeaderView Objective-C语言】

一、好,看一下,刚才我们这个btnGroupTitle的frame为什么是0 现在我们首先知道,当你程序一运行起来以后,你这里的self,就是 当你程序运行起来以后,这个headerView 的frame,默认应该是0的 就是我们看到的效果,它应该都是0 的 一开始都是0 的 那么其实也就是说,是这样…

Pruning 系列 (十)Pruning VGG 实战

环境 python 3.9numpy 1.24.1pytorch 2.0.0+cu117流程 一、 VGG 模型代码 # -*- coding: utf-8 -*- import torch import torch.nn as nndefault_cfg = {11: [64, M, 128, M, 256, 256, M, 512, 512, M, 512, 512],13: [64, 64, M, 128, 128, M, 256, 256, M, 512, 512, M, …

认识企业级定时任务Quartz

文章目录 前言一、实现一个Quartz的小案例1.创建一个maven项目2.添加Quartz依赖3.创建一个配置文件配置Quartz信息4.创建一个Job类继承Job接口5.编写主方法逻辑进行测试6.测试运行结果 二、Job和JobDetail总结 前言 目前仍有大部分企业仍在使用Quartz这种定时任务框架&#xf…

【分布式应用】ceph分布式存储

目录 一、存储基础1.1单机存储设备1.2单机存储的问题1.3分布式存储的类型 二、Ceph简介2.1Ceph 优势2.2Ceph 架构2.3Ceph核心组件OSD(Object Storage Daemon,守护进程 ceph-osd)PG(Placement Group 归置组)PoolMonitor…

【运维】第03讲(上):Nginx 负载均衡常见架构及问题解析

实际上 Nginx 除了承担代理网关角色外还会应用于 7 层应用上的负载均衡,本课时重点讲解 Nginx 的负载均衡应用架构,及最常见的问题。 学前提示 Nginx 作为负载均衡是基于代理模式的基础之上,所以在学习本课时前,你需要对 Nginx …

Codeforces Round 884 (Div. 1 + Div. 2)(视频讲解A--D)

[TOC](Codeforces Round 884 (Div. 1 Div. 2)&#xff08;视频讲解A–D&#xff09;) 视频链接&#xff1a;Codeforces Round 884 (Div. 1 Div. 2)&#xff08;视频讲解A–D&#xff09; A Subtraction Game 1、 板书&#xff1a; 2、代码 #include<bits/stdc.h> #…

网络协议与攻击模拟-19-FTP协议

FTP 协议 1、了解 FTP 协议 2、使用在 Windows 操作系统上使用 serv - U 软件搭建 FTP 服务器 3、分析 FTP 流量 一、 FTP 协议 1、概念 FTP &#xff08;文件传输协议&#xff09;&#xff0c;由两部分组成&#xff1a;客户端&#xff0f;服务器 C / S 架构&#xff0c;应…

Uniapp 版本更新

文章目录 前言Uniapp更新确定接口是否能够使用基本代码封装更新软件区别 前言 软件发布之后更新是经常出现的需求。我们希望软件能够自动连网更新软件&#xff0c;而不是重新去手动安装一个apk安装包。不需要更新的软件只有两个&#xff0c;一个是微信小程序&#xff0c;另一个…

C++浅谈const

在学C的时候&#xff0c;必不可少的是const&#xff0c;他或许在C语言中是可有可无的&#xff0c;但是在C中绝对不是&#xff0c;我们在学习C语言的时候&#xff0c;我们知道的是&#xff0c;经常有人说加const是为了保证“安全”&#xff0c;那么&#xff0c;所谓的“安全”是…

MFC第十六天 CFileDialog、CEdit简介、(线程)进程的启动,以及Notepad的开发(托盘技术-->菜单功能)

文章目录 CCommonDialogCFileDialogCEdit托盘技术进程的启动附录1:启动线程方式附录2:MFC对话框的退出过程 CCommonDialog 通用对话框 CCommonDialog 这些对话框类封装 Windows 公共对话框。 它们提供了易于使用的复杂对话框实现。 CFileDialog 提供用于打开或保存文件的标准对…

使用Git上传大文件模型(超过100MB)教程

目录 modelscope官方教程 服务器拒绝的解决方案 检查.gitattributes文件 modelscope官方教程 我们

Amazon 上的数字孪生:使用 L3 预测性数字孪生来预测“行为”

在上一篇博文中&#xff0c;我们讨论了数字孪生的定义和框架&#xff0c;这与我们的客户在其应用中使用数字孪生的方式一致。我们将数字孪生定义为“单个物理系统的动态数字表示&#xff0c;它通过数据进行动态更新以模仿物理系统的真实结构、状态和行为&#xff0c;从而加快获…

Vue3+ts;枚举(enum);Partial全部可选/Pick选一部分/配置 svg 图标/unplugin-vue-components组件自动按需加载

项目的创建 使用 create-vue 脚手架创建项目。 1.执行创建命令 pnpm create vue # or npm init vuelatest # or yarn create vue2.选择项目依赖内容。 ✔ Project name: … //项目名 ✔ Add TypeScript? … No / Yes ✔ Add JSX Support? … No / Yes ✔ Add Vue Router …

macOS 开发 - 纯代码生成 Window

文章目录 1、创建项目删除项目自带 window创建 BaseWindowController 继承自 NSWindowController子 WC 继承 BaseWC个人更喜欢纯代码:控制力、方便复制,不用卡卡的打开 xib 这里不使用各种项目自带的 storyboard/xib,使用纯代码创建 window(controller) 本示例代码将创建如下…

记录一下Mybatis中的if标签使用时遇到的问题

记录一下Mybatis中的if标签使用时遇到的问题 前言一、if标签遇到的问题二、if标签中""和的问题字符串等于条件的两种写法&#xff1a; 三 、总结 前言 今天在项目中进行查询时使用了if标签&#xff0c;遇到了问题&#xff1a; 开始时拉过代码来的时候是这样的 <…

Java关键字interface(接口)

文章目录 接口的理解接口的声明接口的成员说明接口的使用规则类实现接口&#xff08;implements&#xff09; 接口的多实现接口的多继承(extends)接口与实现类对象构成多态引用使用接口的静态成员使用接口的非静态方法JDK8中相关冲突问题总结小测试接口与抽象类之间的对比练习 …

不允许你不知道的 MySQL 优化实战(二)

文章目录 11、使用联合索引时&#xff0c;注意索引列的顺序&#xff0c;一般遵循最左匹配原则。12、对查询进行优化&#xff0c;应考虑在where及order by涉及的列上建立索引&#xff0c;尽量避免全表扫描。13、如果插入数据过多&#xff0c;考虑批量插入。14、在适当的时候&…

[QT编程系列-9]:C++图形用户界面编程,QT框架快速入门培训 - 3- QT窗体设计 - 自动布局

目录 3. QT窗体设计 3.7 自动布局 3.7.1 自动布局 3.7.2 在主窗口中自动布局 3.7.3 在自动布局容器中自动布局 3.7.4 在widget中自动布局 3.7.5 自动布局工件 3. QT窗体设计 3.7 自动布局 3.7.1 自动布局 在QT中&#xff0c;自动布局是一种灵活而强大的方式来管理和排…