Mẹo tối ưu hóa cho Unity

Unity là một công cụ trò chơi phổ biến không chỉ với các nhà phát triển độc lập mà cả các công ty lớn.

Nó có giao diện thân thiện với người dùng, quy trình Kết xuất mạnh mẽ, hệ thống thành phần dễ sử dụng và cuối cùng, nó hỗ trợ một loạt nền tảng.

Nhưng với giao diện dễ sử dụng, việc phức tạp hóa trò chơi của bạn thậm chí còn dễ dàng hơn (ví dụ: đặt nhiều đối tượng không cần thiết, v.v.), vì vậy điều quan trọng là phải có optimization tâm trong suốt quá trình phát triển.

Dưới đây là các mẹo quan trọng dành cho 3 danh mục chính (Hiển thị, Scripting,Audio) sẽ giúp bạn cải thiện hiệu suất trò chơi của mình:

Kết xuất

Mẹo 1: Giữ nguyên các Đối tượng có thành phần Trình kết xuất không được định tỷ lệ

Các đối tượng không được chia tỷ lệ là những đối tượng có tỷ lệ (1, 1, 1). Trong trường hợp đó, Unity không phải thực hiện các phép tính bổ sung để định lại tỷ lệ đối tượng trong mỗi khung.

Ví dụ: Giả sử bạn có một mô hình ngôi nhà quá lớn hoặc quá nhỏ so với trình độ của bạn. Điều tự nhiên cần làm là mở rộng quy mô như thế này:

Thay đổi kích thước tòa nhà

Trong hầu hết các trường hợp, bạn có thể chia tỷ lệ đối tượng trong chế độ xem Cảnh, nhưng nếu bạn dự định có nhiều phiên bản trùng lặp của đối tượng đó thì tốt hơn là thay đổi tỷ lệ trong Cài đặt nhập.

Điều đầu tiên bạn cần làm là chia tỷ lệ mô hình cho đến khi phù hợp với nhu cầu của bạn (ví dụ: tòa nhà bên trên được chia tỷ lệ từ (1, 1, 1) đến (0,49482, 0,49482, 0,49482)), sau đó chọn mô hình trong Project và trong Cài đặt nhập, hãy lưu ý Hệ số tỷ lệ (Thông thường là 1 hoặc 0,1).

Đặt giá trị mới, giá trị này phải bằng hệ số tỷ lệ mặc định nhân với tỷ lệ mới (Trong trường hợp của tôi là 1 x 0,49482 = 0,49482), sau đó nhấn Áp dụng. Bây giờ hãy quay lại mô hình trong chế độ xem cảnh và đặt tỷ lệ trở lại (1, 1, 1).

Cài đặt hệ số tỷ lệ Unity 3D

Đối tượng hiện được chia tỷ lệ theo cách bạn cần trong khi vẫn giữ nguyên tỷ lệ mặc định (1, 1, 1).

Mẹo này đặc biệt quan trọng đối với các đối tượng hoạt hình sử dụng SkinnedMeshRenderer vì thành phần này đắt hơn khi kết xuất và có tỷ lệ (1, 1, 1) giúp đơn giản hóa quá trình kết xuất.

Mẹo 2: Sử dụng càng ít đèn càng tốt

Có 3 loại đèn trong Unity (Ánh sáng định hướng, Ánh sáng điểm và Đèn chiếu tiêu điểm). Về mặt hiệu suất, Directional light là loại ánh sáng kết xuất rẻ nhất, sau đó là Point và cuối cùng là Spotlight.

Nói chung, bạn không muốn có nhiều hơn 1 ánh sáng định hướng cho mỗi cảnh, và đối với đèn điểm và đèn điểm, hãy cố gắng có càng ít đèn càng tốt (hoặc không có đèn nào cả).

Về mặt bóng thời gian thực, mặc dù nó nâng cao khía cạnh trực quan của trò chơi nhưng nó lại có chi phí hiệu suất cao nên nhìn chung, tốt hơn là bạn nên tắt chúng hoặc biến chúng thành lightmapslight đầu dò.

Mẹo 3: Sử dụng các Shader trong suốt một cách thận trọng

Chỉ sử dụng Bộ tạo bóng trong suốt hoặc Hạt trên các bề mặt cần trong suốt (ví dụ: Hàng rào, Hạt khói, v.v.)

Các đối tượng có độ trong suốt yêu cầu lượt kết xuất bổ sung có thể làm giảm hiệu suất, đặc biệt là trên các nền tảng có tài nguyên hạn chế, chẳng hạn như Di động hoặc Web.

Viết kịch bản

Mẹo 1: Luôn lưu trữ các tham chiếu thành phần

