Zalecenia dotyczące wydajności aparatu Unity

Ten artykuł opiera się na zaleceniach dotyczących wydajności rzeczywistości mieszanej, ale koncentruje się na ulepszeniach specyficznych dla aparatu Unity.

Niedawno opublikowaliśmy aplikację o nazwie Podstawy jakości, która obejmuje typowe problemy z wydajnością, projektowaniem i środowiskiem oraz rozwiązaniami HoloLens 2 aplikacji. Ta aplikacja jest doskonałym pokazem wizualnym zawartości, która jest poniżej.

Najważniejszym pierwszym krokiem podczas optymalizacji wydajności aplikacji rzeczywistości mieszanej w środowisku Unity jest upewnienie się, że używasz zalecanych ustawień środowiska dla aparatu Unity. Ten artykuł zawiera zawartość z niektórymi z najważniejszych konfiguracji scen do tworzenia wydajnych aplikacji Mixed Reality. Niektóre z tych zalecanych ustawień są również wyróżnione poniżej.

Jak profilować za pomocą aparatu Unity

Aparat Unity udostępnia wbudowany program Unity Profiler , który jest doskonałym zasobem do zbierania cennych szczegółowych informacji o wydajności dla określonej aplikacji. Chociaż można uruchomić profilera w edytorze, te metryki nie reprezentują prawdziwego środowiska uruchomieniowego, dlatego wyniki powinny być używane ostrożnie. Zalecamy zdalne profilowanie aplikacji podczas uruchamiania na urządzeniu w celu uzyskania najdokładniejszych i akcji szczegółowych informacji.

Aparat Unity udostępnia świetną dokumentację dla następujących celów:

  1. Jak zdalnie połączyć profilera aparatu Unity z aplikacjami platformy UWP
  2. Jak skutecznie diagnozować problemy z wydajnością w programie Unity Profiler

Profilowanie procesora GPU

Profiler aparatu Unity

Po połączeniu profilera aparatu Unity i po dodaniu profilera procesora GPU (zobacz Dodawanie profilera w prawym górnym rogu), można zobaczyć, ile czasu poświęca się na procesor CPU & procesor GPU odpowiednio w środku profilera. Dzięki temu deweloper może uzyskać szybkie przybliżenie, jeśli ich aplikacja jest powiązana z procesorem CPU lub procesorem GPU.

Procesor UNITY i procesor GPU

Uwaga

Aby używać profilowania procesora GPU, należy wyłączyć zadania grafiki w ustawieniach odtwarzacza Aparatu Unity. Aby uzyskać więcej informacji, zobacz moduł Profiler użycia procesora GPU aparatu Unity.

Debuger ramki aparatu Unity

Debuger frame debuger aparatu Unity to również zaawansowane i szczegółowe narzędzie do użycia. Dzięki temu będziesz dobrze zapoznać się z tym, co procesor GPU robi każdą ramkę. Warto zwrócić uwagę na dodatkowe elementy docelowe renderowania i polecenia z błędami do kopiowania między nimi, ponieważ są one bardzo kosztowne na urządzeniu HoloLens. W idealnym przypadku nie należy używać obiektów docelowych renderowania poza ekranem na urządzeniu HoloLens. Są one zwykle dodawane podczas włączania kosztownych funkcji renderowania (na przykład MSAA, HDR lub pełnoekranowych efektów, takich jak bloom), których należy unikać.

Nakładka szybkości ramek urządzenia HoloLens

Strona Wydajność systemu portalu urządzeń zawiera dobre podsumowanie wydajności procesora CPU i procesora GPU urządzenia. Możesz włączyć licznik szybkości klatek wyświetlania w zestawie słuchawkowym i wyświetlać wykres szybkości klatek w zestawie słuchawkowym. Te opcje umożliwią odpowiednio licznik i wykres FPS, który zapewni natychmiastową opinię w dowolnej uruchomionej aplikacji na urządzeniu.

PIX

PIX można również używać do profilowania aplikacji aparatu Unity. Istnieją również szczegółowe instrukcje dotyczące używania i instalowania PIX dla HoloLens 2. W kompilacji programistycznej te same zakresy, które są widoczne w debugerze Frame Debugger aparatu Unity, będą również wyświetlane w formacie PIX i można je sprawdzić i profilować bardziej szczegółowo.

