Wskazówki dotyczące optymalizacji dla Unity

Unity to silnik gier, który jest popularny nie tylko wśród niezależnych twórców, ale także dużych firm.

Posiada przyjazny dla użytkownika interfejs, potężny potok renderowania, łatwy w obsłudze system komponentów i wreszcie obsługuje szeroką gamę platform.

Ale dzięki łatwemu w użyciu interfejsowi jeszcze łatwiej jest nadmiernie skomplikować grę (na przykład przez umieszczenie wielu niepotrzebnych obiektów itp.), dlatego ważne jest, aby mieć optymalizację mieć na uwadze podczas całego procesu rozwoju.

Oto ważne wskazówki dotyczące 3 głównych kategorii (Renderowanie, Skrypty, i Audio), które pomogą Ci poprawić wydajność gry:

Wykonanie

Wskazówka 1: Zachowaj nieskalowane obiekty z komponentem renderującym

Obiekty nieskalowane to te, które mają skalę (1, 1, 1). W takim przypadku Unity nie musi wykonywać dodatkowych obliczeń, aby przeskalować obiekt w każdej klatce.

Przykład: Załóżmy, że masz model domu, który jest za duży lub za mały na twój poziom. Naturalną rzeczą jest skalowanie tego w następujący sposób:

Zmiana rozmiaru budynku

W większości przypadków skalowanie obiektu w widoku Scena jest w porządku, ale jeśli planujesz mieć wiele zduplikowanych instancji tego obiektu, lepiej zmienić skalę w Ustawieniach importu.

Pierwszą rzeczą, którą musisz zrobić, to przeskalować model tak, aby odpowiadał Twoim potrzebom (np. powyższy budynek został przeskalowany od (1, 1, 1) do (0,49482, 0,49482, 0,49482)), a następnie wybrać model w Projekcie widoku i w Ustawieniach importu zanotuj współczynnik skali (zwykle jest to 1 lub 0,1).

Ustaw nową wartość, która powinna być równa domyślnemu współczynnikowi skali pomnożonemu przez nową skalę (w moim przypadku jest to 1 x 0,49482 = 0,49482), a następnie naciśnij Zastosuj. Teraz wróć do modelu w widoku sceny i ustaw skalę z powrotem na (1, 1, 1).

Ustawienia współczynnika skali Unity 3D

Obiekt jest teraz skalowany zgodnie z potrzebami, zachowując domyślną skalę (1, 1, 1).

Ta wskazówka jest szczególnie ważna w przypadku obiektów animowanych korzystających z narzędzia SkinnedMeshRenderer, ponieważ renderowanie tego komponentu jest droższe, a skala (1, 1, 1) upraszcza proces renderowania.

Wskazówka 2: Używaj jak najmniejszej liczby świateł

W Unity występują 3 rodzaje świateł (światło kierunkowe, światło punktowe i światło punktowe). Pod względem wydajności najtańszym rozwiązaniem do renderowania jest światło kierunkowe, następnie punktowe i na końcu reflektor punktowy.

Ogólnie rzecz biorąc, nie chcesz mieć więcej niż 1 światła kierunkowego na scenę, a w przypadku świateł punktowych i punktowych staraj się mieć ich jak najmniej (lub wcale).

Jeśli chodzi o cienie w czasie rzeczywistym, chociaż poprawiają one wizualny aspekt gry, mają one duży narzut związany z wydajnością, więc ogólnie rzecz biorąc, lepiej je wyłączyć lub wgrać do lightmaps i light sondy.

Wskazówka 3: Używaj przezroczystych shaderów ostrożnie

Używaj wyłącznie przezroczystych lub cząstek cieniujących na powierzchniach, które muszą być przezroczyste (np. płoty, cząsteczki dymu itp.).

Obiekty przezroczyste wymagają dodatkowego przebiegu renderowania, co może obniżyć wydajność, szczególnie na platformach o ograniczonych zasobach, takich jak urządzenia mobilne lub Internet.

Skrypty

Wskazówka 1: Zawsze buforuj odniesienia do komponentów

Zawsze powinieneś buforować odniesienia do komponentów, jeśli planujesz uzyskiwać do nich dostęp przy każdej aktualizacji.

Na przykład sprawdź poniższy skrypt:

Zły

using UnityEngine;