Bạn phải luôn lưu vào bộ nhớ đệm các tham chiếu thành phần nếu định truy cập chúng vào mỗi lần Cập nhật.

Ví dụ: kiểm tra tập lệnh bên dưới:

Xấu

using UnityEngine;

public class Script1 : MonoBehaviour
{
    float someValue = 0;

    // Update is called once per frame
    void Update()
    {
        someValue = GetComponent<Script2>().someValue2;
    }
}

Ở đây chúng ta có Script1 lấy biến "someValue2" từ Script2 và gán nó cho một biến cục bộ.

Bây giờ, chỉ gọi một GetComponent mỗi khung sẽ không có bất kỳ tác động nào đến hiệu suất, tuy nhiên, bạn nên áp dụng thói quen lưu vào bộ nhớ đệm các thành phần sẽ được sử dụng thường xuyên.

Có hai cách để lưu vào bộ đệm một thành phần trong tập lệnh, tạo biến công khai và gán nó trong chế độ xem Thanh tra hoặc tạo biến riêng tư và gán nó từ Bắt đầu hoặc Thức. Kiểm tra ví dụ dưới đây:

Tốt

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;
    }
}

Tốt hơn nhiều, giờ đây Script2 có thể được truy cập vào mỗi Bản cập nhật mà không gây tốn kém về hiệu năng.

Thực hiện tương tự với các thành phần tích hợp sẵn, chẳng hạn như BoxCollider, Rigidbody, v.v. (ngoại trừ Transform và GameObject, những thành phần này đã được lưu vào bộ nhớ đệm theo mặc định để bạn có thể truy cập chúng ngay lập tức).

Mẹo 2: Sử dụng SendMessage một cách thận trọng

SendMessage cho phép bạn gọi một hàm cụ thể (nếu tồn tại) trên mọi MonoBehaviour được đính kèm với một đối tượng trò chơi.

Ví dụ: khi bắn vũ khí trong trò chơi, bạn có thể nhanh chóng gây sát thương khi viên đạn bắn trúng kẻ thù mà không cần sử dụng GetComponent và các thứ bổ sung khác.

Tuy nhiên, phương pháp này không nên được gọi quá thường xuyên vì nó khá tốn nhiều công sức tính toán.

Mẹo 3: Sử dụng GameObject.Find và GameObject.FindWithTag một cách thận trọng

GameObject.Find, GameObject.FindWithTagGameObject.FindGameObjectsWithTag cho phép bạn nhanh chóng tìm kiếm các đối tượng trong Cảnh. Các phương thức này chậm hơn nhiều so với GetComponent và chỉ nên sử dụng trong quá trình khởi tạo.

Mẹo 4: Tránh sử dụng OnGUI

Trong lịch sử OnGUI là cách duy nhất để tạo menu trong Unity. Nhưng kể từ đó, một giải pháp thay thế đã được thêm vào có tên UI Canvas, giải pháp này tốt hơn nhiều về hiệu suất và cung cấp nhiều chức năng hơn.

Tuy nhiên, OnGUI vẫn là một cách khả thi để tạo giao diện người dùng trong Unity và nếu bạn thực sự cần sử dụng nó, hãy nhớ rằng OnGUI được gọi ít nhất hai lần mỗi khung hình (nhiều gấp đôi so với Cập nhật và LateUpdate), vì vậy đừng làm vậy. sử dụng nó cho bất kỳ tính toán nào ngoài UI.

Một điều bạn có thể làm là có một tập lệnh riêng chỉ có OnGUI trong đó và bật/tắt nó khi cần.

Ví dụ:

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
        }
    }
}

Script1.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;
        }
    }
}

Cả UIScript và Script1 đều được đính kèm vào cùng một GameObject. Script1 kiểm soát thời điểm hiển thị menu.

Khi người chơi nhấn Tab, UIScript sẽ được bật, hiển thị các nút. Nhấn Tab lần nữa sẽ tắt nó, ẩn các nút.

Trong khi UIScript bị vô hiệu hóa, phương thức OnGUI không được gọi, từ đó cải thiện hiệu suất.

Mẹo 5: Sử dụng Trình hồ sơ

Profiler là một trong những công cụ quan trọng nhất khi xác định các tắc nghẽn và giảm khung hình/giây, giúp dễ dàng tìm ra nguyên nhân chính xác gây ra hiệu suất thấp.

Âm thanh

Đoạn âm thanh có thể được tối ưu hóa bằng cách đảm bảo Cài đặt nhập của chúng là chính xác.

Cài đặt nhập âm thanh tối ưu sẽ phụ thuộc vào độ dài âm thanh, tần suất phát và nền tảng mục tiêu.