Uwaga

Aparat Unity umożliwia łatwe modyfikowanie rozdzielczości docelowej renderowania aplikacji w czasie wykonywania za pomocą właściwości XRSettings.renderViewportScale . Końcowy obraz przedstawiony na urządzeniu ma stałą rozdzielczość. Platforma będzie próbkować dane wyjściowe o niższej rozdzielczości, aby utworzyć obraz o wyższej rozdzielczości do renderowania na ekranach.

UnityEngine.XR.XRSettings.renderViewportScale = 0.7f;

Zalecenia dotyczące wydajności procesora CPU

W poniższej zawartości opisano bardziej szczegółowe rozwiązania dotyczące wydajności, szczególnie przeznaczone dla środowiska Unity & programowania w języku C#.

Odwołania do pamięci podręcznej

Zalecamy buforowanie odwołań do wszystkich odpowiednich składników i obiektów GameObject podczas inicjowania, ponieważ powtarzające się wywołania funkcji, takie jak GetComponent<T>() i Camera.main są droższe w stosunku do kosztu pamięci do przechowywania wskaźnika. . Camera.main po prostu używa funkcji FindGameObjectsWithTag() poniżej, która kosztownie wyszukuje wykres sceny dla obiektu aparatu z tagiem "MainCamera".

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour
{
    private Camera cam;
    private CustomComponent comp;

    void Start() 
    {
        cam = Camera.main;
        comp = GetComponent<CustomComponent>();
    }

    void Update()
    {
        // Good
        this.transform.position = cam.transform.position + cam.transform.forward * 10.0f;

        // Bad
        this.transform.position = Camera.main.transform.position + Camera.main.transform.forward * 10.0f;

        // Good
        comp.DoSomethingAwesome();

        // Bad
        GetComponent<CustomComponent>().DoSomethingAwesome();
    }
}

Uwaga

Unikaj polecenia GetComponent(string)
W przypadku korzystania z polecenia GetComponent()istnieje kilka różnych przeciążeń. Ważne jest, aby zawsze używać implementacji opartych na typach i nigdy nie przeciążenia wyszukiwania opartego na ciągach. Wyszukiwanie według ciągu w scenie jest znacznie droższe niż wyszukiwanie według typu.
(Dobry) Składnik GetComponent(typ)
(Dobry) T GetComponent<T>()
(Zły) Składnik GetComponent(ciąg)>

Unikaj kosztownych operacji

  1. Unikaj używania LINQ

    Chociaż LINQ może być czysty i łatwy do odczytania i zapisu, zwykle wymaga więcej obliczeń i pamięci niż w przypadku ręcznego pisania algorytmu.

    // Example Code
    using System.Linq;
    
    List<int> data = new List<int>();
    data.Any(x => x > 10);
    
    var result = from x in data
                 where x > 10
                 select x;
    
  2. Typowe interfejsy API aparatu Unity

    Niektóre interfejsy API aparatu Unity, choć przydatne, mogą być kosztowne do wykonania. Większość z nich obejmuje przeszukiwanie całego grafu sceny w celu znalezienia odpowiedniej listy obiektów GameObjects. Te operacje zazwyczaj można uniknąć, buforując odwołania lub implementując składnik menedżera dla obiektu GameObjects w celu śledzenia odwołań w czasie wykonywania.

        GameObject.SendMessage()
        GameObject.BroadcastMessage()
        UnityEngine.Object.Find()
        UnityEngine.Object.FindWithTag()
        UnityEngine.Object.FindObjectOfType()
        UnityEngine.Object.FindObjectsOfType()
        UnityEngine.Object.FindGameObjectsWithTag()
        UnityEngine.Object.FindGameObjectsWithTag()
    

Uwaga

