Unity 的优化技巧
Unity 是一种游戏引擎,不仅在独立开发者中很受欢迎,而且在大公司中也很受欢迎。
它具有用户友好的界面、强大的渲染管道、易于使用的组件系统,最后,它支持大量的平台。
但有了易于使用的界面,就更容易使游戏变得过于复杂(例如 放置 大量不必要的对象等),因此 优化 非常重要在整个开发过程中牢记于心。
以下是针对 3 个主要类别(渲染、脚本、 和 音频)的重要提示,可帮助您提高游戏性能:
渲染
技巧 1:保持带有渲染器组件的对象不缩放
未缩放的对象是那些比例为 (1, 1, 1) 的对象。在这种情况下,Unity 不必进行额外的计算来重新缩放每个帧中的对象。
示例: 假设您的房屋模型对于您的水平来说太大或太小。自然的做法是像这样缩放它:
大多数情况下,可以在“场景”视图中缩放对象,但如果您计划拥有该对象的大量重复实例,最好在“导入设置”中更改比例。
您需要做的第一件事是缩放模型,直到它适合您的需求(例如,上面的建筑物从 (1, 1, 1) 缩放到 (0.49482, 0.49482, 0.49482)),然后在项目中选择模型视图并在导入设置中记下比例因子(通常为 1 或 0.1)。
设置新值,该值应等于默认比例因子乘以新比例(在我的例子中为 1 x 0.49482 = 0.49482),然后点击“应用”。现在返回到场景视图中的模型并将比例设置回 (1, 1, 1)。
现在,对象可以按照您需要的方式缩放,同时保留默认的 (1, 1, 1) 比例。
此技巧对于使用 SkinnedMeshRenderer 的动画对象尤其重要,因为该组件的渲染成本更高,并且比例为 (1, 1, 1) 可以简化渲染过程。
提示 2:使用尽可能少的灯光
Unity 中有 3 种类型的光源(定向光、点光源和聚光灯)。就性能而言,定向光的渲染成本最低,然后是点光,最后是聚光灯。
一般来说,您不希望每个场景有超过 1 个定向光,而对于聚光灯和点光源,请尝试尽可能少(或根本没有)。
就实时阴影而言,虽然它增强了游戏的视觉效果,但它具有高性能开销,因此通常最好禁用它们或将它们烘焙到 lightmaps 和 light 中探针。
技巧 3:谨慎使用透明着色器
仅在需要透明的表面上使用透明或粒子着色器(例如栅栏、烟雾粒子等)
具有透明度的对象需要额外的渲染通道,这可能会降低性能,尤其是在资源有限的平台上,例如移动或 Web。
脚本编写
技巧 1:始终缓存组件引用
如果您计划每次更新都访问组件引用,则应始终缓存它们。
例如,检查下面的脚本:
坏的
using UnityEngine;
public class Script1 : MonoBehaviour
{
float someValue = 0;
// Update is called once per frame
void Update()
{
someValue = GetComponent<Script2>().someValue2;
}
}
这里我们有 Script1,它从 Script2 获取变量 "someValue2" 并将其分配给局部变量。
现在,每一帧仅调用一个 GetComponent 不会对性能产生任何影响,但是,您应该养成缓存经常使用的组件的习惯。
有两种方法可以在脚本中缓存组件,或者创建公共变量并在检查器视图中分配它,或者创建私有变量并从 Start 或 Awake 分配它。检查下面的示例:
好的
using UnityEngine;
public class Script1 : MonoBehaviour
{
float someValue = 0;
Script2 script2Cached;
// Use this for initialization
void Start()
{
script2Cached = GetComponent<Script2>();
}
// Update is called once per frame
void Update()
{
someValue = script2Cached.someValue2;
}
}
更好的是,现在可以在每次更新时访问 Script2,而不会产生性能开销。
对内置组件执行相同的操作,例如 BoxCollider、Rigidbody 等(Transform 和 GameObject 除外,这些组件默认已缓存,因此您可以立即访问它们)。
提示 2:谨慎使用 SendMessage
SendMessage 允许您在每个附加 到游戏对象的 MonoBehaviour 上调用特定函数(如果存在)。
例如,当你在游戏中射击武器时,当子弹击中敌人时,你可以快速造成伤害,而不需要使用 GetComponent 和其他额外的东西。
但是,不应过于频繁地调用此方法,因为它的计算量很大。
提示 3:谨慎使用 GameObject.Find 和 GameObject.FindWithTag
GameObject.Find、GameObject.FindWithTag 和 GameObject.FindGameObjectsWithTag 可让您快速搜索场景中的对象。这些方法比 GetComponent 慢得多,并且只能在初始化期间使用。
提示 4:避免使用 OnGUI
从历史上看, OnGUI 是在 Unity 中制作 menus 的唯一方法。但从那时起,添加了一个名为 UI Canvas 的替代方案,它在性能方面要好得多,并提供更多功能。
尽管如此,OnGUI 仍然是在 Unity 中制作 UI 的可行方法,如果您绝对需要使用它,请记住 OnGUI 每帧至少调用两次(Update 和 LateUpdate 的两倍),所以不要将其用于 UI 之外的任何计算。
您可以做的一件事是拥有一个单独的脚本,其中仅包含 OnGUI,并在需要时启用/禁用它。
例如:
UIScript.cs
using UnityEngine;
public class UIScript : MonoBehaviour {
void OnGUI()
{
if(GUI.Button(new Rect(5, 5, 125, 25), "Button 1"))
{
//Button 1 was pressed, Do Something
}
if (GUI.Button(new Rect(140, 5, 125, 25), "Button 2"))
{
//Button 2 was pressed, Do Something
}
}
}
脚本1.cs
using UnityEngine;
public class Script1 : MonoBehaviour
{
UIScript uiScript;
// Use this for initialization
void Start()
{
uiScript = GetComponent<UIScript>();
uiScript.enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Tab))
{
//toggle UIScript when Tab is pressed
uiScript.enabled = !uiScript.enabled;
}
}
}
UIScript 和 Script1 都附加到同一个 GameObject。Script1 控制何时显示菜单。
当玩家按下 Tab 时,将启用 UIScript,显示按钮。再次按 Tab 键可将其停用,隐藏按钮。
当 UIScript 被停用时,不会调用 OnGUI 方法,这反过来又提高了性能。
技巧 5:使用分析器
Profiler 是识别瓶颈和 fps 下降的最重要工具之一,可以更轻松地找到性能低下的确切原因。
声音的
可以通过确保其导入设置正确来优化音频剪辑。
最佳 音频导入设置 将取决于音频长度、播放频率和目标平台。