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 wydaliśmy aplikację o nazwie Podstawy jakości, która obejmuje typowe problemy z wydajnością, projektowaniem i środowiskiem oraz rozwiązaniami dla aplikacji HoloLens 2. Ta aplikacja jest doskonałym pokazem wizualnym zawartości, która jest poniżej.
Używanie zalecanych ustawień projektu aparatu Unity
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 rzeczywistości mieszanej. Poniżej wyróżniono również niektóre z tych zalecanych ustawień.
Jak profilować przy użyciu 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 konkretnej aplikacji. Mimo że można uruchomić profiler 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 najbardziej dokładnych i przydatnych szczegółowych informacji.
Aparat Unity udostępnia doskonałą dokumentację:
- Jak zdalnie połączyć profilera aparatu Unity z aplikacjami platformy UWP
- Jak skutecznie diagnozować problemy z wydajnością za pomocą profilera aparatu Unity
Profilowanie procesora GPU
Profiler aparatu Unity
Za pomocą profilera aparatu Unity połączonego i po dodaniu profilera procesora GPU (zobacz Dodawanie profilera w prawym górnym rogu), można zobaczyć, ile czasu poświęca się odpowiednio na procesor CPU i procesor GPU 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.
Uwaga
Aby używać profilowania procesora GPU, należy wyłączyć zadania grafiki w Ustawienia odtwarzacza Unity. Aby uzyskać więcej informacji, zobacz moduł Profiler użycia procesora GPU aparatu Unity.
Debuger ramki aparatu Unity
Debuger Frame Debuger aparatu Unity jest również zaawansowanym i wnikliwym narzędziem do użycia. Zapewni to dobre omówienie tego, co procesor GPU wykonuje poszczególne ramki. Kwestie, które należy zwrócić uwagę, to dodatkowe obiekty docelowe renderowania i polecenia blit do skopiowania 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óre należy unikać.
Nakładka szybkości klatek na klatkę urządzenia HoloLens
Strona Wydajność systemu w portalu urządzeń zawiera dobre podsumowanie wydajności procesora CPU i procesora GPU urządzenia. Licznik szybkości klatek wyświetlania można włączyć w zestawie słuchawkowym i wyświetlać wykres szybkości klatek w zestawie słuchawkowym. Te opcje umożliwią odpowiednio licznik i graf klatek na sekundę, dzięki czemu otrzymasz natychmiastową opinię w dowolnej uruchomionej aplikacji na urządzeniu.
PIX
PIX może służyć również do profilowania aplikacji aparatu Unity. Dostępne są również szczegółowe instrukcje dotyczące używania i instalowania PIX dla urządzenia HoloLens 2. W kompilacji programistycznej te same zakresy, które są widoczne w debugerze Frame Debugger aparatu Unity, zostaną również pokazane 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 XR Ustawienia.renderViewportScale. Końcowy obraz przedstawiony na urządzeniu ma stałą rozdzielczość. Platforma będzie próbkować dane wyjściowe niższej rozdzielczości, aby utworzyć obraz o wyższej rozdzielczości do renderowania na wyświetlaczach.
UnityEngine.XR.XRSettings.renderViewportScale = 0.7f;
Zalecenia dotyczące wydajności procesora CPU
Poniższa zawartość obejmuje bardziej szczegółowe rozwiązania dotyczące wydajności, szczególnie przeznaczone do programowania w środowisku Unity i C#.
Odwołania do pamięci podręcznej
Zalecamy buforowanie odwołań do wszystkich odpowiednich składników i obiektów GameObjects podczas inicjowania, ponieważ powtarzające się wywołania funkcji, takie jak GetComponent<T>() i Aparat.main, są droższe w stosunku do kosztu pamięci do przechowywania wskaźnika. . Aparat.main używa po prostu elementu FindGameObjectsWithTag(), który kosztownie wyszukuje wykres sceny dla obiektu aparatu z tagiem "Main Aparat".
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 getComponent(ciąg)
W przypadku korzystania z metody 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 bardziej kosztowne niż wyszukiwanie według typu.
(Dobry) Składnik GetComponent(typ)
(Dobry) T GetComponent<T>()
(Zły) Składnik GetComponent(ciąg)>
Unikanie kosztownych operacji
Unikaj używania LINQ
Mimo że 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;
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 pod kątem pasującej listy obiektów GameObjects. Te operacje można zwykle uniknąć, buforując odwołania lub implementując składnik menedżera dla obiektów 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.
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
,bool
itp., do zmiennych typowych odwołań. Gdy zmienna typu wartość jest "boxed", jest owinięta wSystem.Object
obiekcie , który jest przechowywany na zarządzanym stercie. Pamięć jest przydzielana i ostatecznie po usunięciu musi zostać przetworzona przez moduł odśmiecający pamięć. Te alokacje i alokacje powodują koszt wydajności, a w wielu scenariuszach są niepotrzebne lub można je łatwo zastąpić mniej kosztowną alternatywą.Aby uniknąć boksowania, 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 jakint
,float?
lubMyStruct
, zamiast używać obiektu. W przypadku umieszczania tych obiektów na liście należy użyć silnie typizowanej listy, takiej jakList<int>
zamiastList<object>
lubArrayList
.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. Wszystkie kosztowne operacje w tym miejscu będą miały ogromny i spójny wpływ na wydajność.
Puste funkcje wywołania zwrotnego
Mimo że poniższy kod może wydawać się niewinny do pozostawienia 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 GameObjects ze składnikami, które mają puste powtarzające się wywołania zwrotne aparatu Unity.
void Update() { }
Uwaga
Update() jest najczęstszym objawem 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 gorzej: FixedUpdate(), LateUpdate(), OnPostRender", OnPreRender(), OnRenderImage(), itp.
Operacje 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, a wyniki są 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 powtarzać i identyczne operacje Raycast przez każdy składnik. Niektóre aplikacje mogą wymagać raycasts z różnych źródeł lub różnych masek warstwowych.
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 w funkcji 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()
Unikaj interfejsów i konstrukcji wirtualnych
Wywoływanie wywołań funkcji za pośrednictwem interfejsów a 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 go usunąć. Jednak osiągnięcie wydajności tych podejść jest warte kompromisu, jeśli użycie ich upraszcza współpracę deweloperów, czytelność kodu i konserwację kodu.
Ogólnie rzecz biorąc, zaleceniem jest nie oznaczanie pól i funkcji jako wirtualnych, chyba że istnieje wyraźne 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.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, a tym samym akceptowalny. Jednak w przypadku funkcji wielokrotnie wywoływanych każdej ramki, a także funkcji biorących duże struktury, jeśli to możliwe, zmodyfikuj definicję funkcji, aby przejść przez odwołanie. Dowiedz się więcej tutaj
Różne
Fizyki
a) 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 aucie Unity
b) Typy zderzaków w środowisku Unity mają znacznie różne cechy wydajności. Poniższa kolejność zawiera listę najbardziej wydajnych zderzaków do najmniej wydajnych zderzaków od lewej do prawej. Ważne jest, aby uniknąć zderzaków siatki, które są znacznie droższe niż pierwotne zderzacze.
Siatka skrzynki kapsułowej <<<< sfery < (wypukłe) (bez wypukłych) <
Zobacz Unity Physics Best Practices (Najlepsze rozwiązania dotyczące fizyki aparatu Unity), aby uzyskać więcej informacji
Animacje
Wyłącz bezczynne animacje, wyłączając składnik Animator (wyłączenie obiektu gry nie będzie miało takiego samego efektu). Unikaj wzorców projektowych, w których animator znajduje się w pętli, ustawiając wartość na taką samą rzecz. Ta technika nie ma znacznego nakładu pracy, bez wpływu na aplikację. Więcej informacji można znaleźć tutaj.
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 zwiększyć wydajność, wywołania rysowania muszą być strategicznie a) zredukowane lub b) przekształcone w celu uzyskania optymalnych wyników. Ponieważ same wywołania rysowania intensywnie korzystają z zasobów, zmniejszenie ich spowoduje zmniejszenie ogólnej wymaganej pracy. 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 doskonały artykuł, który zawiera omówienie i omówienie dzielenia na partie wywołań rysowania dla ich platformy.
Renderowanie z pojedynczym przekazywaniem
Renderowanie pojedynczego wystąpienia z przekazywaniem w a unity umożliwia narysowanie wywołań dla każdego oka, które można zmniejszyć do jednego wystąpienia wywołania rysowania. Ze względu na współistnienie pamięci podręcznej między dwoma wywołaniami rysowania istnieje również pewna poprawa wydajności procesora GPU.
Aby włączyć tę funkcję w projekcie aparatu Unity
- Otwórz Ustawienia OpenXR (przejdź do pozycji Edytuj>projekt Ustawienia> XR Plugin Management>OpenXR).
- Wybierz pozycję Pojedyncze wystąpienie przekazywane z menu rozwijanego Tryb renderowania.
Przeczytaj następujące artykuły 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 moduły cieniowania, które nie zostały 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.
Przetwarzanie wsadowe statyczne
Aparat Unity może wsadować wiele obiektów statycznych w celu zmniejszenia liczby wywołań rysowania do procesora GPU. Statyczne przetwarzanie wsadowe działa w przypadku większości obiektów renderujących w a aparatu Unity, które 1) współużytkują ten sam materiał i 2) są oznaczone jako statyczne (wybierz obiekt w akiecie 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 wsadowe statyczne 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 dzielenie na partie może znacznie zmniejszyć liczbę wywołań rysowania, a tym samym zwiększyć wydajność.
Aby uzyskać więcej szczegółów, przeczytaj artykuł Static Batching under Draw Call Batching in Unity (Przetwarzanie wsadowe statyczne w obszarze Rysuj wsadowe wywołania w aporcie Unity).
Dynamiczne przetwarzanie wsadowe
Ponieważ oznaczanie obiektów jako statycznych w przypadku programowania urządzeń HoloLens jest problematyczne, dynamiczne dzielenie wsadowe może być doskonałym narzędziem do zrekompensowania tego braku funkcji. Może być również przydatny w immersywnych zestawach nagłownych. Jednak dynamiczne przetwarzanie wsadowe w a 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.
Aby uzyskać pełną listę, przeczytaj artykuł Dynamiczne przetwarzanie wsadowe w obszarze Rysowanie wsadowe wywołań w środowisku Unity. Najczęściej obiekty GameObjects stają się 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 GameObjects 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 się tekstury w jedną dużą 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 a środowisku Unity będzie miał skojarzone wywołania rysowania w porównaniu do przesyłania połączonej siatki w ramach jednego modułu renderowania.
Uwaga
Modyfikowanie właściwości elementu Renderer.material w czasie wykonywania spowoduje utworzenie kopii materiału i w związku z tym potencjalnie przerwanie dzielenia na partie. Użyj elementu Renderer.sharedMaterial, aby zmodyfikować współużytkowane właściwości 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łnienia.
- Przepustowość pamięci to szybkość operacji odczytu i zapisu, które procesor GPU może wykonywać z pamięci
- Szybkość wypełnienia odnosi się do pikseli, które mogą być rysowane na sekundę przez procesor GPU.
- W środowisku Unity użyj właściwości XR Ustawienia.renderViewportScale.
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. Podczas włączania 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 znacząco zmniejszają przepustowość (a tym samym moc) związaną z ruchem buforu głębokości. Może to być duża poprawa zarówno w zakresie redukcji zużycia energii, jak i wydajności. Istnieją jednak dwa możliwe negatywne wyniki przy użyciu formatu głębokości 16-bitowej.
Walka Z
Zmniejszona wierność zakresu głębokości sprawia, że walka z jest bardziej prawdopodobna z 16 bitów niż 24-bitowa. Aby uniknąć tych artefaktów, zmodyfikuj bliskie/dalekie płaszczyzny klipów 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 na ogół wyeliminować wszelkie walki z.
Wyłączony bufor wzornika
Gdy aparat Unity tworzy teksturę renderowania z 16-bitową głębokością, nie ma utworzonego 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 zwykle ma zastosowanie).
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 aliasowanie, rozkwit i nie tylko.
Optymalne ustawienia oświetlenia
Globalne oświetlenie w czasie rzeczywistym w aferze Unity może zapewnić doskonałe wyniki wizualne, ale obejmuje kosztowne obliczenia oświetlenia. Zalecamy wyłączenie oświetlenia globalnego w czasie rzeczywistym dla każdego pliku sceny aparatu Unity za pomocą oświetlenia renderowania okien>>Ustawienia> usuń zaznaczenie globalnej oświetlenia w czasie rzeczywistym.
Ponadto zaleca się wyłączenie wszystkich rzutów 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ż kontrolować holistyczne za pomocą ustawień jakości.
Zmodyfikuj> Ustawienia projektu, a następnie wybierz kategorię Jakość wybierz pozycję > Niska jakość dla platformy UWP. Można również ustawić właściwość Cienie na wartość Wyłącz cienie.
Zalecamy używanie oświetlenia upieczonego z modelami w aucie Unity.
Zmniejsz liczbę poli
Liczba wielokątów jest zmniejszana przez jeden z tych elementów
- Usuwanie obiektów ze sceny
- Decymacja zasobów, która zmniejsza liczbę wielokątów dla danej siatki
- Implementowanie systemu poziomów szczegółów (LOD) w aplikacji, który renderuje daleko idące obiekty o niższej wersji wielokątnej tej samej geometrii
Opis cieniowania w aplecie Unity
Łatwe przybliżenie do porównywania cieniowania wydajności polega na zidentyfikowaniu średniej liczby operacji wykonywanych w czasie wykonywania. Można to łatwo zrobić w środowisku Unity.
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ń"
Po wybraniu elementu zawartości cieniowania wybierz przycisk "Kompiluj i pokaż kod" w oknie inspektora
Po skompilowaniu wyszukaj sekcję statystyk w wynikach 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)
Optymalizowanie cieniowania pikseli
Patrząc na skompilowane wyniki statystyki przy użyciu powyższej metody, cieniowanie fragmentu zazwyczaj wykonuje więcej operacji niż cieniowanie wierzchołka, średnio. Cieniowanie fragmentów, znane również jako cieniowanie pikseli, jest wykonywane na piksel w danych wyjściowych ekranu, podczas gdy cieniowanie wierzchołka jest wykonywane tylko na wierzchołku wszystkich siatk rysowanych na ekranie.
W związku z tym nie tylko cieniowania fragmentów mają więcej instrukcji niż cieniowania wierzchołków ze względu na wszystkie obliczenia oświetlenia, cieniowania fragmentów są prawie zawsze wykonywane w większym zestawie danych. Jeśli na przykład dane wyjściowe ekranu to 2k przez 2k obrazu, cieniowanie fragmentu może zostać wykonane 2000*2000 = 4 000 000 razy. W przypadku renderowania dwóch oczu liczba ta podwaja się, ponieważ istnieją dwa ekrany. Jeśli aplikacja rzeczywistości mieszanej ma wiele przebiegów, pełnoekranowych efektów przetwarzania końcowego lub renderowania wielu siatk do tego samego piksela, ta liczba znacznie się zwiększy.
W związku z tym zmniejszenie liczby operacji w cieniowaniu fragmentów może na ogół dać znacznie większe zyski wydajności w optymalizacji w cieniowaniu wierzchołka.
Alternatywy cieniowania w warstwie Standardowa aparatu Unity
Zamiast korzystać z fizycznego renderowania (PBR) lub innego cieniowania wysokiej jakości, przyjrzyj się wykorzystaniu bardziej wydajnego i tańszego cieniowania. Zestaw narzędzi Mixed Reality Toolkit udostępnia standardowy moduł cieniowania zestawu narzędzi MRTK zoptymalizowany pod kątem projektów rzeczywistości mieszanej.
Aparat Unity zapewnia również nielitowane, oświetlone wierzchołki, dyfuzory i inne uproszczone opcje cieniowania, które są szybsze w porównaniu do cieniowania w warstwie Standardowa 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 sztuczek, aby zoptymalizować czas ładowania cieniowania. W szczególności wstępne ładowanie cieniowania oznacza, że nie będzie widocznych żadnych trafień z powodu kompilacji cieniowania środowiska uruchomieniowego.
Limit przerysowania
W środowisku 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żna ograniczyć przez uścisk 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
Nadmierne przydzielanie pamięci i operacje cofania przydziału mogą mieć negatywny wpływ na aplikację holograficzną, co powoduje niespójną wydajność, zamrożone ramki i inne szkodliwe zachowanie. Szczególnie ważne jest zrozumienie zagadnień dotyczących 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 przeanalizowania obiektów, które nie są już w zakresie 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 powoduje szkodę w wydajności i środowisku użytkownika.
Aparat Unity dostarczył doskonałą stronę, która szczegółowo wyjaśnia, jak działa moduł odśmieceń pamięci i porady dotyczące pisania bardziej wydajnego kodu w odniesieniu do zarządzania pamięcią.
Jedną z najczęstszych praktyk, 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 tworzenia 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 przydziałów. Odbywa się to poprzez 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 przy użyciu narzędzia SceneManager.LoadSceneAsync. Dzięki temu aplikacja może przejść do stanu interaktywnego tak szybko, jak to możliwe. Może wystąpić duży skok użycia procesora CPU podczas aktywowania nowej sceny i że każda renderowana zawartość może być zacinana lub uderzona. 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.