Funkcja SendMessage() i BroadcastMessage() powinna zostać wyeliminowana ze wszystkich kosztów. Te funkcje mogą być w kolejności 1000x wolniejsze niż wywołania funkcji bezpośrednich.

  1. Uważaj na boks

    Boxing to podstawowa koncepcja języka C# i środowiska uruchomieniowego. Jest to proces zawijania zmiennych typowych wartości, takich jak char, int, boolitp. do zmiennych typowych odwołań. Gdy zmienna typu wartości jest "boxed", jest opakowana w element , który jest przechowywany na zarządzanym System.Objectstercie. Pamięć jest przydzielana i ostatecznie po usunięciu musi zostać przetworzona przez moduł odśmiecający pamięć. Te alokacje i przydziały powodują koszt wydajności, a w wielu scenariuszach są niepotrzebne lub można je łatwo zamienić na mniej kosztowną alternatywę.

    Aby uniknąć boxingu, upewnij się, że zmienne, pola i właściwości, w których są przechowywane typy liczbowe i struktury (w tym Nullable<T>) są silnie typizowane jako określone typy, takie jak int, float? lub MyStruct, zamiast używać obiektu. W przypadku umieszczania tych obiektów na liście należy użyć silnie typizowanej listy, takiej jak List<int> zamiast List<object> lub ArrayList.

    Przykład boksu w języku C#

    // boolean value type is boxed into object boxedMyVar on the heap
    bool myVar = true;
    object boxedMyVar = myVar;
    

Powtarzanie ścieżek kodu

Wszystkie powtarzające się funkcje wywołania zwrotnego aparatu Unity (tj. Aktualizacja), które są wykonywane wiele razy na sekundę i/lub ramkę, powinny być starannie napisane. Wszelkie kosztowne operacje w tym miejscu będą miały ogromny i spójny wpływ na wydajność.

  1. Puste funkcje wywołania zwrotnego

    Chociaż poniższy kod może wydawać się niewinny, aby pozostawić w aplikacji, zwłaszcza że każdy skrypt aparatu Unity automatycznie inicjuje metodę Update, te puste wywołania zwrotne mogą stać się kosztowne. Aparat Unity działa tam i z powrotem między granicą kodu niezarządzanego i zarządzanego między kodem Aparatu UnityEngine i kodem aplikacji. Przełączanie kontekstu przez ten most jest dość kosztowne, nawet jeśli nie ma nic do wykonania. Staje się to szczególnie problematyczne, jeśli aplikacja ma 100 obiektów GameObject z składnikami, które mają puste powtarzające się wywołania zwrotne aparatu Unity.

    void Update()
    {
    }
    

Uwaga

Update() jest najczęstszym przejawem tego problemu z wydajnością, ale inne powtarzające się wywołania zwrotne aparatu Unity, takie jak następujące, mogą być równie złe, jeśli nie są gorsze: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), itp.

  1. Operacje do faworyzowania uruchamiania raz na ramkę

    Następujące interfejsy API aparatu Unity są typowymi operacjami dla wielu aplikacji Holographic Apps. Chociaż nie zawsze jest to możliwe, wyniki z tych funkcji można często obliczać raz i wyniki ponownie wykorzystywane w całej aplikacji dla danej ramki.

    a) Dobrym rozwiązaniem jest posiadanie dedykowanej klasy lub usługi Singleton do obsługi spojrzenia Raycast w scenie, a następnie ponowne użycie tego wyniku we wszystkich innych składnikach sceny, zamiast powtarzania i identycznych operacji Raycast przez każdy składnik. Niektóre aplikacje mogą wymagać raycasts z różnych źródeł lub różnych mask warstw.

        UnityEngine.Physics.Raycast()
        UnityEngine.Physics.RaycastAll()
    

    b) Unikaj operacji GetComponent() w powtarzających się wywołaniach zwrotnych aparatu Unity, takich jak Update(), buforując odwołania do start () lub Awake()

        UnityEngine.Object.GetComponent()
    

    c) Dobrym rozwiązaniem jest utworzenie wystąpienia wszystkich obiektów, jeśli to możliwe, podczas inicjowania i używania puli obiektów do recyklingu i ponownego używania obiektów GameObjects w całym środowisku uruchomieniowym aplikacji

        UnityEngine.Object.Instantiate()
    
  2. Unikaj interfejsów i konstrukcji wirtualnych

    Wywoływanie wywołań funkcji za pośrednictwem interfejsów i obiektów bezpośrednich lub wywoływanie funkcji wirtualnych często jest znacznie droższe niż przy użyciu konstrukcji bezpośrednich lub wywołań funkcji bezpośrednich. Jeśli funkcja wirtualna lub interfejs są niepotrzebne, należy ją usunąć. Jednak osiągnięcie wydajności tych podejść jest warte kompromisu, jeśli ich użycie upraszcza współpracę deweloperów, czytelność kodu i łatwość utrzymania kodu.

    Ogólnie rzecz biorąc, zaleca się, aby nie oznaczać pól i funkcji jako wirtualnych, chyba że istnieje jasne oczekiwanie, że ten element członkowski musi zostać zastąpiony. Należy zachować szczególną ostrożność w przypadku ścieżek kodu o wysokiej częstotliwości, które są wywoływane wiele razy na ramkę, a nawet raz na ramkę UpdateUI() , taką jak metoda.

  3. Unikaj przekazywania struktur według wartości

    W przeciwieństwie do klas, struktury są typami wartości, a po przekazaniu bezpośrednio do funkcji ich zawartość jest kopiowana do nowo utworzonego wystąpienia. Ta kopia dodaje koszt procesora CPU, a także dodatkową pamięć na stosie. W przypadku małych struktur efekt jest minimalny i w ten sposób akceptowalny. Jednak w przypadku funkcji wielokrotnie wywoływanych każdej ramki, a także funkcji, które przyjmują duże struktury, jeśli to możliwe, zmodyfikuj definicję funkcji, aby przejść przez odwołanie. Dowiedz się więcej tutaj

