赞
踩
本文将介绍下常用的Unity自带的常用优化工具,并介绍部分常用优化方法。都是比较基础的内容。
可以简单查看Unity运行时的统计数据,当前一帧的性能数据。
音频相关内容。
图像相关内容。
PS:没用的Animator组件和Animation组件可以考虑删掉。因为即使只有空的动画,Animator组件和Animation组件也会根据自己的工作流程进行每帧的计算和更新,以检查当前动画状态和过渡条件,这样就会消耗不必要的性能。
- using UnityEditor;//编辑器头文件
- using UnityEngine;
-
- public class NewBehaviourScript : MonoBehaviour
- {
- private void Update()
- {
- //使用UnityStats类访问相关数据
- Debug.Log(UnityStats.vertices);
- }
- }
性能分析器的窗口,用来详细分析游戏性能。
打开Profiler窗口的方法:
如图所示,显示的是性能模块,分别显示了各类性能条目。我们也可以自定义这块内容。
点击后如图:
可以勾选来选择哪些显示、哪些隐藏,右下角可以恢复默认状态,左下角小齿轮则是设置,点击它。
图上已经标明相关操作了,除了对已有模块的排序,其他操作都是针对我们创建的新的自定义模块的。
Play Mode需要在运行状态下收集,Edit Mode在编辑器状态下收集。另外,开始收集后再次点击圆形按钮将会中值收集。
可以保存为二进制文件,后续可以读取这个二进制文件。
选中后即可开启深度分析,在收集数据,并选择观察某一帧的数据时,里面会包含脚本函数的性能分析数据。一般是不开的,因为若脚本过多的话,深度分析会收集过多的数据,导致分析器过卡。
深度分析是分析所有脚本的函数,不能仅仅只收集某一个函数的。这里还有两个方法可以针对性的收集某一段代码的性能,方便我们使用。
代码:
- using UnityEngine;
- using UnityEngine.Profiling;//引用头文件
-
- public class NewBehaviourScript : MonoBehaviour
- {
- private void Update()
- {
- //使用BeginSample和EndSample包裹一段代码,这段代码便可被性能分析器收集到
- Profiler.BeginSample("MyProfilerTest HHHHHHH");//参数就是下面那段代码,在性能分析器中的名称。(建议不要写中文名)
-
- for (int i = 0; i < 10000; i++)
- {
- int a = 149;
- a += 1;
- }
-
- Profiler.EndSample();
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
然后在性能分析器中收集,再查询:
可以看到我们之前的代码段就可以被搜索到了。
调用栈(Call Stack)是计算机程序在执行过程中记录函数调用的一种数据结构。
调用栈是一个栈结构,即先进后出。它用于记录程序执行过程中,每个函数被调用的情况。
当一个函数被调用时,它的相关信息,如函数名、参数、返回地址等,会被添加进调用栈中。当该函数执行完成后,相应的信息会从调用栈中移除。通过不断添加和移除函数调用的信息,调用栈就记录了程序执行的顺序。
调用栈对于程序调试和分析非常有用。当程序出现错误或异常时,可以通过查看调用栈来确定错误发生的位置和函数调用的顺序。调试器通常会显示当前调用栈的信息,以帮助开发人员查看函数的执行过程并找出发生异常的原因。
选中Deep Profile右侧的Call Stacks按钮,这样在收集性能数据的时候,每一帧都会记录方法的的调用栈信息,这里的方法指三个方法,点击右侧倒置小三角可以看到它们:GC.Alloc、UnsafeUtility.Malloc、JobHandle.Complete。其是Unity的方法,启用Call Stacks且勾选它们后,如果Unity有调用它们,则可以在Hierarchy或Raw Hierarchy右侧的搜索框中搜索到它们,这样就可以查看它们的性能了。
下方窗口可以选择Timeline、Hierarchy、Raw Hierarchy。
选择Timeline,可以通过时间轴的方式查看这一帧中CPU依次干了什么。
选择Hierarchy,可以查看CPU在这一帧中做的事情所消耗的性能和所花费的时间。Total表示一共占用了CPU使用情况的百分之几。Self表示自身的代码占用了CPU使用情况的百分之几,调用其它方法的代码不算在内的。Calls表示被调用了几次。GC Alloc表示GC分配的内存,当一个对象被释放后,它GC分配的内存不会马上被回收,所有GC分配的内存的总量达到一定程度,会触发GC,此时垃圾回收器才会把这些内存回收,不过同时也会造成游戏卡一下。Time ms表示一共耗时多少毫秒。Self ms表示表示自身的代码耗时多少毫秒,调用其它方法的代码不算在内的。
选择Raw Hierarchy比起Hierarchy会单独列出更多信息,Hierarchy实际上是把这些信息合并了。
其功能和Profiler基本一致,只是其是独立运行的性能分析器,不在Unity中运行,分析的内容中也不会包含自己(性能分析器)的性能数据。
Frame Debugger窗口也叫帧调试器窗口,用于查看每一帧的画面是如何渲染出来的,可以详细查看这一帧的绘制过程。
按下“Enable”(窗口左上角),则会启动帧调试,此时如果运行了游戏,则会自动暂停,然后当前这帧的渲染情况可以在这个窗口中查看。
上面拖动调中最大数值表示了绘制过程中有多少步,可以查看下一步或上一步。如果要禁用帧调试,可以按下“Disable”。用Frame Debugger窗口查看当前一帧的每一步时,可以配合Stats窗口使用,以此来确定哪一个物体造成的性能开销较大。绘制的步骤越少,性能越好。Frame Debugger窗口也能看到每一帧的Shader信息,但是需要有一定Shader基础才能看懂。
PS:
大多数平台都支持帧调试器的使用,可以用手机的数据线成功连接到电脑,在手机上运行Unity的游戏,Frame Debugger窗口中会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。也可以让手机和电脑都连接同一个wifi,这样一来,Frame Debugger窗口中也会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
但是要注意,构建时必须在Project Settings窗口中勾选“Development Build”。而且有些平台可能不支持Frame Debugger的使用,例如WebGL平台。
在Profiler中打开:
安装后,安装按钮便变为了打开按钮,点击即可。
具体的使用方式是“内存快照”。点击“Captrue New Snapshot”,就会捕捉当前内存情况。非运行状态下捕捉的是编辑器状态下的内容,运行状态下捕捉的是运行下的内容。内存快照中将包含当前内存中的所有信息,所以存在泄漏重要内容的可能性,这点要注意。快照会被默认保存到与项目Assets文件夹同级的MemoryCaptures文件夹中,后续可再次打开旧快照。另外,保存路径在窗口右上角的设置中可以修改。
点击快照,即可看到详细数据。
窗口内提供了对比功能,可以拍多张快照进行对比,查询两个瞬间下内存的变化,通常用来查找内存泄露。后续自己可以研究下里面的内容,这里就不多说了。
在Window→Analysis中还有一些其他窗口,使用上可能没有那么频繁,具体内容直接从官方文档中学习吧。
静态合批也叫静态批处理,是Unity的一种优化技术。对于始终静止不动的物体使用静态合批后,CPU会把它们合并为一个批次发送给GPU处理,这样可以减少Draw Call带来的性能消耗,从而提升游戏性能。
要使用静态合批,必须确保Edit——Project Settings——Player——Other Settings——Static Batching是勾选的。
把一个物体设置为静态的方法:选中该物体,点击在Inspector窗口右上角的Static右方的下拉菜单,选择Batching Static。
使用静态合批虽然可以提升游戏性能,但是设置为静态的物体在整个游戏中就不能再运动了,强行使它们运动会出问题。
即使按照以上步骤进行了静态合批,也不一定保证会成功,必须满足以下全部条件,静态合批才会成功:
即使静态合批成功,合出来的每个批次可以包含的网格顶点数是有限的,最多是64000个顶点。如果超过这个数,则会创建到另一个批次中。
在Profiler中查看,如下图所示:
选中Rendering后,下方窗口会显示详细数据,红色框住的地方可以查看合批的效果,主要看中间那个Static Batching即可,若后面有数值表示进行了合批。另外说下,Dynamic Batching是动态合批,Instancing是GPU Instancing,这些后面会讲,看合批效果也是在这看。还有,Batched Draw Calls是参于合批的Draw Calls数,Batches则是参与合批的Batches数,后面两个是三角面数与顶点数。
如果要在游戏运行时进行静态合批,则可以使用StaticBatchingUtility类的Combine方法。
- using UnityEngine;
-
- public class NewBehaviourScript : MonoBehaviour
- {
- public GameObject m_obj;
- public GameObject[] m_objArray;
-
- private void Start()
- {
- //对指定的根物体的所有子孙物体进行静态合批。
- StaticBatchingUtility.Combine(m_obj);
-
- //对指定的游戏对象进行静态合批,并指定它们静态合批的根物体。这里数组是静态合批的对象,m_obj是根物体。
- StaticBatchingUtility.Combine(m_objArray, m_obj);
-
- //对于以上两个:
- //只有当它们符合静态合批的所有条件,静态合批才会成功。
- //成功之后,这些物体就不能再运动了,强行运动会出问题。但是该根物体仍然允许运动。
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
动态合批也叫动态批处理,是Unity的一种优化技术。对移动的物体使用动态合批后,则Unity不会一个个绘制它们,而是把它们合并为一个批次(Batch),再由CPU把它们一次性提交给GPU进行处理,这样可以减少Draw Call带来的性能消耗,从而提高性能。
动态合批默认是由Unity自动完成。可以在Edit——Project Settings——Player——Other Settings——Dynamic Batching查看。默认Dynamic Batching是勾选的,当条件满足时,Unity会自动对使用了相同材质(Material)的物体进行动态合批。如果取消勾选,则不会进行动态合批。
即使勾选了Dynamic Batching,也必须同时满足以下条件,动态合批才会成功:
几乎所有的Unity着色器都支持正向渲染中的多个光源。为了实现这一点,他们为每个光处理一个额外的渲染通道。Unity只批处理第一个渲染通道。它不能批处理额外的逐像素灯光的绘制调用。
遗留延迟渲染路径不支持动态批处理,因为它在两个渲染通道中绘制GameObjects。第一个通道是灯光预通道,第二个通道渲染GameObjects。
其中我们要注意的是,物体必须使用相同的材质,才有可能成功进行动态合批。
使用动态合批往往能减少CPU和GPU的开销,提升游戏性能,但同时也会占用一定的内存。
是否要开启动态合批,要根据自己的项目来定。可以尝试启用,在性能分析器中看看效果如果,如果效果好,再确定启用它。
请查看3.1.3。
Instancing是Unity的一种优化技术。使用GPU Instancing可以在一个Draw Call中同时渲染多个相同或类似的物体,从而减少CPU和GPU的开销。
要启用GPU Instancing,我们可以选中一个材质,然后在Inspector窗口勾选Enable GPU Instancing,这样就可以了。
要成功使用GPU Instancing进行优化,游戏对象必须同时满足以下条件:
另外需要注意的是,GPU Instancing与SRP Batcher不兼容。如果项目使用了SRP Batcher,并且配置为优先使用SRP Batcher而不是GPU实例化,启用GPU实例化可能不会生效。SRP Batcher是Unity提供的一种渲染优化技术,它可以将多个网格合并成单个批次进行渲染,从而提高性能。在这种情况下,GPU实例化将被忽略。
使用GPU Instancing往往能减少CPU和GPU的开销,提升游戏性能,但同时也会占用一定的内存。
是否要启用GPU Instancing,要根据自己的项目来定。可以尝试启用,在性能分析器中看看效果如果,如果效果好,再确定启用它。
一般来说,当场景中有大量重复的网格实例时,可以尝试启用GPU Instancing。例如场景中有大量树木、草地、石块等,这些实例具有相同的网格和材质,只是位置、颜色等属性稍有差异,那么启用GPU Instancing或许能够显著提高性能。
请查看3.1.3。
正常情况下,如果一个障碍物A挡住了后面的物体B,虽然我们看不见物体B,但是Unity仍然会消耗性能来渲染这个物体B。这样CPU和GPU就会有一部分性能白白浪费在渲染物体B身上。如果想在一个障碍物挡住了后面的物体后,不渲染被挡住的物体,则可以使用遮挡剔除。
以一堵墙挡住几个小球为例,选中这堵墙,在Inspector窗口右上角的Static右侧的下拉菜单处选择Occluder Static,则这堵墙就是遮挡物。分别选中这些小球,在Inspector窗口右上角的Static右侧的下拉菜单处选择Occludee Static,则这些小球就是被遮挡物。对于一个物体,两个标签都可以勾选,这样它既可以遮挡剔除别的物体,也可以被别的物体遮挡剔除。有时候被遮挡物只勾Occludee Static,烘焙之后可能看不出遮挡剔除的效果,建议把Occluder Static也勾上,再重新烘焙,或许就能看出效果了。注意,无论是勾选了Occluder Static还是Occludee Static,勾选后物体就无法运动了。
选中摄像机,要确保它启用了Occlusion Culling属性。
设置完之后,要创建一个遮挡区域,当摄像机处于这个遮挡区域中,遮挡剔除才会生效。创建遮挡区域的方法:
第一种:
新创建的区域对象如下:
Occlusion Area组件的Size决定了遮挡剔除区域的范围,它越大,烘焙之后生成的遮挡剔除区域就越大。Center控制遮挡区域中心点的世界坐标。Is View Volume表示是否定义视图体积,只有启用了这个选项,Occlusion Area组件才可能生效。调整区域大小:
之后,要让遮挡剔除生效,还要在Occlusion Culling窗口的Bake选项卡中点击右下方的Bake按钮,进行烘焙,遮挡剔除才可能生效。而且以后每次调整完场景的遮挡物、被遮挡物、Occlusion Area组件的范围,都要这样烘焙一次。如果点击Bake按钮旁边的Clear按钮,则会清除之前烘焙的数据。对场景进行烘焙:
黄色的框的范围才是最终的相机应该所在的范围。其大小跟前面的Occlusion Area组件的范围可能不一致。
烘焙完之后,当摄像机在黄框范围内,则被遮挡的物体不会被渲染。遮挡物实际上遮挡了摄像机视锥体的范围,只要物体完全没有出现在摄像机视锥体的范围内,则都不会被渲染。但是一旦物体的任意一小部分暴露在了摄像机视锥体的范围内,则这个物体整个会被渲染出来。 当摄像机移出了黄框范围,则遮挡剔除会失效。
使用Occlusion Portal组件也可以实现遮挡剔除。
例如可以在一堵墙上添加Occlusion Portal组件。而且这堵墙不要不勾选Inspector窗口右上角下拉菜单的Occluder Static和Occludee Static,但是被它遮挡的物体仍然要勾选Occluder Static和Occludee Static。
设置好之后,打开Occlusion Culling窗口,在Bake选项卡进行烘焙。
这样一来,Occlusion Portal组件就会生效。当取消勾选它的Open属性后,被这堵墙就会使用遮挡剔除。当勾选它的Open属性后,被这堵墙就不会使用遮挡剔除。我们可以使用代码来控制Open属性,控制这堵墙在什么时候使用遮挡剔除,什么时候不使用遮挡剔除。
Occlusion Portal组件的Center属性控制了中心的位置,Size属性控制了遮挡的范围。点击Edit Bounds左侧的按钮后,可以在Scene窗口手动调节Occlusion Portal组件的遮挡范围。每次调整完,或者修改过场景,都要重新烘焙。
PS:挂载Occlusion Portal的墙是可以移动的,但是遮挡位置是不能移动的,即移动了墙后,原来的位置虽然空了,但起遮挡作用的“墙”依旧在原来的位置。
PS:光照和阴影最影响项目的性能,其次才是模型网格和贴图。把实时光照改成烘焙光照,可以使游戏性能大幅度增加。
如果这张图片是应用在移动端的,则导入Unity前,可以对这张图的每条边进行调整,确保每条边的长度都是2的正整数次方个像素。例如2、4、8、16...256、512、1024、2048、4096...。这个做法只对移动端有效。
用Sprite Atlas用于制作图集,把多张图片打包成一整张图集。
从Window→PackageManger中安装2D Sprite插件,才能使用Sprite Atlas。
在安装完插件后,可以在Project窗口中创建图集:
创建好图集后,选中它,Inspector面板如图所示:
红框中为我们添加图片的地方,但在添加之前注意下面的叹号提示,我们需要提前做一些设置,才能正常使用图集。去Project Settings中进行设置,如图:
V1、V2是两种不同的版本,选V1就好。之后返回图集数据界面去添加图像,添加图像的方式也有多种,如下(添加图像需要为Sprite类型):
添加后,点击打包:
可以看到,两张图像被打包到了一起。
代码:
- using UnityEngine;
- using UnityEngine.U2D;
- using UnityEngine.UI;
-
- public class NewBehaviourScript : MonoBehaviour
- {
- //精灵图集对象
- private SpriteAtlas m_mySpriteAtlas;
-
- //拖拽进来的图像组件,用于展示图像
- public Image m_image;
-
- private void Start()
- {
- //加载精灵图集
- m_mySpriteAtlas = Resources.Load<SpriteAtlas>("MySpriteAtlas");
- }
-
- private void Update()
- {
- //按下键盘Q键
- if (Input.GetKeyDown(KeyCode.Q))
- {
- //从图集中获取名称为“1”的图像,并赋值给Image组件
- m_image.sprite = m_mySpriteAtlas.GetSprite("1");
- //设置图像为原始尺寸
- m_image.SetNativeSize();
- }
-
- //按下键盘E键
- if (Input.GetKeyDown(KeyCode.E))
- {
- //从图集中获取名称为“testd”的图像,并赋值给Image组件
- m_image.sprite = m_mySpriteAtlas.GetSprite("testd");
- //设置图像为原始尺寸
- m_image.SetNativeSize();
- }
- }
- }
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
演示:
如图,按下Q和E键,从图集中加载不同的图像进行展示。
如果使用Untiy的默认材质,则可以把Material Creation Mode设置为None。
Edit——Project Settings——Player——勾选Optimize Mesh Data,这样一来,Unity会在构建的时候中对网格数据进行优化处理,以达到提高游戏性能的效果。但是这样往往会修改网格,我们勾选之后应该要进行测试,确保没有问题,再确定启用它。
LOD是Level of Detail的简称,意思是细节层次,它是一种优化技术。LOD的原理,就是我们可以为一个游戏对象设定多个模型,这些模型消耗的游戏性能由高到低排列。会根据摄像机距离模型的远近自动显示对应的模型。近的时候显示最精细的模型,距离中等的时候显示没那么精细的模型,远的时候显示粗糙的模型,最远的时候可以隐藏该模型。使用LOD技术能起到优化渲染性能的效果。但是使用LOD技术也会增加内存占用。
在Unity中可以使用LODGroup组件来实现LOD技术,当然资源商店也有LOD的插件,这里只讲Unity自带的LODGroup组件。把LODGroup组件添加在一个空物体身上。这个空物体身上不添加MeshRenderer组件,也不添加MeshFilter组件,但可以添加碰撞器。如果要添加刚体、脚本等。这个空物体要渲染的每一个模型都要作为它的子物体,它们的身上要添加MeshRenderer组件和MeshFilter组件,用于渲染这个模型,但是不要给它们添加碰撞器。
LOD级别LOD 0、LOD 1、LOD 2分别表示摄像机从近处看、从中等距离处看、从远处看时,所使用的模型的信息。Culled表示不渲染该模型。鼠标悬停在两个LOD级别之间,按住鼠标左键,左右拖动,可以调整LOD级别的范围。如果右击它们中的一个,点击Insert Before可以添加一个新的LOD级别到渲染条上,点击Delete,则可以删除该LOD级别。点击选中要设置的LOD级别,在Renderers下方点击Add可以选择要显示的游戏对象,点击-号可以移除该游戏对象,添加时也可以直接拖拽,另外,点开下方的LOD 0、LOD 1、LOD 2,点击+、-号也可以添加、删除模型。
演示:
Edit——Project Settings——Quality中有控制整个项目LOD的参数。
LOD Bias值,可以理解为控制整个LOD条的距离,值越大LOD条表示的距离越长,值越小距离越短。比如,Bias为2,则相机从LOD条起始到末尾的移动距离为100,若Bias为20,则这个距离值将远大于100。
Maximum LOD Level表示所有LOD Group组件最大能使用LOD级别,超过这个限制的LOD级别的模型不会显示。注意,LOD级别0大于LOD级别1,LOD级别1大于LOD级别2,依次类推。例如把这个值设置为1,则即使摄像机到物体的距离达到了LOD级别为0的范围,则也不会切换到LOD级别为0的模型来显示。例如把这个值设置为2,则即使摄像机到物体的距离达到了LOD级别为0或者LOD级别为1的范围,则也不会切换到这些模型来显示。
这里展示了一些LODGroup组件在代码中可调用内容。
- LODGroup.crossFadeAnimationDuration
- //float型。控制各个LOD级别之间进行切换的时候,用多少秒进行淡入淡出。
- //如果赋值为0或者负数,则会报错。
-
- LODGroup对象.animateCrossFading
- //bool型。控制各个LOD级别之间过渡的时候,是否有淡入淡出动画。
- //值为true,则过渡时有淡入淡出动画。
- //值为false,则过渡时没有淡入淡出动画。
-
- LODGroup对象.enabled
- //bool型。是否启用这个LODGroup组件。
- //值为true,则这个LODGroup组件才能正常工作。
- //值为false,则这个LODGroup组件将不起作用,不会根据摄像机的距离切换要渲染的模型。
-
- LODGroup对象.fadeMode
- //对应Inspector窗口的Fade Mode
- //LODFadeMode型。控制各个LOD级别之间进行切换的时候,使用怎么样的动画进行过渡。
- //LODFadeMode.None表示不使用任何过渡动画,切换LOD级别的时候,会瞬间切换。
- //LODFadeMode.CrossFade表示切换LOD级别的时候,原来的模型仍然会存在一定秒数,之后才会消失。这样可能会同时看到两个LOD级别的模型,造成不好的视觉效果。
- //LODFadeMode.SpeedTree表示切换LOD级别的时候,使用SpeedTree样式的过渡动画。
-
- LODGroup对象.localReferencePoint
- //Vector3型。用于计算LOD级别与摄像机之间的距离的本地空间的参考点。
- //Unity会自动计算这个参考点与摄像机之间的距离,并根据该距离切换到对应的LOD级别,从而渲染对应的模型。
-
- LODGroup对象.lodCount
- //int型。这个LODGroup组件的LOD级别的数量。Culled是不算在内的。
- //例如默认情况下,有LOD 0、LOD 1、LOD 2、Culled,则这个变量的值是3,因为Culled是不算在内的。
-
- LODGroup对象.size
- //对应Inspector窗口的Object Size的值。
- //float型。表示本地空间中这个LOD组件的包围区域的大小。
- //在使用LODGroup组件进行LOD级别的切换时,Unity将自动根据摄像机到包围区域表面的距离来判断要切换到哪个LOD级别,而size属性是计算此距离的重要因素之一。
-
- LODGroup对象.ForceLOD(int 要切换到的LOD级别的索引)
- //强制渲染指定LOD级别对应的模型。
- //例如要渲染LOD 0对应的模型,则传入的参数就是0。如果要渲染LOD 1对应的模型,则传入的参数就是1。
- //如果传入的参数大于这个LODGroup组件.lodCount-1,则不会渲染任何一个模型。
- //调用这个方法且传入0或正整数作为参数后,则这个LODGroup组件就不会根据摄像机的距离自动切换到对应的LOD级别了,会一直渲染这个方法指定的LOD级别对应的模型。
- //此时如果要让这个LODGroup组件重新根据摄像机的距离自动切换到对应的LOD级别,并自动渲染该LOD级别对应的模型,则可以再次调用这个方法,传入一个负整数作为参数,例如LODGroup型对象.ForceLOD(-1)。
-
- LODGroup对象.GetLODs()
- //返回LOD[]型。表示这个LODGroup组件的LOD级别的数组。
- //LOD级别的数组有哪些元素,可以在Inspecotor窗口的Object Size下方查看。
-
- LODGroup对象.RecalculateBounds()
- //对应Inspector窗口的Recalculate Bounds按钮。
- //调用之后,会重置这个LODGroup组件的包围区域。这个区域就是模型对象尺寸区域Object Size,在我们点击Reset Object Size后,就可以点击Recalculate Bounds按钮重新计算Bounds了。
- //这个方法的调用相对较慢,不要经常调用。
-
- LODGroup对象.SetLODs(LOD[]型 LOD级别的数组)
- //重新设置这个LODGroup组件的LOD级别的数组。
- //一旦调用这个方法,则这个LODGroup组件原来的LOD数组就会被整个替换掉。
- //LOD级别的数组有哪些元素,可以在Inspecotor窗口的Object Size下方查看。
-
- LOD lod=new LOD();
- //创建一个LOD级别,它是一个结构体。
-
- LOD lod=new LOD(float 用于过渡的屏幕相对高度,Renderer[] 此LOD级别要使用的渲染器的数组)
- //创建一个LOD级别,它是一个结构体。并且设置用于过渡的屏幕相对高度和渲染器的数组。
- //用于过渡的屏幕相对高度的范围是[0,1]。
-
- LOD对象.fadeTransitionWidth
- //float型。表示切换LOD界别时淡入淡出的过渡区域的宽度。
- //这个宽度与当前LOD的整个长度成比例,范围是[0,1]。
- //仅当未动画化时才使用。
-
- LOD对象.renderers
- //Renderer[]型。表示这个LOD级别的渲染器的数组。
-
- LOD对象.screenRelativeTransitionHeight
- //float型。表示这个LOD级别用于过渡的屏幕相对高度,范围是[0,1]。
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
合并网格就是把多个网格合并为一个整体,从而提升游戏性能。但是这样一来,我们就不能单独控制这些网格运动了,只能控制合并后的整个网格运动。而且合并的网格使用的材质必须是相同的,合并才可能成功,否则合并之后依然不能提升性能。
可以自己写代码,使用Unity自带的CombineMeshes方法来合并网格,也可以使用资源商店的插件,在资源商店搜Mesh Combine可以搜索到相关的插件,例如Easy Mesh Combine Tool等插件。
合并后面DrawCall可能降低,面数和顶点数可能增多,具体性能怎样要测试才知道。
恰当地设置Animator组件的Culling Mode,可设置内容:
对于Animator组件,可以使用Animator.StringToHash方法获得指定字符串的哈希值,然后保存此哈希值,后续再把它作为参数传入Animator型对象.GetXXX方法和Animator型对象.SetXXX方法中进行使用。只是起个方便作用吧。
禁用SkinMesh Renderer组件的Update When Offscreen可以让角色在不可见的时候动画不更新,这样可以减少计算量,提升性能。
不用的Animation组件和Animator组件可以考虑删掉,因为只要它们存在,就会消耗性能来检测当前的状态和过渡条件。
一些简单的动画可以使用DoTween、iTween等插件实现,而不需要每个动画都用Animator来实现。
Unity支持后缀为.wav、.ogg、.mp3的音频文件,但建议使用.wav,因为Unity对它的支持特别好。注意:Unity在构建项目时总是会自动重新压缩音频文件,因此无需刻意提前压缩一个音频文件再导入Unity,因为这样只会降低该音频文件最终的质量。
音频属性设置(选中音频后的Inspector面板):
可以使用Unity UPR对整个项目进行性能分析,找出问题后,再手动优化它们。其中Unity UPR中的Asset Checker能对本地的整个Unity项目进行性能分析,帮助我们找出问题。
Unity UPR网址:UPR - Unity专业性能优化工具
没啦。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。