Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

項目優化之性能優化(Unity3D)

恬靜的小魔龍itMonon 2021-08-16 21:29:25 阅读数:5268 评论数:0 点赞数:0 收藏数:0

這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰

推薦閱讀

一、前言

如果一個遊戲卡死了,它就沒有樂趣。本文介紹了一些非常簡單的性能改進,為了讓玩家滿意,每個Unity 開發者都應該知道這些改進。沒有人期望你制作一個看起來像AAA+標題的遊戲,但是它應該每秒有大量的幀。

注意:當我們談論在FPS改進環境中,我們總是意味著計算起來很費時間(是什麼使我們的CPU變得瘋狂)。

二、算法和數據結構

當涉及到遊戲的性能時,最主要的部分是開發人員對高效算法和數據結構的了解。這是一個太大的主題,不能在這裏討論。如果您是編程新手,請嘗試查看以下主題,以了解什麼時候最好使用這些主題:

  • 列錶
  • 鏈接列錶
  • HashMaps
  • 排隊
  • 堆疊
  • 排序(快速排序,Bubblesort,.)

三、數學

為了保持理智,我們將在本文中不討論數學。然而,數學對性能很重要。想象一下我們的場景中有個怪物。玩家現在射殺了怪物-我們怎樣才能發現他是否擊中了它?

有無數的方法可以做到這一點,它們都包括數學。你的工作是了解他們,並决定哪一種是最好的方法。幸運的是,聯合已經為我們提供了大量的功能。不過,如果找不到合適的方法,數學就會出現。

四、網格

讓我們來談談一些可以不用付出很大努力就可以學習和應用的東西:優化網格。在制作遊戲時,我們通常在場景中有很多3D模型。每個模型都由一個所謂的網格組成。網格就是一大串三角形。三角形越多,我們得到的FPS就越少,所以保持它們盡可能低是很重要的。

例如,一個怪物模型可以看起來真的很好,只有4000三角形。沒有必要使用其中的一百萬個。大多數三維建模程序已經具有網格優化功能,這取决於您使用它們。

如果沒有方法繞過有很多三角形的網格,那麼還有另一個選擇:LOD(細節級別)。LOD的概念很簡單:當網格離攝像機很遠時,它會被修改,所以它有較少的三角形。玩家看不出有什麼不同,因為離攝像機很遠。統一支持這個特性,所以總有一天會嘗試一下。

五、緩存GetComponent

通常使用GetComponent函數來訪問GameObject的組件。就計算而言,這個函數是昂貴的。

讓我們看一個關於如何不使用它的示例:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Health h = GetComponent<Health>();
h.increaseBy(100);
}
}
複制代碼

這個例子很糟糕,因為每次更新都會調用GetComponent一次(大約每秒60次)。這一點可以很容易地改進如下:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
// Cache
Health h;
// Use this for initialization
void Start () {
h = GetComponent<Health>();
}
// Update is called once per frame
void Update () {
h.increaseBy(100);
}
}
複制代碼

這個例子要好得多。它提供了相同的功能,但是計算較少,因為GetComponent函數在開始時只調用一次,而不再每秒調用60次。

六、單比特捷徑性質

為了讓我們的生活變得更簡單,Unitity提供了一種不使用GetComponent函數訪問一些標准組件的方法,例如:

  • 變換
  • 遊戲對象

它們是這樣使用的:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 pos = transform.position;
}
}
複制代碼

要知道這段代碼需要大量的計算,需要了解一些關於Unity的知識。原因是它真正做的就是這樣:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 pos = GetComponent<Transform>.position;
}
}
複制代碼

盡管它看起來不像它,但它仍然每次都使用GetComponent,正如上面提到的,計算起來很費時間。

正確的方法是這樣做:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
// Cache
Transform tr;
// Use this for initialization
void Start () {
tr = transform;
}
// Update is called once per frame
void Update () {
Vector3 pos = tr.position;
}
}
複制代碼

七、GUIS

在使用guis時,最簡單的方法通常是使用GUILayout類而不是GUI類,等級。遺憾的是,GUILayout類要比GUI類慢得多,所以請慎重考慮它是否值得。

八、Shaders

Shaders可以使圖形卡變得完全瘋狂。除非你是一個Shaders專家,這是一個好主意,只使用那些Unity提供的Shaders。除此之外,還有帶有“Mobile”後綴的Unity Shaders。這些著色器特別適用於手機,但它們也能在普通電腦上帶來性能改進。

注意:Unity著色器制作精良,但計算起來仍然很昂貴。少用!

九、烘焙

我們做點餅幹.。 統一有幾個烘焙特點。例如,當我們想在遊戲中有陰影時,首先想到的是這樣的方法: 在每次Draw Call中:

  • 1.燈的比特置
  • 2.畫場景
  • 3.畫陰影

這意味著在每次Draw Call中,陰影都會被一次又一次地計算出來。現在,烘焙的功能類似於我們上面使用的緩存。它只計算了一次陰影,並且已經在我們的紋理上繪制了它們,所以它們不需要一次又一次的計算。這個巨量性能優勢。

嘗試一下,這個特性可以在Window-Lightmap下面找到.有更多的烘焙方法,除了照明以外的東西,只要與他們一起玩,看看他們是否有益於你的遊戲的錶現。

十、動態燈

烘焙燈的缺點是,如果其中一個物體移動,它的陰影不會隨著它移動,因為它很久以前就被烤到了紋理上。

烘焙燈的對立面叫做動態燈..物體移動時,陰影也會移動。

雖然這聽起來很酷,但也有一個巨大的缺點:根據經驗,每增加一盞燈,場景就必須再畫一次。因此,如果我們在現場使用2個燈,我們可能會得到一半的FPS(以此類推)。

雖然這是一個經驗法則和統一仍然是相當快,當涉及到繪制燈,這通常是一個好主意,使用盡可能少的燈。

十一、內存分配

讓我們看看下面的代碼:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
// Update is called once per frame
void Update () {
SomeClass x = new SomeClass("Some", 123, "Parameters");
}
}
複制代碼

在每個更新調用中,SomeClassx使用關鍵字創建(“已分配”)。新的..當使用新的關鍵字,United從我們的計算機中分配一些內存。當對象不再使用時,它將再次釋放這個內存。如果經常這樣做,這可能是一個非常昂貴的計算。

整個概念背後有更多的東西,但對我們來說,重要的是要記住,我們應該避免新的只要我們能。

另一種選擇可能是這樣的:

using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
// Cache
SomeClass v = new SomeClass();
// Update is called once per frame
void Update () {
v.setName("Some");
v.setLevel(123);
v.setSomethingElse("Parameters");
}
}
複制代碼

十二、摘要

性能是計算機科學研究的主要問題之一。我們討論了增加遊戲FPS的基本方法,而不使用任何可怕的數學。然而,一個很大的(如果不是最大的)部分在於程序員對數學、算法和數據結構的知識。這些話題可能是壓倒性的,但是在你的旅途中,盡可能多地了解它們是很重要的。

順便提一句:我們的其他文章通常不是為了保持它們盡可能容易理解而對性能進行優化。這取决於您應用本文中所學到的內容。

版权声明
本文为[恬靜的小魔龍itMonon]所创,转载请带上原文链接,感谢

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领