Różne

  1. Fizyki

    a) Ogólnie najprostszym sposobem poprawy fizyki jest ograniczenie ilości czasu spędzonego na fizyce lub liczbę iteracji na sekundę. Spowoduje to zmniejszenie dokładności symulacji. Zobacz TimeManager w środowisku Unity

    b) Typy zderzaków w unity mają znacznie różne cechy wydajności. Kolejność poniżej zawiera listę najbardziej wydajnych zderzaków do najmniej wydajnych zderzaków od lewej do prawej. Ważne jest, aby uniknąć zderzaków mesh, które są znacznie droższe niż pierwotne zderzacze.

    Siatka skrzynki <<< kapsułowej < sfery < (wypukłe) (bez wypukłych) <

    Aby uzyskać więcej informacji, zobacz Artykuł Unity Physics Best Practices (Najlepsze rozwiązania dotyczące fizyki aparatu Unity )

  2. Animacje

    Wyłącz animacje bezczynności, wyłączając składnik Animator (wyłączenie obiektu gry nie będzie miało tego samego efektu). Unikaj wzorców projektowania, w których animacja siedzi w pętli ustawiając wartość na tę samą rzecz. Istnieje znaczne obciążenie dla tej techniki, bez wpływu na aplikację. Więcej informacji można znaleźć tutaj.

  3. Złożone algorytmy

    Jeśli aplikacja używa złożonych algorytmów, takich jak odwrotne kinematyka, znajdowanie ścieżek itp., poszukaj prostszego podejścia lub dostosuj odpowiednie ustawienia pod kątem ich wydajności

Zalecenia dotyczące wydajności procesora CPU do procesora GPU

Ogólnie rzecz biorąc, wydajność procesora CPU do procesora GPU sprowadza się do wywołań rysowania przesłanych do karty graficznej. Aby poprawić wydajność, wywołania rysowania muszą być strategicznie a) zmniejszone lub b) zrestrukturyzowane w celu uzyskania optymalnych wyników. Ponieważ wywołania rysowania są intensywnie obciążające zasoby, zmniejszenie liczby wywołań zmniejszy ogólną wymaganą pracę. Ponadto zmiany stanu między wywołaniami rysowania wymagają kosztownej weryfikacji i kroków tłumaczenia w sterowniku graficznym, a tym samym restrukturyzacja wywołań rysowania aplikacji w celu ograniczenia zmian stanu (np. różnych materiałów itp.) może zwiększyć wydajność.

Aparat Unity zawiera świetny artykuł, który zawiera omówienie i szczegółowe informacje na temat przetwarzania wsadowego wywołań rysowania dla ich platformy.

Renderowanie pojedynczego wystąpienia

