如何用好Unity自带的unity profiler使用

Unity 通过WiFi调试GearVR 使用internal profiler工具
原始标题:
做Gear开发的时候发现,手机的USB口要插在头盔上,没办法用USB线连手机。不过查了一下发现,ADB是可以通过WiFi连接手机的,然后同样可以通过logcat来查看手机输出。具体方法如下:编译程序并安装到手机启用Internal Profiler打开Editor-&Project Setting-&Player,在optimization下面勾选“Enable Internal Profiler”选项。设置编译开发版本打开File-&Build Settings,在Android平台下面,勾选“Development Build”选项,然后点击Build。把生成好的apk文件安装到手机。设置使用WiFi连接手机1、手机和adb运行的计算机要同时连接到一个WiFi网络。2、用USB先把手机连接到电脑。3、设置目标设备监听TCP/IP连接,使用端口5555.$ adb tcpip 55554、把手机从USB线上拔掉。5、找到手机的IP地址,可以在查看WiFi连接的地方找到。6、通过IP地址连接手机。$ adb connect &device-ip-address&7、在电脑上确认手机已连接。$ adb devicesList of devices attached&device-ip-address&:5555 device监听程序的输出启动安装好的程序,然后命令行启动logcat,输出的内容实在太多,一定记得加上后面的选项!adb logcat -s &tag&只需要把tag为Unity的输出抓到就可以了。adb logcat -s Unity也可以把内容重定向到文件中去:adb logcat -s Unity & crash.log输出信息还是很多,最主要的是这里:原文链接:/p/b47f971b13b2注意:关注了泰斗微信公众号,想获得《用Unity5做一款即时战略游戏》等课程观看权的童鞋,可以联系晴天(QQ:)或Lisa(QQ:),他们会添加你到该课程中,感谢!感谢阅读点击下方“阅读原文”更多精彩等你来!↓↓↓
VR资源网整理出品【经验】使用Profiler工具分析内存占用情况
时间: 17:40:20
&&&& 阅读:5104
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&& & & &Unity3D为我们提供了一个强大的性能分析工具Profiler。今天我们就使用Profiler来详细分析一下官方例子AngryBots的内存使用信息数据。
&&&&&& 首先打开Profiler选择Memory选项,在游戏运行的某一帧查看Detailed选项数据(Simple模式的数据很直观,可以知道内存大体被哪部分占用了,网上也有很多相关介绍,我就不再啰嗦了),如下图所示:
选中后,unity会自动获取这一帧的内存占用数据项,主要分为:Other、Assets、BuiltinResources、Scene Memory、NotSaved这五大部分,下面我们就来一一分析。
记录数据项很多,篇幅时间有限,我们就专挑占用大小排行榜靠前的几项来详细分析吧。
System.ExecutableAndDlls:系统可执行程序和DLL,是只读的内存,用来执行所有的脚本和DLL引用。不同平台和不同硬件得到的值会不一样,可以通过修改Player Setting的Stripping
Level来调节大小。
Ricky:我试着修改了一下Stripping Level似乎没什么改变,感觉虽占用内存大但不会影响游戏运行。我们暂时忽略它吧(- -)!
GfxClientDevice:GFX(图形加速\图形加速器\显卡 (GraphicsForce Express))客户端设备。
Ricky:虽占用较大内存,但这也是必备项,没办法优化。继续忽略吧(- -)!!
ManagedHeap.UsedSize:托管堆使用大小。
Ricky:重点监控对象,不要让它超过20MB,否则可能会有性能问题!
ShaderLab:Unity自带的着色器语言工具相关资源。
Ricky:这个东西大家都比较熟悉了,忽略它吧。
SerializedFile:序列化文件,把显示中的Prefab、Atlas和metadata等资源加载进内存。
Ricky:重点监控对象,这里就是你要监控的哪些预设在序列化中在内存中占用大小,根据需求进行优化。
PersistentManager.Remapper:持久化数据重映射管理相关
Ricky:与持久化数据相关,比如AssetBundle之类的。注意监控相关的文件。
ManagedHeap.ReservedUnusedSize:托管堆预留不使用内存大小,只由Mono使用。
Ricky:无法优化。
Texture2D: 2D贴图及纹理。
Ricky:重点优化对象,有以下几点可以优化:
许多贴图采用的Format格式是ARGB 32 bit所以保真度很高但占用的内存也很大。在不失真的前提下,适当压缩贴图,使用ARGB 16 bit就会减少一倍,如果继续Android采用RGBA Compressed ETC2 8 bits(iOS采用RGBA Compressed PVRTC 4 bits),又可以再减少一倍。把不需要透贴但有alpha通道的贴图,全都转换格式Android:RGB
Compressed ETC 4 bits,iOS:RGB Compressed PVRTC 4 bits。当加载一个新的Prefab或贴图,不及时回收,它就会永驻在内存中,就算切换场景也不会销毁。应该确定物体不再使用或长时间不使用就先把物体制空(null),然后调用Resources.UnloadUnusedAssets(),才能真正释放内存。有大量空白的图集贴图,可以用TexturePacker等工具进行优化或考虑合并到其他图集中。
AudioManager:音频管理器
Ricky:随着音频文件的增多而增大。
AudioClip:音效及声音文件
Ricky:重点优化对象,播放时长较长的音乐文件需要进行压缩成.mp3或.ogg格式,时长较短的音效文件可以使用.wav 或.aiff格式。
Cubemap:立方图纹理
Ricky:这个一般在天空盒中比较常见,我也不知道如何优化这个。。。
Mesh:模型网格
Ricky:主要检查是否有重复的资源,还有尽量减少点面数。
Scene Memory
Mesh:场景中使用的网格模型
Ricky:注意网格模型的点面数,能合并的mesh尽量合并。
Builtin Resources
Ricky:这些都是Unity的一些内部资源,对于项目内存没有什么分析价值,所以我就暂时不对其进行分析了。
Profiler内存重点关注优化项目
1)ManagedHeap.UsedSize: 移动游戏建议不要超过20MB.
2)SerializedFile: 通过异步加载(LoadFromCache、WWW等)的时候留下的序列化文件,可监视是否被卸载.
3)WebStream: 通过异步WWW下载的资源文件在内存中的解压版本,比SerializedFile大几倍或几十倍,不过我们现在项目中展示没有。
4)Texture2D: 重点检查是否有重复资源和超大Memory是否需要压缩等.
5)AnimationClip: 重点检查是否有重复资源.
6)Mesh: 重点检查是否有重复资源.
项目中可能遇到的问题
1.Device.Present:
1)GPU的presentdevice确实非常耗时,一般出现在使用了非常复杂的shader.
2)GPU运行的非常快,而由于Vsync的原因,使得它需要等待较长的时间.
3)同样是Vsync的原因,但其他线程非常耗时,所以导致该等待时间很长,比如:过量AssetBundle加载时容易出现该问题.
4)Shader.CreateGPUProgram:Shader在runtime阶段(非预加载)会出现卡顿(华为K3V2芯片).
5)StackTraceUtility.PostprocessStacktrace()和StackTraceUtility.ExtractStackTrace(): 一般是由Debug.Log或类似API造成,游戏发布后需将Debug API进行屏蔽。
2.Overhead:
1)一般情况为Vsync所致.
2)通常出现在Android设备上.
3.GC.Collect:
1)代码分配内存过量(恶性的)
2)一定时间间隔由系统调用(良性的).
占用时间:
1)与现有Garbage size相关
2)与剩余内存使用颗粒相关(比如场景物件过多,利用率低的情况下,GC释放后需要做内存重排)
4.GarbageCollectAssetsProfile:
1)引擎在执行UnloadUnusedAssets操作(该操作是比较耗时的,建议在切场景的时候进行)。
2)尽可能地避免使用Unity内建GUI,避免GUI.Repaint过渡GCAllow.
3)if(other.tag == a.tag)改为pareTag(a.tag).因为other.tag为产生180B的GC Allow.
4)少用foreach,因为每次foreach为产生一个enumerator(约16B的内存分配),尽量改为for.
5)Lambda表达式,使用不当会产生内存泄漏.
5.尽量少用LINQ:
1)部分功能无法在某些平台使用.
2)会分配大量GC Allow.
6.控制StartCoroutine的次数:
1)开启一个Coroutine(协程),至少分配37B的内存.
2)Coroutine类的实例 -& 21B.
3)Enumerator -& 16B.
7.使用StringBuilder替代字符串直接连接.
8.缓存组件:
1)每次GetComponent均会分配一定的GC Allow.
2)每次Object.name都会分配39B的堆内存.
Ricky Yang个人原创,版权所有,转载注明,谢谢。http://blog.csdn.net/yangyy753
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:&&&&&&&&&&&&&&&原文:http://blog.csdn.net/yangyy753/article/details/
教程昨日排行
&&国之画&&&& &&&&&&
&& &&&&&&&&&&&&&&
鲁ICP备号-4
打开技术之扣,分享程序人生!总结使用Unity 3D优化游戏运行性能的经验
发布时间: 17:44:42
Tags:,,,,
作者:Amir Fasshihi
流畅的游戏玩法来自流畅的帧率,而我们即将推出的动作平台游戏《Shadow Blade》已经将在标准iPhone和iPad设备上实现每秒60帧视为一个重要目标。
以下是我们在紧凑的优化过程中提升游戏运行性能,并实现目标帧率时需要考虑的事项。
当基本游戏功能到位时,就要确保游戏运行表现能够达标。我们衡量游戏运行表现的一个基本工具是Unity内置分析器以及Xcode分析工具。使用Unity分析器来分析设备上的运行代码真是一项宝贵的功能。
我们总结了这种为将目标设备的帧率控制在60fps而进行衡量、调整、再衡量过程的中相关经验。
shadow blade()
一、遇到麻烦时要调用“垃圾回收器”(Garbage Collector,无用单元收集程序,以下简称GC)
由于具有C/C++游戏编程背景,我们并不习惯无用单元收集程序的特定行为。确保自动清理你不用的内存,这种做法在刚开始时很好,但很快你就公发现自己的分析器经常显示CPU负荷过大,原因是垃圾回收器正在收集垃圾内存。这对移动设备来说尤其是个大问题。要跟进内存分配,并尽量避免它们成为优先数,以下是我们应该采取的主要操作:
1.移除代码中的任何字符串连接,因为这会给GC留下大量垃圾。
2.用简单的“for”循环代替“foreach”循环。由于某些原因,每个“foreach”循环的每次迭代会生成24字节的垃圾内存。一个简单的循环迭代10次就可以留下240字节的垃圾内存。
3.更改我们检查游戏对象标签的方法。用“if (go.CompareTag (“Enemy”)”来代替“if (go.tag == “Enemy”)” 。在一个内部循环调用对象分配的标签属性以及拷贝额外内存,这是一个非常糟糕的做法。
4.对象库很棒,我们为所有动态游戏对象制作和使用库,这样在游戏运行时间内不会动态分配任何东西,不需要的时候所有东西反向循环到库中。
5.不使用LINQ命令,因为它们一般会分配中间缓器,而这很容易生成垃圾内存。
二、谨慎处理高级脚本和本地引擎C++代码之间的通信开销。
所有使用Unity3D编写的游戏玩法代码都是脚本代码,在我们的项目中是使用Mono执行时间处理的C#代码。任何与引擎数据的通信需求都要有一个进入高级脚本语言的本地引擎代码的调用。这当然会产生它自己的开销,而尽量减少游戏代码中的这些调用则要排在第二位。
1.在这一情景中四处移动对象要求来自脚本代码的调用进入引擎代码,这样我们就会在游戏玩法代码的一个帧中缓存某一对象的转换需求,并一次仅向引擎发送一个请求,以便减少调用开销。这种模式也适用于其他相似的地方,而不仅局限于移动和旋转对象。
2.将引用本地缓存到元件中会减少每次在一个游戏对象中使用 “GetComponent” 获取一个元件引用的需求,这是调用本地引擎代码的另一个例子。
三、物理效果
1.将物理模拟时间步设置到最小化状态。在我们的项目中就不可以将让它低于16毫秒。
2.减少角色控制器移动命令的调用。移动角色控制器会同步发生,每次调用都会耗损极大的性能。我们的做法是缓存每帧的移动请求,并且仅运用一次。
3.修改代码以免依赖“ControllerColliderHit” 回调函数。这证明这些回调函数处理得并不十分迅速。
4.面对性能更弱的设备,要用skinned mesh代替physics cloth。cloth参数在运行表现中发挥重要作用,如果你肯花些时间找到美学与运行表现之间的平衡点,就可以获得理想的结果。
5.在物理模拟过程中不要使用ragdolls,只有在必要时才让它生效。
6.要谨慎评估触发器的“onInside”回调函数,在我们的项目中,我们尽量在不依赖它们的情况下模拟逻辑。
7.使用层次而不是标签。我们可以轻松为对象分配层次和标签,并查询特定对象,但是涉及碰撞逻辑时,层次至少在运行表现上会更有明显优势。更快的物理计算和更少的无用分配内存是使用层次的基本原因。
8.千万不要使用Mesh对撞机。
9.最小化碰撞检测请求(例如ray casts和sphere checks),尽量从每次检查中获得更多信息。
四、让AI代码更迅速
我们使用AI敌人来阻拦忍者英雄,并同其过招。以下是与AI性能问题有关的一些建议:
1.AI逻辑(例如能见度检查等)会生成大量物理查询。可以让AI更新循环设置低于图像更新循环,以减少CPU负荷。
五、最佳性能表现根本就不是来自代码!
没有发生什么情况的时候,就说明性能良好。这是我们关闭一切不必要之物的基本原则。我们的项目是一个侧边横向卷轴动作游戏,所以如果不具有可视性时,就可以关闭许多动态关卡物体。
1.使用细节层次的定制关卡将远处的敌人AI关闭。
2.移动平台和障碍,当它们远去时其物理碰撞机也会关闭。
3.Unity内置的“动画挑选”系统可以用来关闭未被渲染对象的动画。
4.所有关卡内的粒子系统也可以使用同样的禁用机制。
六、回调函数!那么空白的回调函数呢?
要尽量减少Unity回调函数。即使敌人回调函数存在性能损失。没有必要将空白的回调函数留在代码库中(有时候介于大量代码重写和重构之间)。
七、让美术人员来救场
在程序员抓耳挠腮,绞尽脑汁去想该如何让每秒运行更多帧时,美术人员总能神奇地派上大用场。
1.共享游戏对象材料,令其在Unity中处于静止状态,可以让它们绑定在一起,由此产生的简化绘图调用是呈现良好移动运行性能的重要元素。
2.纹理地图集对UI元素来说尤其有用。
3.方形纹理以及两者功率的合理压缩是必不可少的步骤。
4.我们的美术人员移除了所有远处背景的网格,并将其转化为简单的2D位面。
5.光照图非常有价值。
6.我们的美术人员在一些关口移除了额外顶点。
7.使用合理的纹理mip标准是一个好主意(游戏邦注:要让不同分辨率的设备呈现良好的帧率时尤其如此)。
8.结合网格是美术人员可以发挥作用的另一个操作。
9.我们的动画师尽力让不同角色共享动画。
10.要找到美学/性能之间的平衡,就免不了许多粒子效果的迭代。减少发射器数量并尽量减少透明度需求也是一大挑战。
八、要减少内存使用
使用大内存当然会对性能产生负面影响,但在我们的项目中,我们的iPod由于超过内存上限而遭遇了多次崩溃事件。我们的游戏中最耗内存的是纹理。
1.不同设备要使用不同的纹理大小,尤其是UI和大型背景中的纹理。《Shadow Blade》使用的是通用型模板,但如果在启动时检测到设备大小和分辨率,就会载入不同资产。
2.我们要确保未使用的资产不会载入内存。我们必须迟一点在项目中找到仅被一个预制件实例引用,并且从未完全载入内存中实例化的资产。
3.去除网格中的额外多边形也能实现这一点。
4.我们应该重建一些资产的生周期管理。例如,调整主菜单资产的加载/卸载时间,或者关卡资产、游戏音乐的有效期限。
5.每个关卡都要有根据其动态对象需求而量身定制的特定对象库,并根据最小内存需求来优化。对象库可以灵活一点,在开发过程中包含大量对象,但知道游戏对象需求后就要具体一点。
6.保持声音文件在内存的压缩状态也是必要之举。
加强游戏运行性能是一个漫长而具有挑战性的过程,游戏开发社区所分享的大量知识,以及Unity提供的出色分析工具为《Shadow Blade》实现目标运行性能提供了极大帮助。(本文为游戏邦/编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦)
“0 – 60 fps in 14 days!” What we learned trying to optimize our game using Unity3D.
by Amir Fassihi
The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.
A smooth gameplay is built upon the foundations of a smooth frame rate and hitting the 60 frames per second target on the standard iPhone and iPad devices was a significant goal during the development of our upcoming action platformer game, Shadow Blade. ()
The following is a summary from the things we had to consider and change in the game in order to increase the performance and reach the targeted frame rate during the intense optimization sessions.
Once the basic game functionalities were in place, it was time to make sure the game performance would meet its target. Our main tool for measuring the performance was the built-in Unity profiler and the Xcode profiling tools. Being able to profile the running code on the device using the Unity profiler proved to be an invaluable feature.
So here goes our summary and what we learned about the results of this intense measuring, tweaking and re-measuring journey which paid out well at the end and resulted in a fixed 60fps for our target devices.
1 – Head to head with a ferocious monster called the Garbage Collector.
Coming from a C/C++ game programming background, we were not used to the specific behaviors of the garbage collector. Making sure your unused memory is cleaned up automatically for you is nice at first but soon the reality kicks in and you witness regular spikes in your profiler showing the CPU load caused by the garbage collector doing what it is supposed to do, collecting the garbage memory. This proved to be a huge issue specifically for the mobile devices. Chasing down memory allocations and trying to eliminate them became priority number one and here are some of the main actions we took:
Remove any string concatenation in code since this leaves a lot of garbage for the GC to collect.
Replace the “foreach” loops with simple “for” loops. For some reason, every iteration of every “foreach” loop generated 24 Bytes of garbage memory. A simple loop iterating 10 times left 240 Bytes of memory ready to be collected which was just unacceptable
Replace the way we checked for game object tags. Instead of “if (go.tag == “Enemy”)” we used “if (go.CompareTag (“Enemy”)”. Calling the tag property on an object allocates and copies additional memory and this is really bad if such a check resides in an inner loop.
Object pools are great, we made and used pools for all dynamic game objects so that nothing is ever allocated dynamically during the game runtime in the middle of the levels and everything is recycled back to the pool when not needed.
Not using LINQ commands since they tended to allocate intermediate buffers, food for the GC.
2 – Careful with the communication overhead between high level scripts and native engine C++ code.
All gameplay code written for a game using Unity3D is script code which in our case was C# that was handled using the Mono runtime. Any requirements to communicate with the engine data would require a call into the native engine code from the high level scripting language. This of course has its own overhead and trying to reduce such calls in game code was the second priority.
Moving objects around in the scene requires calls from the script code to the engine code and we ended up caching the transformation requirements for an object during a frame in the gameplay code and sending the request to the engine only once to reduce the call overhead. This pattern was used in other similar places other than the needs to move and rotate an object.
Caching references to components locally would eliminate the need to fetch a component reference using the “GetComponent” method on a game object every time which is another example for a call into the native engine code.
3 – Physics, Physics and more Physics.
Setting the physics simulation timestep to the minimum possible. For our case we could not set it lower than 16 milliseconds.
Reducing calls to character controller move commands. Moving the character controller happens synchronously and every call can have a significant performance cost. What we did was to cache the movement requests per frame and apply them only once.
Modifying code to not rely on the “ControllerColliderHit” callbacks. It proved that these callbacks are not handled very quickly.
Replacing the physics cloth with a skinned mesh for the weaker devices. The cloth parameters can play important roles in performance also and it pays off to spend some time to find the appropriate balance between aesthetics and performance.
Ragdolls were disabled so that they were not part of the physics simulation loop and only enabled when necessary.
“OnInside” callbacks of the triggers need to be assessed carefully and in our case we tried to model the logic without relying on them if possible.
Layers instead of tags! Layers and tags can be assigned to objects easily and used for querying specific objects, however, layers have a definite advantage at least performance wise when it comes to working with collision logic. Quicker physics calculations and less unwanted newly allocated memory are the basic reasons.
Mesh colliders are definitely a no-no.
Minimize collision detection requests like ray casts and sphere checks in general and try to get as much information from each check.
4 – Let’s make the AI code faster!
We use artificial intelligence for the enemies that try to block our main ninja hero and fight with him. The following topics needed to be covered regarding AI performance issues:
A lot of physical queries are generated from AI logic like visibility checks. The AI update loop could be set to something much lower than the graphics update loop to reduce CPU load.
5 – Best performance is achieved from no code at ALL!
When nothing happens, performance is good. This was the base philosophy for us to try and turn anything not necessary at the moment off. Our game is a side scroller action game and so a lot of the dynamic level objects can be turned off when they are not visible in the scene.
Enemy AI was turned off when far away using a custom level of detail scheme.
Moving platforms and hazards and their physics colliders were turned off when far away.
Built in Unity “animation culling” system was used to turn off animations on objects not being rendered.
Same disabling mechanism used for all in level particle systems.
6 – Callback! How about empty callbacks?
The Unity callbacks needed to be reduced as much as possible. Even the empty callbacks had performance penalties. There is no reason for having empty callbacks but they just get left in the code base sometimes in between a lot of code rewrite and refactoring.
7 – The mighty Artists to the rescue.
Artists can always magically help out the hair-pulling programmer trying to go for a few more frames per second.
Sharing materials for game objects and making them static in Unity causes them to be batched together and the resulting reduced draw calls are critical for good mobile performance.
Texture atlases helped a lot especially for the UI elements.
Square textures and power of two with proper compression was a must.
Being a side-scroller enabled our artists to remove all far background meshes and convert them to simple 2D planes instead.
Light maps were highly valuable.
Our artists removed extra vertices during a few passes.
Proper texture mip levels were a good decision especially for having a good frame rate on devices with different resolutions.
Combining meshes was another performance friendly action by the artists.
Our animator tried to share animations between different characters if it was possible.
A lot of iterations on the particles were necessary to find the aesthetic/performance balance. Reducing number of emitters and trying to reduce transparency requirements were among the major challenges.
8 – The memory usage needs to be reduced, now!
Using a lot of memory of course has negative performance related effects but in our case we experienced a lot of crashes on iPods due to exceeding memory limits which was a much more critical problem. The biggest memory consumers in our game were the textures.
Different texture sizes were used for different devices, especially textures used in UI and large backgrounds. Shadow Blade uses a universal build but different assets get loaded when the device size and resolution is detected upon startup.
We needed to make sure un-used assets were not loaded in memory. We had to find out a little late in the project that any asset that was only referenced by an instance of a prefab and never instantiated was fully loaded in memory.
Stripping out extra polygons from meshes helped.
We needed to re-architect the lifecycle management of some assets a few times. For example tweaking the load/unload time for the main menu assets or end of level assets or game music.
Each level needed to have its specific object pool tailored to its dynamic object requirements and optimized for the least memory needs. Object pools can be flexible and contain a lot of objects during development, however, they need to be specific once the game object requirements are known.
Keeping the sound files compressed in memory was necessary.
Game performance enhancement is a long and challenging journey and we had a fun time experiencing a small part of this voyage. The vast amount of knowledge shared by the game development community and very good profiling tools provided by Unity were what made us reach our performance targets for Shadow Blade.(source:)
CopyRight Since 2010 GamerBoom All rights reserved &&闽ICP备&号-1

我要回帖

更多关于 unity profiler 的文章

 

随机推荐