Unity3D 5 优化经验分享
一、Prefabs(预设)与 Instantiate(实例化)
如果场景中有多个重复的内容,可将其设置为一个 Prefabs(预设)。Prefabs 是一种资源类型,代表可被重复使用的游戏对象。例如在游戏中呈现千军万马、大量的树木或者一模一样的汽车等场景时,使用 Prefabs 可以高效地管理和复用这些重复元素。
二、对象集合的概念
为了减少频繁增删 Prefabs(预设)的操作,引入了对象集合的概念。在一些需要频繁创建和销毁对象的复用场景中,使用对象集合能够减少代码层面的操作(如 new/delete)。一般建议在比较复杂的场景中使用该方法。
三、美术相关的优化
(一)极端做法
- 灯光与阴影处理:一些美术的极端做法包括不使用像素光(pixelsLights)、不使用阴影(No Shadows),不设置追灯和实时阴影,用面来代替阴影,不使用实时灯光,而是采用 lightmap 代替,甚至不进行灯光烘培,全依靠贴图。然而,这种做法并不适合 3D 游戏,实际效果一般。
- 模型面数选择:根据不同的需求选择不同面数的模型,例如角色展示窗使用 2 万面的模型,场景人物使用 5000 面的模型,远景则使用只有几百面的模型。但这种做法是以牺牲美术效果为代价,并且会导致游戏包体变大。
- 程序着色器编写:让程序使用着色器来编写贴图和特效,不过这种程序极端做法并不适用于大型项目。
(二)实用优化方法
- 使用遮挡剔除插件:笔者使用的是老版本的 Occlusion Culling 和 Simplygon(裁面插件)。这些插件的作用是自动进行视锥体剔除(Frustum Culling)和遮挡剔除(Occlusion Culling),即自动将玩家看不到的东西不再进行绘制。插件会把相同材质的物体分为一组(一个 Batch),然后将它们组合成一个物体(统一变换),这样就可以在一个 Draw Call 中处理多个物体(实际上是组合后的一个物体)。当绘制指令 draw call 越少时,游戏性能自然越高。
- 美术规则约定:在项目前期,需要对美术规则进行约定。例如,卡通风格的模型 1500 面就可以体现人物细节,写实风格的模型 5000 面即可,同时要控制人物的骨骼数量,减少粒子发射器的使用,禁用粒子碰撞。最重要的是确定美术规格,一般团队会把所有的贴图整合到一张较大的图片上,使用工具进行整合。各种参数一定要在前期商量好,因为美术后期进行减面操作会非常痛苦。
- 非运动物体设置:非运动物体尽量打上 Static 标签。Unity 在运行时会对 static 物体进行自动优化处理,所以应该尽可能将非运行实体勾选上 static 标签。
四、程序相关的优化
(一)物理优化
一般情况下,物理方面尽可能使用 Sphere Collider、Box Collider 等简单的碰撞体,尽量避免使用 Mesh Collider 等复杂的碰撞体。在渲染设置上,要避免使用 Alpha Test,因为该操作非常耗时,性价比很低。关于 Static Batching,它可以对静态物体进行 Batch 处理,并且对几何数据的大小没有限制(此结论出自 u3d 4.3 做某 3D 项目时)。
(二)常见问题及解决思路
在实际工作过程中,会遇到很多问题,例如 JIT 编译、Shader 编译、骨骼拼装、物理运算、Animator 运算、实时合并 Mesh、低效的代码接口、文件操作、资源同步加载、NGUI 激活、DC 过多、面数过多、NGUI 和 shader 运算、代码运算量过大等。在项目过程中虽然找到了一些解决办法,但大部分方法网上都有现成的资料,考虑到比赛的庄重性和原创性,这里就不照搬了。
借用同事的一句话:针对卡顿进行优化,使用 profile 工具查看消耗情况,确定哪里消耗资源,然后去解决相应的问题。
五、最有用的做法
策划应少提一些难以落地的需求。例如,策划要求一个 15000 面的模型,具备换装、携带武器和宝宝的功能,场景效果要出色,还要有实时光影,实现万人国战且时时同步,为了配合玩法至少显示自己周围 50 个人包括他们的时装特效。这样的需求在实现过程中会面临诸多困难和性能问题。