Renderowanie pojedynczego wystąpienia w środowisku Unity umożliwia narysowanie wywołań dla każdego oka, które można zmniejszyć do jednego wystąpienia wywołania losowania. Ze względu na współistnienie pamięci podręcznej między dwoma wywołaniami rysowania, istnieje również pewne zwiększenie wydajności procesora GPU.

Aby włączyć tę funkcję w projekcie aparatu Unity

  1. Otwórz kolejno pozycje OpenXR Settings (Edytowanie>ustawień> projektuXR Plugin Management>OpenXR).
  2. Wybierz pozycję Pojedyncze wystąpienie z listy rozwijanej Tryb renderowania .

Zapoznaj się z następującymi artykułami z aparatu Unity, aby uzyskać szczegółowe informacje na temat tego podejścia renderowania.

Uwaga

Jednym z typowych problemów z renderowaniem pojedynczego wystąpienia z przekazywaniem występuje, jeśli deweloperzy mają już istniejące niestandardowe cieniowania, które nie są napisane na potrzeby stancingu. Po włączeniu tej funkcji deweloperzy mogą zauważyć, że niektóre obiekty GameObject są renderowane tylko w jednym oku. Jest to spowodowane tym, że skojarzone niestandardowe cieniowania nie mają odpowiednich właściwości do ściągnięcia.

Zobacz Renderowanie jednoprzepustowe stereo dla urządzenia HoloLens z aparatu Unity, aby dowiedzieć się, jak rozwiązać ten problem

Statyczne przetwarzanie wsadowe

Aparat Unity może wsadować wiele obiektów statycznych, aby zmniejszyć liczbę wywołań rysowania do procesora GPU. Statyczne przetwarzanie wsadowe działa w przypadku większości obiektów renderujących w środowisku Unity, które 1) mają ten sam materiał i 2) są oznaczone jako Statyczne (wybierz obiekt w środowisku Unity i zaznacz pole wyboru w prawym górnym rogu inspektora). Obiekty GameObject oznaczone jako Statyczne nie mogą być przenoszone w całym środowisku uruchomieniowym aplikacji. W związku z tym statyczne przetwarzanie wsadowe może być trudne do wykorzystania na urządzeniu HoloLens, gdzie praktycznie każdy obiekt musi zostać umieszczony, przeniesiony, przeskalowany itp. W przypadku immersyjnych zestawów słuchawkowych statyczne partie mogą znacznie zmniejszyć liczbę wywołań rysowania, a tym samym zwiększyć wydajność.

Aby uzyskać więcej informacji, przeczytaj artykuł Static Batching under Draw Call Batching in Unity (Przetwarzanie wsadowe statyczne w usłudze Draw Call Batching in Unity).

Dynamiczne przetwarzanie wsadowe

Ponieważ problematyczne jest oznaczanie obiektów jako statycznych na potrzeby opracowywania urządzeń HoloLens, dynamiczne przetwarzanie wsadowe może być doskonałym narzędziem do zrekompensowania tego braku funkcji. Może to być również przydatne w immersyjnych zestawach słuchawkowych, jak również. Jednak dynamiczne przetwarzanie wsadowe w środowisku Unity może być trudne, ponieważ obiekty GameObjects muszą a) współdzielić ten sam materiał i b) spełniają długą listę innych kryteriów.

Przeczytaj artykuł Dynamic Batching under Draw Call Batching in Unity (Dynamiczne przetwarzanie wsadowe w usłudze Draw Call Batching w środowisku Unity), aby uzyskać pełną listę. Najczęściej obiekty GameObject są nieprawidłowe do dynamicznego dzielenia na partie, ponieważ skojarzone dane siatki nie mogą przekraczać 300 wierzchołków.

Inne techniki

Przetwarzanie wsadowe może wystąpić tylko wtedy, gdy wiele obiektów GameObject może współużytkować ten sam materiał. Zazwyczaj będzie to blokowane przez potrzebę, aby obiekty GameObject miały unikatową teksturę dla odpowiedniego materiału. Często łączy tekstury w jedną wielką teksturę, czyli metodę znaną jako Texture Atlasing.

