首页 > 技术文章 > Unity优化整理资料总结

wanglufly 2014-12-08 12:24 原文

1. 更新不透明贴图的压缩格式为ETC 4bit,因为android市场的手机中的GPU有多种,
每家的GPU支持不同的压缩格式,但他们都兼容ETC格式,

2. 对于透明贴图,我们只能选择RGBA 16bit 或者RGBA 32bit。

3. 减少FPS,在ProjectSetting-> Quality中的
VSync Count 参数会影响你的FPS,EveryVBlank相当于FPS=60,EverySecondVBlank = 30;
这两种情况都不符合游戏的FPS的话,我们需要手动调整FPS,首先关闭垂直同步这个功能,然后在代码的Awake方法里手动设置FPS(Application.targetFrameRate = 45;)
降低FPS的好处:
1)省电,减少手机发热的情况;
2)能都稳定游戏FPS,减少出现卡顿的情况。

4. 当我们设置了FPS后,再调整下Fixed timestep这个参数,
这个参数在ProjectSetting->Time中,目的是减少物理计算的次数,来提高游戏性能。

5. 尽量少使用Update LateUpdate FixedUpdate,这样也可以提升性能和节省电量。
多使用事件(不是SendMessage,使用自己写的,或者C#中的事件委托)。

6. 待机时,调整游戏的FPS为1,节省电量。

7. 图集大小最好不要高于1024,否则游戏安装之后、低端机直接崩溃、原因是手机系统版本低于2.2、超过1000的图集无法读取、导致。
2.2 以上没有遇见这个情况。
注意手机的RAM 与 ROM、小于 512M的手机、直接放弃机型适配。

VSCount 垂直同步
   unity3d中新建一个场景空的时候,帧速率(FPS总是很低),大概在60~70之间。
一直不太明白是怎么回事,现在基本上明白了。我在这里解释一下原因,如有错误,欢迎指正。
在Unity3D中当运行场景打开Profiler的时候,我们会看到VSync 这一项占了很大的比重。
这个是什么呢,这个就是垂直同步,稍后再做解释。
我们可以关闭VSync来提高帧速率,选择edit->project settings->Quality。

<ignore_js_op>

 


在右侧面板中可以找到VSync Count,把它选成Don't Sync。
<ignore_js_op> 
这就关闭了VSync(垂直同步),现在在运行场景看看,帧速率是不是提高很多。

现在来说说什么是垂直同步,要知道什么是垂直同步,必须要先明白显示器的工作原理,
显示器上的所有图像都是一线一线的扫描上去的,无论是隔行扫描还是逐行扫描,
显示器都有两种同步参数——水平同步和垂直同步。

什么叫水平同步?什么叫垂直同步?
垂直和水平是CRT中两个基本的同步信号,水平同步信号决定了CRT画出一条横越屏幕线的时间,
垂直同步信号决定了CRT从屏幕顶部画到底部,再返回原始位置的时间,
而恰恰是垂直同步代表着CRT显示器的刷新率水平。

为什么关闭垂直同步信号会影响游戏中的FPS数值?
如果我们选择等待垂直同步信号(也就是我们平时所说的垂直同步打开),
那么在游戏中或许强劲的显卡迅速的绘制完一屏的图像,但是没有垂直同步信号的到达,
显卡无法绘制下一屏,只有等85单位的信号到达,才可以绘制。
这样FPS自然要受到操作系统刷新率运行值的制约。

而如果我们选择不等待垂直同步信号(也就是我们平时所说的关闭垂直同步),那么游戏中作完一屏画面,
显卡和显示器无需等待垂直同步信号就可以开始下一屏图像的绘制,自然可以完全发挥显卡的实力。
但是不要忘记,正是因为垂直同步的存在,才能使得游戏进程和显示器刷新率同步,使得画面更加平滑和稳定。
取消了垂直同步信号,固然可以换来更快的速度,但是在图像的连续性上势必打折扣。
这也正是很多朋友抱怨关闭垂直后发现画面不连续的理论原因。

合并材质球unity 3d中每倒入一次模型就多一个材质球,可我的这些模型都是共用一张贴图的就想共用一个材质球,所以每次都要删除再附上,很麻烦。怎么才能合并这些材质球?
采用TexturePacking吧
1、遍历gameobject,取出material,并根据shader来将material分类
2、调用Unity自带的PackTextures函数来合并每个shader分类中的material所对应的textures(PackTextures函数有缺陷,不过可以将就用)
3、根据合并的大的texture来更新原有模型的texture、material已经uv坐标值。

需要注意的是:需要合并的纹理应该是物体在场景中距离相近的,如果物体在场景中的距离较远,
则不建议合并纹理,因为这样做很有可能非但起不到优化的作用,反而降低了运行效率。 

mesh合并 
分为2种方式合并
1.自带的合并必须勾选静态。
<ignore_js_op> 
所有被勾选了“Static”的GameObject,其中的Mesh Filter中的mesh都会被合并到 "Combined Mesha (root: scene)" 中


2.也可以用脚本来合并mesh 。

[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
using UnityEngine;
using System.Collections;
 
public class MyClass : MonoBehaviour
{
    void Start ()
    {
        MeshFilter [] meshFilters = GetComponentsInChildren<MeshFilter> ();
        CombineInstance[] combine = new CombineInstance[meshFilters.Length];
 
        for (int i = 0; i < meshFilters.Length; i++) {
            combine [i].mesh = meshFilters [i].sharedMesh;
            combine [i].transform = meshFilters [i].transform.localToWorldMatrix;
            meshFilters [i].gameObject.active = false;
        }
 
            transform.GetComponent<MeshFilter> ().mesh = new Mesh ();
            transform.GetComponent<MeshFilter> ().mesh.CombineMeshes (combine);
            transform.gameObject.active = true;
    }
}


1. 先在 Unity 中建立 空物件 ( Empty ) 
2. 再创建2个 Cube 方块,并放入 空物件底下 (可以改成你自己的模型)
3. 把 MyClass 代码丟进 空物件上 。
4. (可选) 建立一个 Material 材质,并且丢进 空物件上
5. 执行

<ignore_js_op> 


<ignore_js_op> 
========================================分割线====================================

  • 角色Material数量
2-3
  • 骨骼数量
小于30个
  • 面片数量
300-1500
  • 一般角色应该没有IK结点
这是因为角色的动作大多数都是事先设定好的,并不需要经过IK操作来进行实时计算(Rogdoll除外),所以在模型导入时,不要将IK结点一起导入。

 

2、静态实体

  • 不要附加Animation Component
在静态实体上附加Animation部件虽然对结果没有影响,但却会增加一定的CPU开销来调用这一组件,所以尽量去掉该组件。
  • 网格顶点数
小于500
  • UV值范围尽量不要超过(0, 1)区间
尽量保证UV值不越界,这对于将来的纹理拼合优化很有帮助。

 

3、地形

  • 地形的分辨率大小
长宽均尽量小于257。这是因为地形太大,会造成大量顶点数据,给你的内存带宽造成一定的影响,在目前的ios设备中,内存带宽是非常有限的,需要尽量节省。同时,如果用Unity自带的地形,一定也要使用Occlusion Culling,因为Unity的刷地形工具虽然方便,但却是framekiller,刷过之后,你会发现drawcall增加的非常多。
  • 混合纹理数量
不要超过4。地形的混合操作是很耗时的,应该尽量避免。能合并的纹理尽量合并。

 

4、纹理

  • 纹理格式
建议png或tga。不用转成ios硬件支持的PVRTC格式,因为Unity在发布时会帮你自动转的。
  • 纹理尺寸
长宽小于1024。同时应该尽可能地小,够用就好,以保证纹理对内存带宽的影响达到最小。
  • 支持Mipmap
建议生成Mipmap。虽然这种做法会增加一些应用程序的大小,但在游戏运行时,系统会根据需求应用Mipmap来渲染,从而减少内存带宽。
  • 检查Alpha值
如果纹理的alpha通道均为1,则用RGB的24位纹理来代替RGBA的32位纹理。(据说Unity内部会进行自动检测)

 

5、光源

  • 光源“Important”个数
建议1个,一般为方向光。“Important”个数应该越小越少。个数越多,drawcall越多。
  • Pixel Light数目
1-2个。

 

6、粒子特效

  • 屏幕上的最大粒子数
建议小于200个粒子。
  • 每个粒子发射器发射的最大粒子数
建议不超过50个。
  • 粒子大小
如果可以的话,粒子的size应该尽可能地小。因为Unity的粒子系统的shader无论是alpha test还是alpha blending都是一笔不小的开销。同时,对于非常小的粒子,建议粒子纹理去掉alpha通道。
  • 尽量不要开启粒子的碰撞功能。
非常耗时。

 

7、音频

  • 游戏中播放时间较长的音乐(如背景音乐)
使用.ogg或.mp3的压缩格式。
  • 较短音乐(如枪声)
使用.wav和.aif的未压缩音频格式。

 

8、相机

  • 裁剪平面
将远平面设置成合适的距离。远平面过大会将一些不必要的物体加入渲染,降低效率。
  • 根据不同的物体设置不同的远裁剪平面
Unity提供了可以根据不同的layer来设置不同的view distance,所以我们可以实现将物体进行分层,大物体层设置的可视距离大些,而小物体层可以设置地小些,另外,一些开销比较大的实体(如粒子系统)可以设置得更小些等等。

 

9、碰撞

  • 尽量不用MeshCollider
如果可以的话,尽量不用MeshCollider,以节省不必要的开销。如果不能避免的话,尽量用减少Mesh的面片数,或用较少面片的代理体来代替。

 

10、其他

  • Drawcall
尽可能地减少Drawcall的数量。IOS设备上建议不超过100。减少的方法主要有如下几种:Frustum Culling,Occlusion Culling,Texture Packing。Frustum Culling是Unity内建的,我们需要做的就是寻求一个合适的远裁剪平面;Occlusion Culling,遮挡剔除,Unity内嵌了Umbra,一个非常好OC库。但Occlusion Culling也并不是放之四海而皆准的,有时候进行OC反而比不进行还要慢,建议在OC之前先确定自己的场景是否适合利用OC来优化;Texture Packing,或者叫Texture Atlasing,是将同种shader的纹理进行拼合,根据Unity的static batching的特性来减少draw call。建议使用,但也有弊端,那就是一定要将场景中距离相近的实体纹理进行拼合,否则,拼合后很可能会增加每帧渲染所需的纹理大小,加大内存带宽的负担。这也就是为什么会出现“DrawCall降了,渲染速度也变慢了”的原因。

 

  • 非运动物体尽量打上Static标签
Unity在运行时会对static物体进行自动优化处理,所以应该尽可能将非运行实体勾上static标签。

 

  • 场景中尽可能地使用prefab
尽可能地使用prefab的实例化物体,以降低内存带宽的负担。检查实体的PrefabType,尽量将其变成PrefabInstance,而不是ModelPrefabInstance。



========================================分割线==================================== 

移动平台相对于PC机,具有体积小,计算弱,带宽少的特点。

因此做手机游戏的开发,优化的方向,与力度对比PC游戏都有所区别。

 

必须要做到优化流程,合理利用资源。

目前在手机上面,还不能够像PC游戏那样追求高质量渲染效果,为了让手机不那么容易发烫,还要控制cpu,gpu,不能让他们全速运算。

 

材质方面:

纹理方面,建议使用压缩纹理,

Android上面使用ETC1,苹果上面使用PVRTC。

 

UV坐标控制在0到1之间,人物模型面数控制在1500内,骨骼控制在30个以内。

场景中使用一个主光(不能再多了)。

 

尽量减少alphaTest和alphaBlend材质的使用。在手机上,这是很杀效率的。

 

骨骼动画方面:

在动画方面可以考虑不使用插值,固定的帧率的动画。

如果要做插值,考虑使用四元数(表示旋转)和向量(表示位移)来做插值。

四元数做插值速度比矩阵来的快,Slerp提供了平滑插值。



========================================分割线==================================== 

优化的常规技巧
剖析你的游戏。
不要花费时间来优化那些晦涩的代码或者缩减图形文件的大小,除非这是你游戏的瓶颈。
第一次剖析你的游戏将会使你发现你游戏的瓶颈。Apple's Shark是一个很好的用来剖析基于OpenGL的程序的工具。
再次剖析你的游戏。
优化之后不要忘记再剖析一次你的游戏,这样可以检查你所做的优化是否达到了预期的效果。
当然,这样做也可能会使你发现更多的瓶颈。
流程第一、性能第二。花费时间来使你游戏的创建尽可能地流畅。
尽可能快地修正游戏中的错误将会使你后期更容易优化你的游戏。
在Scene View中测试场景。
这样做将会使你清楚了解这个场景中的物体或者附加在物体上的脚本是否降低了游戏性能。
如果Scene View反应迟钝,那么有可能是图形方面的原因,如果Scene View反应不迟钝,那么瓶颈可能出在脚本或者物理系统上。
禁用指定游戏物体。
在play模式下,尝试禁用并启用游戏物体来排查出游戏慢的原因。

网格
如果可能的话,把相邻的物体(网格)合并为一个只有一个材质的物体(网格)。比如,你的游戏中包含一个桌子,上面有一堆东西,你完全可以在3D程序中将它们合并在一起(这可能也需要你将这些物体的纹理合并为一个大的纹理集)。减少需要渲染的物体的数量可以极大地提高游戏性能。

不要有不必要的网格。
如果你的游戏场景中有一个人物,那么他应该是一个网格。如果你有一个船,那么它也应该只是一个网格。
每一个网格只用一种材质。
使用极少的面数的网格(比如500个多边形以下)。
最好把你人物的三角面数量控制在1500-2000个之间。
这个数量可以说是游戏质量和性能之间一个均衡值。如果你的模型有四边形,那么在导入模型的时候,引擎将会把每个四边形变为两个三角形。

光照
像素光。
像素光可以让你的游戏看起来效果很牛逼,但是不要使用过多的像素光。
在你的游戏中可以使用质量管理器来调节像素光的数量来取得一个性能和质量的均衡点.

性能占用顺序:聚光灯>点光源>平行光。
一个好的点亮场景的方法就是先得到你想要的效果,然后看看哪些光更重要;
在保持光效的前提下看看哪些光可以去掉。

点光源和聚光灯只影响它们范围内的网格。
如果一个网格处于点光源或者聚光灯的照射范围之外,并且光源的attenuate开关是打开的,那么这个网格将不会被光源所影响,这样就可以节省性能开销。
这样做理论上来讲可以使用很多小的点光源而且依然能有一个好的性能,因为这些光源只影响一小部分物体。
一个网格在有8个以上光源影响的时候,只响应前8个最亮的光源。

贴图
在外观不变的前提下,贴图大小越小越好。
如果你的显卡的显存不够大的话,你游戏中的贴图将会被转存到系统内存中,在显卡调用它们的时候再传到显卡中。
对于比较新的电脑来说,内存和显卡之间有足够的带宽来达到一个很好的性能;
如果你很无耻地用了巨多的大图片的话,在低显存的电脑上运行你的游戏的时候,你的游戏必然会挂掉。
倒是没有必要在图形编辑软件中调整贴图的大小。你可以在unity导入贴图的时候进行调整。

不要使用低质量的图片。
在小播放界面的游戏中使用低质量的jpeg图片或者低色彩的png图片亦或是gif图片没什么问题
在发布游戏的时候,引擎会自动压缩这些图片,多重压缩和解压将会降低图片的质量,所以最好保持贴图文件的分辨率为原始分辨率。
这样就会减少多重压缩和解压所导致的图片失真现象。

Shaders
多重效果的shader就比看起来样式很单一的shader要更耗费资源。
同样在一个拥有贴图和光反射的物体上,使用VertexLit Diffuse shader无疑是最省资源的。


========================================分割线==================================== 

在美术制作场景的过程中,会使用到大量的粒子系统。
比如场景中的火把。在我们的一个地下城场景中,美术们放置了大量的火把。整个场景中的各个地方,有100来个火把。

unity中,在摄像机范围外的粒子系统虽然不会被绘制。
但是update是一直持续的。这也就意味着,这100多个火把,不论是否可见都在更新。

这个设计应该是很不合理的,在我看过的其他引擎中,都会有一个开关,来控制不可见的粒子系统是否需要update。
有的粒子系统在不可见的时候需要更新,比如爆炸。有的不需要更新,比如火堆火把。

为了避免不必要的update开销,尤其是最后游戏是要发布到页游平台(web player只能使用一个cpu的核)。
于是写了一个脚本,控制不可见的粒子系统就不更新。

该脚本主要是用到了2个MonoBehaviour的函数。
OnBecameInvisible() 当变为不可见   和   OnBecameVisible() 当变成可见。 

要这2个函数起作用的前提是,该GameObject绑定了MeshRender组件。
所以,我们要在粒子系统的GameObject放置在一个GameObject  下,且给该GameObject绑定一个MeshRender 与 MeshFilter。
MeshFilter中的mesh可以随便找个cube。

在Start() 的时候,把最GameObject的scale设置为很小,以保证该cube不被看见。
其实遍历所有的child,把active设置为false。

在OnBecameVisible 中 遍历所有child,把active设置为true。
在OnBecameInvisible中 遍历所有child,把active设置为false。

转自:http://www.unitymanual.com/thread-24302-1-1.html

 

流畅的游戏玩法来自流畅的帧率,而我们即将推出的动作平台游戏《Shadow Blade》已经将在标准iPhone和iPad设备上实现每秒60帧视为一个重要目标。

以下是我们在紧凑的优化过程中提升游戏运行性能,并实现目标帧率时需要考虑的事项。

当基本游戏功能到位时,就要确保游戏运行表现能够达标。我们衡量游戏运行表现的一个基本工具是Unity内置分析器以及Xcode分析工具。使用Unity分析器来分析设备上的运行代码真是一项宝贵的功能。

我们总结了这种为将目标设备的帧率控制在60fps而进行衡量、调整、再衡量过程的中相关经验。

shadow blade(from deadmage.com)

shadow blade(from deadmage.com)

一、遇到麻烦时要调用“垃圾回收器”(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》实现目标运行性能提供了极大帮助。

转自http://gamerboom.com/archives/76214

 

1、在使用数组或ArrayList对象时应当注意

[csharp] view plaincopy
 
  1. length=myArray.Length;  
  2.   
  3. for(int i=0;i<length;i++)  
  4.   
  5. {  
  6.   
  7. }  

避免

[csharp] view plaincopy
 
  1. for(int i=0;i<myArray.Length;i++)  
  2.   
  3.  {  
  4.   
  5. }  

2、如果没有必要每帧都处理,则可以每隔几帧处理一次

[csharp] view plaincopy
 
  1. void Update(){ if(Time.frameCount%6==0) { DoSomething(); }}  


3、定时重复调用可以使用InvokeRepeating函数实现,比如,启动0.5秒后每隔1秒执行一次 DoSomeThing 函数:

[csharp] view plaincopy
 
  1. void Start()   
  2. {        
  3.  InvokeRepeating("DoSomeThing", 0.5f, 1.0f);  
  4. }   


4、少使用临时变量,特别是在Update OnGUI等实时调用的函数中。

[csharp] view plaincopy
 
  1. void Update()  
  2. {  
  3.    Vector3 pos;  
  4.    pos=transform.position;  
  5. }  

可以改为:

[csharp] view plaincopy
 
  1. private Vector3 pos;  
  2. void Update()  
  3. {  
  4.    pos=transform.position;  
  5. }  

5、主动进行垃圾回收

[csharp] view plaincopy
 
  1. void Update()  
  2. {  
  3.     if(Time.frameCount%50==0)  
  4.     {   
  5.       System.GC.Collection();  
  6.     }  
  7. }  


6、优化数学运算,尽量避免使用float,而使用int,特别是在手机游戏中,尽量少用复杂的数学函数,比如sin,cos等函数。改除法/为乘法,例如:使用x*0.5f而不是 x/2.0f 。

7、压缩 Mesh  

导入 3D 模型之后,在不影响显示效果的前提下,最好打开 Mesh Compression。  Off, Low, Medium, High 这几个选项,可酌情选取。对于单个Mesh最好使用一个材质。

8、 运行时尽量减少 Tris 和 Draw Calls  

      预览的时候,可点开 Stats,查看图形渲染的开销情况。特别注意 Tris 和 Draw Calls 这两个参数。  一般来说,要做到:  Tris 保持在 7.5k 以下  ,Draw Calls 保持在 35 以下。

9、避免大量使用 Unity 自带的 Sphere 等内建 Mesh  

      Unity 内建的 Mesh,多边形的数量比较大,如果物体不要求特别圆滑,可导入其他的简单3D模型代替。 

10、如果可能,将GameObject上不必要的脚本disable掉。如果你有一个大的场景在你的游戏中,并且敌方的位置在数千米意外,这是你可以disable你的敌方AI脚本直到它们接近摄像机为止。一个好的途径来开启或关闭GameObject是使用SetActiveRecursively(false),并且球形或盒型碰撞器设为trigger。

11、删除空的Update方法。当通过Assets目录创建新的脚本时,脚本里会包括一个Update方法,当你不使用时删除它。
12、引用一个游戏对象的最合乎逻辑的组件。有人可能会这样写someGameObject.transform,gameObject.rigidbody.transform.gameObject.rigidbody.transform,但是这样做了一些不必要的工作,你可以在最开始的地方引用它,像这样:

privateTransform myTrans;

void Start()

{

    myTrans=transform;

}

 

13、协同是一个好方法。可以使用协同程序来代替不必每帧都执行的方法。(还有InvokeRepeating方法也是一个好的取代Update的方法)。

14、尽可能不要再Update或FixedUpdate中使用搜索方法(例如GameObject.Find()),你可以像前面那样在Start方法里获得它。

15、不要使用SendMessage之类的方法,他比直接调用方法慢了100倍,你可以直接调用或通过C#的委托来实现。

16、使用javascript或Boo语言时,你最好确定变量的类型,不要使用动态类型,这样会降低效率,你可以在脚本开头使用#pragmastrict 来检查,这样当你编译你的游戏时就不会出现莫名其妙的错误了。

转自:http://blog.csdn.net/yesy10/article/details/7847926

推荐阅读