public class Script1 : MonoBehaviour
{
    float someValue = 0;

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

Tutaj mamy Skrypt1, który pobiera zmienną "someValue2" ze Skryptu2 i przypisuje ją do zmiennej lokalnej.

Teraz wywołanie tylko jednego GetComponent każdej klatki nie będzie miało żadnego wpływu na wydajność, jednak powinieneś przyjąć nawyk buforowania komponentów, które będą często używane.

Istnieją dwa sposoby buforowania komponentu w skrypcie: albo utwórz zmienną publiczną i przypisz ją w widoku Inspektora, albo utwórz zmienną prywatną i przypisz ją z menu Start lub Obudź. Sprawdź poniższy przykład:

Dobry

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

Znacznie lepiej, dostęp do Skryptu 2 można teraz uzyskać przy każdej aktualizacji bez narzutu na wydajność.

Zrób to samo dla wbudowanych komponentów, takich jak BoxCollider, Rigidbody itp. (z wyjątkiem Transform i GameObject, te są już domyślnie buforowane, więc możesz uzyskać do nich natychmiastowy dostęp).

Wskazówka 2: Używaj SendMessage ostrożnie

SendMessage umożliwia wywołanie określonej funkcji (jeśli istnieje) dla każdego MonoBehaviour, które jest dołączone do obiektu gry.

Na przykład, strzelając z broni w grze, możesz szybko zadać obrażenia, gdy kula trafi wroga, bez konieczności używania GetComponent i innych dodatkowych rzeczy.

Jednak tej metody nie należy wywoływać zbyt często, ponieważ wymaga dużej mocy obliczeniowej.

Wskazówka 3: Używaj GameObject.Find i GameObject.FindWithTag ostrożnie

GameObject.Find, GameObject.FindWithTag i GameObject.FindGameObjectsWithTag umożliwiają szybkie wyszukiwanie obiektów w Scenie. Metody te są znacznie wolniejsze niż GetComponent i powinny być używane tylko podczas inicjalizacji.

Wskazówka 4: Unikaj korzystania z OnGUI

Historycznie rzecz biorąc, OnGUI był jedynym sposobem na utworzenie menu w Unity. Ale od tego czasu dodano alternatywę o nazwie UI Canvas, która jest znacznie lepsza pod względem wydajności i oferuje znacznie więcej funkcjonalności.

Niemniej jednak OnGUI nadal pozostaje realnym sposobem na utworzenie interfejsu użytkownika w Unity i jeśli koniecznie musisz go użyć, pamiętaj, że OnGUI jest wywoływany co najmniej dwa razy na klatkę (dwa razy częściej niż Update i LateUpdate), więc nie rób tego używaj go do wszelkich obliczeń poza interfejsem użytkownika.

Jedną rzeczą, którą możesz zrobić, to mieć oddzielny skrypt, który zawiera tylko OnGUI i włączać/wyłączać go w razie potrzeby.

Na przykład:

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

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

Zarówno UIScript, jak i Script1 są dołączone do tego samego obiektu GameObject. Skrypt 1 kontroluje, kiedy wyświetlać menu.

Kiedy gracz naciśnie Tab, UIScript zostanie włączony i wyświetli przyciski. Ponowne naciśnięcie Tab dezaktywuje tę funkcję, ukrywając przyciski.

Gdy UIScript jest wyłączony, metoda OnGUI nie jest wywoływana, co z kolei poprawia wydajność.

Wskazówka 5: Użyj Profilera

Profiler to jedno z najważniejszych narzędzi do identyfikowania wąskich gardeł i spadków fps, ułatwiające znalezienie dokładnej przyczyny niskiej wydajności.

Audio

Klipy audio można zoptymalizować, upewniając się, że ich ustawienia importu są prawidłowe.

Optymalne Ustawienia importu dźwięku będą zależeć od długości dźwięku, częstotliwości odtwarzania i platformy docelowej.

Sugerowane artykuły
Generator billboardów dla Unity
Jak wykorzystać aktualizację w Unity
Unity Zoptymalizuj swoją grę za pomocą Profilera
Ustawienia importu klipów audio Unity w celu uzyskania najlepszej wydajności
Poprawianie wydajności gry mobilnej w Unity
Wskazówki na Twitterze dotyczące jedności
Podstawowe pojęcia projektowania gier