Ponadto lepiej jest połączyć siatki w jeden obiekt GameObject, jeśli jest to możliwe i uzasadnione. Każdy moduł renderowania w środowisku Unity będzie miał skojarzone wywołania rysowania w porównaniu do przesyłania połączonej siatki w ramach jednego modułu renderowanego.

Uwaga

Modyfikowanie właściwości pliku Renderer.material w czasie wykonywania spowoduje utworzenie kopii materiału i potencjalnie przerwanie przetwarzania wsadowego. Użyj elementu Renderer.sharedMaterial, aby zmodyfikować właściwości udostępnionego materiału w obiektach GameObjects.

Zalecenia dotyczące wydajności procesora GPU

Dowiedz się więcej na temat optymalizowania renderowania grafiki w środowisku Unity

Przepustowość i współczynniki wypełnienia

Podczas renderowania ramki na procesorze GPU aplikacja jest powiązana z przepustowością pamięci lub szybkością wypełniania.

  • Przepustowość pamięci to szybkość odczytów i zapisów, które procesor GPU może wykonywać z pamięci
    • W środowisku Unity zmień jakość tekstury w obszarze Edytuj>ustawienia jakościustawień> projektu.
  • Szybkość wypełniania odnosi się do pikseli, które mogą być rysowane na sekundę przez procesor GPU.

Optymalizowanie udostępniania buforu głębokości

Zalecamy włączenie udostępniania buforu głębokości w celu zoptymalizowania pod kątem stabilności hologramu. W przypadku włączenia ponownego projektu na podstawie głębokości na późnym etapie przy użyciu tego ustawienia zalecamy wybranie formatu głębokości 16-bitowej zamiast formatu głębokości 24-bitowej . Bufory głębokości 16-bitowej znacznie zmniejszają przepustowość (a tym samym moc) skojarzoną z ruchem buforowym głębokości. Może to być duża poprawa zarówno w zakresie redukcji mocy, jak i wydajności. Istnieją jednak dwa możliwe negatywne wyniki przy użyciu formatu głębokości 16-bitowej.

Walka Z

Zmniejszona dokładność zakresu głębokości sprawia, że walka z prawdopodobnie wystąpi z 16 bitami niż 24-bitowa. Aby uniknąć tych artefaktów, zmodyfikuj bliskie/dalekie płaszczyzny aparatu Unity , aby uwzględnić niższą precyzję. W przypadku aplikacji opartych na urządzeniu HoloLens dalekoskładnikowy o wartości 50 m zamiast domyślnego aparatu Unity 1000 m może ogólnie wyeliminować wszelkie walki z.

Wyłączony bufor wzornika

Gdy środowisko Unity tworzy teksturę renderowania z 16-bitową głębokością, nie utworzono buforu wzornika. Wybranie formatu głębokości 24-bitowej zgodnie z opisem w dokumentacji aparatu Unity spowoduje utworzenie 24-bitowego buforu z i 8-bitowego buforu wzornika (jeśli 32-bitowy ma zastosowanie na urządzeniu (na przykład HoloLens), co jest ogólnie możliwe).

Unikaj efektów pełnoekranowych

Techniki działające na pełnym ekranie mogą być kosztowne, ponieważ ich kolejność wielkości to miliony operacji na każdej ramce. Zaleca się unikanie efektów przetwarzania końcowego , takich jak anty aliasing, bloom i nie tylko.

Optymalne ustawienia oświetlenia

Globalne oświetlenie w środowisku Unity w czasie rzeczywistym może zapewnić wybitne wyniki wizualne, ale obejmuje kosztowne obliczenia oświetlenia. Zalecamy wyłączenie globalnego oświetlenia w czasie rzeczywistym dla każdego pliku sceny aparatu Unity za pomocąustawień> oświetleniarenderowania>okna> Usuń zaznaczenie globalnego oświetlenia w czasie rzeczywistym.

Ponadto zaleca się wyłączenie całego rzutowania w tle, ponieważ dodanie kosztownego procesora GPU przechodzi do sceny aparatu Unity. Cienie można wyłączyć na światło, ale można również sterować całościowo za pomocą ustawień jakości.

