Part 1 連結 、演講影片、簡報檔
承接第一點 (減少 Vector 的運算) 的建議 ,
這裡Playdead工作室建議的不只是減少對 Vector 做運算了,
直接建議大家完全不要對 Vector 做運算!
所以在這裡的優化範例中,他們將下面的計算 :
這其概念即承接前面的優化建議第4點【減少向 Unity 查找資料的頻率】,
向 Unity 引擎查找資料其實是會消耗一些效能的。
因此 Playdead 建議也將 Time.deltaTime 統一儲存在一個全域變數供需要的程序存取。
foreach 雖然寫起來非常簡短,
但是 for...Loop 在Unity中執行起來還是比較節省效能。
雖然 比起 foreach 寫起來會比較長一些些,
但為了在有限的硬體資源中讓遊戲跑得更順,這點麻煩算不了什麼吧?
... 這點真的是讓我蠻訝異的 ! 因為我一直以為 Array 比較慢 @@
我超級喜歡使用List類型的陣列,
不用特別宣告長度這一點真的很方便。
P.S : 不過簡報中也提到實際節省的效率差異不大,請大家自行斟酌囉
在 Unity 中使用 Update() 或是 FixedUpdate() 時,
6、Actually… don’t do Vector math at all! (不要對 Vector 做運算 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | Transform _transform; // Use this for initialization void Start() { _transform = transform; } public void before() { cachedLocalPosition += wantedVelocity * (speed * speedfactor * Mathf.Sin(someOtherFactor) * drag * friction * Time.deltaTime); _transform.localPosition = cachedLocalPosition; } public void after() { float factor = speed * speedfactor * Mathf.Sin(someOtherFactor) * drag * friction * Time.deltaTime; cachedLocalPosition.x += wantedVelocity.x * factor; cachedLocalPosition.y += wantedVelocity.y * factor; cachedLocalPosition.z += wantedVelocity.z * factor; _transform.localPosition = cachedLocalPosition; } |
這裡Playdead工作室建議的不只是減少對 Vector 做運算了,
直接建議大家完全不要對 Vector 做運算!
所以在這裡的優化範例中,他們將下面的計算 :
cachedLocalPosition += wantedVelocity * (speed * speedfactor * Mathf.Sin(someOtherFactor) * drag * friction * Time.deltaTime);猜分為先計算變化量係數 factor :
float factor = speed * speedfactor
* Mathf.Sin(someOtherFactor)
* drag * friction * Time.deltaTime;
然後在針對 Vector 內的 XYZ 做個別計算:cachedLocalPosition.x += wantedVelocity.x * factor; cachedLocalPosition.y += wantedVelocity.y * factor; cachedLocalPosition.z += wantedVelocity.z * factor;
7、Time.deltaTime could be cached ( Time.deltaTime 也用快取吧! )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public void before() { float factor = speed * speedfactor * Mathf.Sin(someOtherFactor) * drag * friction * Time.deltaTime; cachedLocalPosition.x += wantedVelocity.x * factor; cachedLocalPosition.y += wantedVelocity.y * factor; cachedLocalPosition.z += wantedVelocity.z * factor; _transform.localPosition = cachedLocalPosition; } public void after() { float factor = speed * speedfactor * Mathf.Sin(someOtherFactor) * drag * friction * main.globalDeltaTime; cachedLocalPosition.x += wantedVelocity.x * factor; cachedLocalPosition.y += wantedVelocity.y * factor; cachedLocalPosition.z += wantedVelocity.z * factor; _transform.localPosition = cachedLocalPosition; } |
向 Unity 引擎查找資料其實是會消耗一些效能的。
因此 Playdead 建議也將 Time.deltaTime 統一儲存在一個全域變數供需要的程序存取。
8、Don’t use “foreach” - ever ( 永遠不要使用 foreach )
1 2 3 4 5 6 7 8 9 10 | void Update() { // do a lot of iterations: for (int a = 0; a < 1000; ++a) { ScriptPerformanceTest.globalDeltaTime = Time.deltaTime; for (int i = 0, cnt = scriptList.Count; i < cnt; ++i) scriptList[i].UpdateCharacter(); } } |
1 2 3 4 5 6 7 8 9 10 | void Update () { // do a lot of iterations: for (int a = 0; a<1000; ++a) { ScriptPerformanceTest.globalDeltaTime=Time.deltaTime; foreach (var script in scriptList) script.UpdateCharacter(); } } |
但是 for...Loop 在Unity中執行起來還是比較節省效能。
雖然 比起 foreach 寫起來會比較長一些些,
但為了在有限的硬體資源中讓遊戲跑得更順,這點麻煩算不了什麼吧?
9、Arrays! Not Lists. (用Arrays 而非Lists! )
1 2 3 4 5 6 7 8 9 10 11 | public List<ScriptPerformanceTest> scriptList; void Update() { for (int a = 0; a < 1000; ++a) { ScriptPerformanceTest.globalDeltaTime = Time.deltaTime; for (int i = 0, cnt = scriptList.Count; i < cnt; ++i) scriptList[i].UpdateCharacter(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 | // this array will be filled with 100 elements in “Start()” public ScriptPerformanceTest[] scriptArray; void Update() { for (int a = 0; a < 1000; ++a) { ScriptPerformanceTest.globalDeltaTime = Time.deltaTime; for (int i = 0, cnt = scriptArray.Length; i < cnt; ++i) scriptArray[i].UpdateCharacter(); } } |
我超級喜歡使用List類型的陣列,
不用特別宣告長度這一點真的很方便。
P.S : 不過簡報中也提到實際節省的效率差異不大,請大家自行斟酌囉
10、Avoid using Update() and FixedUpdate() . (自製更新管理系統 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using UnityEngine; using System.Collections.Generic; public class UpdateManager : MonoBehaviour { private ManagedUpdateBehavior[] list; private void Start () { list = GetComponents<ManagedUpdateBehavior>(); } private void Update () { var count = list.Length; for (var i = 0; i < count; i++) { list[i].UpdateMe(); } } } |
會產生一些不會記錄在側寫器 (Profiler)的運算資源消耗。
因此 Playdead 建議 Unity 使用者自行撰寫一個 Update-manager。
將有所有的Script記錄在一個Array之中,並由Update-manger統一執行。
Playdade在簡報中表這麼做使得 Inside 在 XBox 及 Ps4 版上獲得 1、2ms的效能提升。
Playdade在簡報中表這麼做使得 Inside 在 XBox 及 Ps4 版上獲得 1、2ms的效能提升。
沒有留言:
張貼留言