Edytuj>Ustawienia projektu, a następnie wybierz kategorię >Jakość Wybierz niską jakość dla platformy UWP. Można również po prostu ustawić właściwość Shadows na Wartość Wyłącz cienie.

Zalecamy używanie oświetlenia upieczonego z modelami w akodzie Aparatu Unity.

Zmniejsz liczbę poli

Liczba wielokątów jest zmniejszana przez jedną z tych

  1. Usuwanie obiektów ze sceny
  2. Decymacja zasobów, która zmniejsza liczbę wielokątów dla danej siatki
  3. Implementowanie systemu poziomów szczegółowości (LOD) w aplikacji, który renderuje odległe obiekty o niższej wersji wielokątnej tej samej geometrii

Opis cieniowania w aplecie Unity

Łatwe przybliżenie do porównywania cieniowania w wydajności polega na zidentyfikowaniu średniej liczby operacji wykonywanych w czasie wykonywania. Można to łatwo zrobić w a aparatu Unity.

  1. Wybierz zasób cieniowania lub wybierz materiał, a następnie w prawym górnym rogu okna inspektora wybierz ikonę koła zębatego, a następnie pozycję "Wybierz cieńszy"

    Wybieranie cieniowania w aplecie Unity

  2. Po wybraniu elementu zawartości cieniowania wybierz przycisk "Kompiluj i pokaż kod" w oknie inspektora

    Kompilowanie kodu cieniującego w aplecie Unity

  3. Po skompilowaniu poszukaj w wynikach sekcji statystyk z liczbą różnych operacji zarówno dla cieniowania wierzchołka, jak i cieniowania pikseli (Uwaga: cieniowanie pikseli jest często nazywane cieniowaniem fragmentów)

    Operacje cieniowania standardowego aparatu Unity

Optymalizowanie cieniowania pikseli

Patrząc na skompilowane wyniki statystyki przy użyciu powyższej metody, cieniowanie fragmentu zwykle wykonuje więcej operacji niż cieniowanie wierzchołków, średnio. Cieniowanie fragmentów, znane również jako cieniowanie pikseli, jest wykonywane na piksel w danych wyjściowych ekranu, podczas gdy cieniowanie wierzchołków jest wykonywane tylko na wierzchołek wszystkich siatki rysowanych na ekranie.

W związku z tym nie tylko cieniowanie fragmentów ma więcej instrukcji niż cieniowanie wierzchołków ze względu na wszystkie obliczenia oświetlenia, cieniowanie fragmentów jest prawie zawsze wykonywane na większym zestawie danych. Jeśli na przykład dane wyjściowe ekranu są obrazem 2k na 2k, cieniowanie fragmentów może zostać wykonane 2000 *2000 = 4000 000 razy. Jeśli renderowanie dwóch oczu, liczba ta podwaja się, ponieważ istnieją dwa ekrany. Jeśli aplikacja rzeczywistości mieszanej ma wiele przebiegów, efektów przetwarzania końcowego pełnoekranowego lub renderowania wielu siatki w tym samym pikselu, ta liczba znacznie wzrośnie.

W związku z tym zmniejszenie liczby operacji w cieniowaniu fragmentów może zwykle dać znacznie większy wzrost wydajności w optymalizacji w cieniowaniu wierzchołka.

Alternatywy cieniowania standardowego aparatu Unity

Zamiast korzystać z renderowania fizycznego (PBR) lub innego cieniowania wysokiej jakości, przyjrzyj się użyciu bardziej wydajnego i tańszego cieniowania. Zestaw narzędzi Mixed Reality udostępnia standardowy moduł cieniowania zestawu narzędzi MRTK zoptymalizowany pod kątem projektów rzeczywistości mieszanej.

Aparat Unity zapewnia również nielitowe, oświetlone wierzchołki, rozproszone i inne uproszczone opcje cieniowania, które są szybsze w porównaniu do cieniowania standardowego aparatu Unity. Aby uzyskać bardziej szczegółowe informacje, zobacz Użycie i wydajność wbudowanych cieniowania .

Wstępne ładowanie cieniowania

Użyj wstępnego ładowania cieniowania i innych wskazówek, aby zoptymalizować czas ładowania cieniowania. W szczególności wstępne ładowanie cieniowania oznacza, że nie zobaczysz żadnych trafień ze względu na kompilację cieniowania środowiska uruchomieniowego.

Limit przerysowania

W amencie Unity można wyświetlić przerysowanie sceny, przełączając menu trybu rysowania w lewym górnym rogu widoku Scena i wybierając pozycję Przerysuj.

Ogólnie rzecz biorąc, przerysowanie może być ograniczane przez wyłusanie obiektów przed wysłaniem ich do procesora GPU. Aparat Unity zawiera szczegółowe informacje na temat implementowania aparatu Occlusion Culling .

Zalecenia dotyczące pamięci

Nadmierna alokacja pamięci & operacji cofania może mieć negatywny wpływ na aplikację holograficzną, co powoduje niespójną wydajność, zamrożone ramki i inne szkodliwe zachowanie. Szczególnie ważne jest, aby zrozumieć zagadnienia dotyczące pamięci podczas opracowywania w środowisku Unity, ponieważ zarządzanie pamięcią jest kontrolowane przez moduł odśmiecający pamięci.

Wyrzucanie elementów bezużytecznych

Aplikacje holograficzne utracą czas przetwarzania zasobów obliczeniowych do modułu odśmiecanie pamięci (GC), gdy GC zostanie aktywowany w celu analizowania obiektów, które nie są już objęte zakresem podczas wykonywania, a ich pamięć musi zostać zwolniona, dzięki czemu będzie można ją udostępnić do ponownego użycia. Stałe alokacje i delokacje zwykle wymagają częstszego uruchamiania modułu odśmiecania pamięci, co szkodzi wydajności i środowisku użytkownika.

Aparat Unity udostępnia doskonałą stronę, która szczegółowo wyjaśnia, jak działa moduł odśmieczania pamięci, oraz wskazówki dotyczące pisania bardziej wydajnego kodu w odniesieniu do zarządzania pamięcią.

Jedną z najbardziej typowych rozwiązań, które prowadzą do nadmiernego odzyskiwania pamięci, nie jest buforowanie odwołań do składników i klas w programowaniu aparatu Unity. Wszelkie odwołania powinny być przechwytywane podczas uruchamiania() lub funkcji Awake() i ponownie używane w późniejszych funkcjach, takich jak Update() lub LateUpdate().

Inne szybkie porady:

  • Używanie klasy StringBuilder C# do dynamicznego kompilowania złożonych ciągów w czasie wykonywania
  • Usuń wywołania funkcji Debug.Log(), gdy nie są już potrzebne, ponieważ nadal są wykonywane we wszystkich wersjach kompilacji aplikacji
  • Jeśli aplikacja holograficzna zwykle wymaga dużej ilości pamięci, rozważ wywołanie metody System.GC.Collect() podczas faz ładowania, takich jak podczas prezentowania ekranu ładowania lub przejścia

Buforowanie obiektów

Buforowanie obiektów to popularna technika zmniejszania kosztów ciągłej alokacji obiektów i cofania alokacji. Odbywa się to przez przydzielanie dużej puli identycznych obiektów i ponowne użycie nieaktywnych, dostępnych wystąpień z tej puli zamiast stale duplikować i niszczyć obiekty w czasie. Pule obiektów doskonale nadają się do ponownego użycia składników, które mają zmienny okres istnienia w aplikacji.

Wydajność uruchamiania

Rozważ uruchomienie aplikacji z mniejszą sceną, a następnie załadowanie pozostałej części sceny za pomocą narzędzia SceneManager.LoadSceneAsync . Dzięki temu aplikacja może jak najszybciej przejść do stanu interaktywnego. Może wystąpić duży wzrost użycia procesora CPU podczas aktywowania nowej sceny i że każda renderowana zawartość może się zacinać lub uderzać. Jednym ze sposobów obejścia tego problemu jest ustawienie właściwości AsyncOperation.allowSceneActivation na wartość "false" na ładowanej scenie, poczekaj na załadowanie sceny, wyczyść ekran na czarny, a następnie ustaw ją z powrotem na "true", aby ukończyć aktywację sceny.

Pamiętaj, że podczas ładowania sceny uruchamiania do użytkownika zostanie wyświetlony ekran powitalny holograficzny.

Zobacz też