Ta strona opisuje powszechne problemy z wydajnością i najlepsze praktyki ich łagodzenia.
Obliczanie skryptów
Kosztowne operacje w kodzie Luau zajmują więcej czasu na przetworzenie i mogą zatem wpłynąć na szybkość ram.Chyba że jest wykonywany równolegle, kod Luau jest wykonywany równocześnie i blokuje główny wątek, dopóki nie spotka funkcję, która zwraca wątek.
Powszechne problemy
Intensywne operacje na strukturach tabeli - Skomplikowane operacje, takie jak serjalizacja, odserializacja i głębokie klonowanie, generują wysokie koszty wydajności, szczególnie na dużych strukturach tabel.Jest to szczególnie prawdą, jeśli te operacje są rekurencyjne lub obejmują iterowanie nad bardzo dużymi strukturami danych
Wydarzenia o wysokiej częstotliwości - Łączenie drogich operacji z wydarzeniami opartymi na ramach RunService oznacza, że operacje te powtarzają się za każdym razem, co często prowadzi do niepotrzebnego zwiększenia czasu obliczeń.Te wydarzenia obejmują:
Złagodzenie
- Wzywaj kod na wydarzeniach RunService oszczędnie, ograniczając jego użycie do przypadków, w których wysoka częstotliwość wezwania jest niezbędna (na przykład aktualizacja kamery).Możesz wykonać większość innego kodu w innych wydarzeniach lub rzadziej w pętli.
- Rozbij duże lub kosztowne zadania za pomocą task.wait() rozprzestrzeniając pracę na wiele ram.
- Zidentyfikuj i zoptymalizuj niepotrzebnie drogie operacje i użyj wielowątkowości do kosztownych operacji obliczeniowych, które nie muszą mieć dostępu do modelu danych.
- Niektóre skrypty stronowe mogą skorzystać z natywnej generacji kodu, prostego flagu, który kompiluje skrypt do kodu maszynowego, a nie do kodu bajtowego.
Zakresy mikroprofilera
Zakres | Powiązane obliczenia |
Uruchom usługę.PreRender | Kod wykonywany na wydarzeniu PreRender |
Wykonaj usługę.PreSimulation | Kod wykonywany na wydarzeniu Stepped |
Wykonaj usługę.PostSimulation | Kod wykonywany na wydarzeniu Heartbeat |
Heartbeat usługi RunService | Kod wykonywany na wydarzeniu Heartbeat |
Aby uzyskać więcej informacji o debugowaniu skryptów za pomocą mikroprofilera, zobacz bibliotekę debug, która zawiera funkcje do oznaczania konkretnego kodu i dalszego zwiększania specyfiki, takie jak debug.profilebegin i debug.profileend.Wiele metod API Roblox wezwanych przez skrypty ma również własne powiązane tagi mikroprofilera, które mogą dostarczyć użyteczny sygnał.
Użycie pamięci skryptu
Wycieki pamięci mogą wystąpić, gdy piszesz skrypty, które zużywają pamięć, której zbieracz śmieci nie może prawidłowo uwolnić, gdy nie jest już używany.Wycieki są szczególnie powszechne na serwerze, ponieważ mogą być stale online przez wiele dni, podczas gdy sesja klienta jest znacznie krótsza.
Wartości pamięci następujące w Konsoli programisty mogą wskazać na problem, który wymaga dalszych badań:
- LuaHeap - Wysoki lub rosnący pobór sugeruje wyciek pamięci.
- Liczba instancji - Konsekwentnie rosnąca liczba instancji sugeruje, że odniesienia do niektórych instancji w twoim kodzie nie są gromadzone jako odpady.
- Pamięć skryptu miejscowego - Dostarcza skrypt przez podział pamięci na użycie skryptu.
Powszechne problemy
Pozostawianie połączeń włączonych - Silnik nigdy nie gromadzi odpadów wydarzeń połączonych z instancją i żadnych wartości odwołanych wewnątrz połączonego powrotu.Dlatego aktywne połączenia wydarzeń i kodu w połączonych instancjach, połączonych funkcjach i odwołanych wartościach są poza zakresem dla zbieracza pamięci odpadów, nawet po wystrzeleniu wydarzeń.
Chociaż wydarzenia są odłączone, gdy instancja, do której należą, zostanie zniszczona, powszechnym błędem jest zakładanie, że dotyczy to obiektów Player.Po opuszczeniu przez użytkownika doświadczenia silnik nie automatycznie niszczy jego reprezentatywnego obiektu Player i modelu postaci, więc połączenia do obiektu Player i instancji w ramach modelu postaci, takich jak Player.CharacterAdded, nadal zużywają pamięć, jeśli nie odłączysz ich w swoich skryptach.Może to doprowadzić do bardzo znacznych wycieków pamięci z biegiem czasu na serwerze, gdy setki użytkowników dołącza i opuszcza doświadczenie.
Tabele - Wstawianie obiektów do tabel, ale nie usuwanie ich, gdy nie są już potrzebne, powoduje niepotrzebne zużycie pamięci, szczególnie dla tabel, które śledzą dane użytkownika po dołączeniu.Na przykład następujący przykład kodu tworzy tabelę, która dodaje informacje o użytkowniku za każdym razem, gdy użytkownik się dołącza:
Przykładlocal playerInfo = {}Players.PlayerAdded:Connect(function(player)playerInfo[player] = {} -- nieco informacjiend)Jeśli nie usuniesz tych wpisów, gdy nie będą już potrzebne, tabela nadal rośnie w rozmiarze i zużywa więcej pamięci, gdy do sesji dołącza więcej użytkowników.Każdy kod, który iteruje nad tą tabelą, staje się również bardziej kosztowny pod względem obliczeń, gdy tabela rośnie w rozmiarze.
Złagodzenie
Aby wyczyścić wszystkie używane wartości w celu zapobiegania wyciekom pamięci:
Rozłącz wszystkie połączenia - Przejdź przez bazę kodu, aby upewnić się, że każde połączenie zostało wyczyszczone za pomocą jednej z następujących ścieżek::
- Rozłączanie ręcznie za pomocą funkcji Disconnect().
- Niszczenie instancji, do której należy zdarzenie za pomocą funkcji Destroy().
- Niszczenie obiektu skryptu, do którego odwołuje się połączenie
Usuń obiekty i postacie gracza po opuszczeniu - Wdroż kod, aby zapewnić, że po opuszczeniu przez użytkownika nie utrzymują się połączenia, tak jak w następnym przykładzie:
PrzykładPlayers.PlayerAdded:Connect(function(player)player.CharacterRemoving:Connect(function(character)task.defer(character.Destroy, character)end)end)Players.PlayerRemoving:Connect(function(player)task.defer(player.Destroy, player)end)
Kalkulacja fizyczna
Nadmierna symulacja fizyki może być główną przyczyną zwiększonego czasu obliczeń na ramę na serwerze i klientzie.
Powszechne problemy
Nadmierna częstotliwość kroków fizycznych - Domyślnie zachowanie kroków jest w trybie adaptacyjnym, gdzie kroki fizyczne w 60 Hz, 120 Hz lub 240 Hz zależą od złożoności mechanizmu fizycznego.
Dostępny jest również tryb stały z poprawioną dokładnością fizyki, który zmusza wszystkie złożenia fizyczne do skoku z częstotliwością 240 Hz (cztery razy na ramę).Wynika to z znacznie większej liczby obliczeń w każdym ramie.
Nadmierna liczba złożoności symulowanych obiektów - Im więcej złożonych 3D zespołów jest symulowanych, tym dłużej trwają obliczenia fizyczne w każdym ramie.Często doświadczenia będą miały obiekty, które są symulowane, które nie muszą być lub będą miały mechanizmy, które mają więcej ograniczeń i połączeń niż potrzebują.
Nadmiernie precyzyjne wykrywanie kolizji - części siatki mają właściwość CollisionFidelity wykrywania kolizji, która oferuje różne modele o różnym poziomie wpływu na wydajność.Dokładny tryb wykrywania kolizji dla części siatkowych ma najwyższy koszt wydajności i wymaga dłuższego czasu na obliczenie silnika.
Złagodzenie
Kotwiczne części, które nie wymagają symulacji - Zakotwicz wszystkie części, które nie muszą być napędzane przez fizykę, takie jak dla statycznych NPC.
Użyj adaptacyjnego krokowania fizyki - adaptacyjne krokowanie dynamicznie dostosowuje szybkość obliczeń fizyki dla mechanizmów fizycznych, umożliwiając dokonywanie aktualizacji fizyki rzadziej w niektórych przypadkach.
Zmniejsz złożoność mechanizmu * W miarę możliwości zmniejsz liczbę ograniczeń fizycznych lub połączeń w złożeniu.
- Zmniejsz ilość samokolizji w mechanizmie, na przykład poprzez zastosowanie ograniczeń lub zakazów kolizji do kończyn ragdoll, aby zapobiec ich zderzaniu się ze sobą.
Zmniejsz użycie dokładnej wierności kolizji dla siatek * Dla małych lub nieinteraktywnych obiektów, w których użytkownicy rzadko zauważą różnicę, użyj wierności pudełka.
Dla obiektów o małej lub średniej wielkości użyj wierności pudełka lub kadłuba, w zależności od kształtu.
W przypadku dużych i bardzo złożonych obiektów buduj niestandardowe kolizje za pomocą niewidzialnych części, jeśli to możliwe
Dla obiektów, które nie wymagają kolizji, wyłącz kolizje i użyj wierności skrzyni lub kadłuba, ponieważ geometria kolizji jest nadal przechowywana w pamięci.
Możesz wyrenderować geometrię kolizji do celów debugowania w Studio, przełączając wierność kolizji z widgetu Opcje wizualizacji w prawym górnym rogu widoku 3D.
Alternatywnie możesz zastosować filtr CollisionFidelity = Precise do Eksploratora, który pokazuje liczbę wszystkich części siatki z dokładną wiernością i pozwala łatwo je wybrać.
Aby uzyskać szczegółowy przegląd sposobu wyboru opcji wierności kolizji, która zrównoważa wymagania precyzji i wydajności, zobacz Ustaw parametry fizyki i renderowania.
Zakresy mikroprofilera
Zakres | Powiązane obliczenia |
fizyka krok po kroku | Ogólne obliczenia fizyki |
krok świata | Dyskretne kroki fizyki wykonywane co każdą ramę |
Zużycie pamięci fizycznej
Ruch fizyczny i wykrywanie kolizji zużywają pamięć.Części siatki mają właściwość CollisionFidelity, która określa podejście używane do oceny granic kolizji siatki.
Wspólny problem
Domyślny i precyzyjny tryb wykrywania kolizji zużywa znacznie więcej pamięci niż dwa pozostałe tryby z niższą precyzją kształtów kolizji.
Jeśli zobaczysz wysokie poziomy zużycia pamięci pod częściami fizycznymi , możesz potrzebować zbadania zmniejszenia wierności kolizji obiektów w swoim doświadczeniu.
Jak złagodzić
Aby zmniejszyć wykorzystywaną pamięć dla wierności kolizji:
- Dla części, które nie wymagają kolizji, wyłącz ich kolizje poprzez ustawienie BasePart.CanCollide, BasePart.CanTouch i BasePart.CanQuery na false .
- Zmniejsz wierność kolizji za pomocą ustawienia CollisionFidelity.Box ma najniższe obciążenie pamięci, a Default i Precise są ogólnie droższe.
- Zasadniczo bezpieczne jest ustawienie wierności kolizji dowolnej małej osadzonej części na Box .
- W przypadku bardzo złożonych dużych siatek możesz chcieć zbudować własną siatkę kolizyjną z mniejszymi obiektami z dokładnością kolizji pudełka.
Humanoidy
Humanoid jest klasą, która zapewnia szeroką gamę funkcjonalności dla postaci graczy i niegraczy (NPC).Chociaż potężny, Humanoid przychodzi z znaczącym kosztem obliczeń.
Powszechne problemy
- Pozostawienie wszystkich HumanoidStateTypes włączonych na NPCach - Istnieje koszt wydajności związany z pozostawieniem pewnych HumanoidStateTypes włączone.Wyłącz wszystkie, które nie są potrzebne dla twoich NPCów.Na przykład, chyba że twój NPC zamierza wspinać się po drabinach, bezpiecznie jest wyłączyć stan Climbing.
- Instancjalizowanie, modyfikowanie i odrodzenie modeli z Humanoidami często * Może to być intensywne dla silnika do przetworzenia, szczególnie jeśli te modele używają wielowarstwowej odzieży .Może to być szczególnie problematyczne w doświadczeniach, w których awatary często respawnują.
- W Mikroprofilu , długie tagi aktualizacjiNieaktualizowane szybkie klastry (ponad 4 ms) są często sygnałem, że instancjalizacja/modyfikacja awatara wywołuje nadmierne nieważności.
- Korzystanie z humanoidów w przypadkach, gdy nie są one wymagane - Statyczne NPC, które nie poruszają się ogólnie, nie mają potrzeby klasy Humanoid.
- Odtwarzanie animacji na dużej liczbie NPC z serwera - animacje NPC, które uruchamiają się na serwerze, muszą być na serwerze symulowane i replikowane do klientaMoże to być zbędne obciążenie.
Złagodzenie
- Odtwarzaj animacje NPC na klientzie - W przypadkach z dużą liczbą NPCów rozważ stworzenie Animator na klientzie i uruchomienie animacji lokalnieZmniejsza to obciążenie na serwerze i konieczność niepotrzebnej replikacjiUmożliwia także dodatkowe optymalizacje (na przykład tylko odtwarzanie animacji dla NPCów, które są blisko postaci).
- Wykorzystaj przyjazne dla wydajności alternatywy dla Humanoidów - modele NPC niekoniecznie muszą zawierać obiekt humanoidowy.
- Dla statycznych NPCów użyj prostego AnimationController, ponieważ nie muszą się poruszać, ale po prostu potrzebują odtwarzać animacje.
- W przypadku przemieszczania NPCów rozważ implementację własnego kontrolera ruchu i użycie AnimationController do animacji, w zależności od złożoności Twoich NPC.
- Wyłącz nieużywane stany humanoidów - Użyj Humanoid:SetStateEnabled(), aby włączyć tylko niezbędne stany dla każdego humanoida.
- Modele NPC z częstym odrodzeniem - Zamiast niszczyć NPC całkowicie, wyślij NPC do basenu nieaktywnych NPC.W ten sposób, gdy wymagane jest odrodzenie nowego NPC, możesz po prostu ponownie aktywować jednego z NPCów z basenu.Proces ten nazywa się poolowaniem, co minimalizuje liczbę razy, w których konieczne jest instancjowanie znaków.
- Spawnuj tylko NPC, gdy użytkownicy są w pobliżu - Nie spawnuj NPC, gdy użytkownicy nie są w zasięgu, i wyeliminuj ich, gdy użytkownicy opuszczą swój zasięg.
- Unikaj dokonywania zmian w hierarchii awatarów po jej zainicjowaniu - Niektóre modyfikacje hierarchii awatarów mają znaczące implikacje dla wydajności.Dostępne są niektóre optymalizacje:
- W przypadku niestandardowych animacji proceduralnych nie aktualizuj właściwości JointInstance.C0 i JointInstance.C1. Zamiast tego aktualizuj właściwość Motor6D.Transform.
- Jeśli musisz przymocować jakiekolwiek BasePart obiekty do awatara, zrób to poza hierarchią awatara Model.
Zakresy mikroprofilera
Zakres | Powiązane obliczenia |
stepsHumanoidowy | Kontrola i fizyka humanoidów |
stopniowa animacja | Animacja ludzoidów i animatorów |
aktualizacja NieaktualizowanychSzybkichKlasterek | Związane z instancjonowaniem lub modyfikowaniem awatara |
Renderowanie
Znaczna część czasu, jaki klient spędza na każdym ramie, jest poświęcona na renderowanie sceny w obecnym ramie.Serwer nie wykonuje żadnego renderowania, więc ta sekcja jest wyłączna dla klienta.
Wywołaj wezwania
Wezwanie do rysowania to zbiór instrukcji od silnika do GPU do rysowania czegośWezwania do rysowania mają znaczny nadmiar.Ogólnie rzecz biorąc, im mniej jest wezwań do rysowania na ramę, tym mniej czasu obliczeniowego jest poświęcane na renderowanie ramy.
Możesz zobaczyć, ile wezwań do renderowania występuje obecnie z przedmiotem Statystyki renderowania > Czas w Studio.Możesz wyświetlić Statystyki renderowania w klientzie, naciskając ShiftF2.
Im więcej obiektów musi być narysowanych w twojej scenie w danym kadrze, tym więcej wezwań do GPU jest wykonywanych.Jednak silnik Roblox wykorzystuje proces o nazwie instancjonowanie, aby skompresować identyczne siatki z tymi samymi cechami tekstury do jednego wezwania do rysowania.W szczególności, wiele siatek z tymi samymi MeshId jest obsługiwanych w jednym wezwaniu do rysowania, gdy:
- Materiały są identyczne, gdy zarówno SurfaceAppearance i MeshPart.TextureID nie istnieją
Inne częste problemy
Nadmierna gęstość obiektów - Jeśli duża liczba obiektów jest skoncentrowana przy wysokiej gęstości, renderowanie tej części sceny wymaga więcej wezwań do rysowania.Jeśli znajdujesz spadek częstotliwości klatek, gdy patrzysz na pewną część mapy, może to być dobry sygnał, że gęstość obiektów w tym obszarze jest zbyt wysoka
Obiekty takie jak nadruki, tekstury i cząsteczki nie są dobrze rozdzielane i wprowadzają dodatkowe wezwania do rysowania.Zwróć dodatkową uwagę na te typy obiektów w scenie.W szczególności zmiany właściwości do ParticleEmitters mogą mieć dramatyczny wpływ na wydajność.
Pominięte możliwości instancjonowania - Często scenka będzie zawierać tę samą siatkę powieloną wiele razy, ale każda kopia siatki ma różne ID zasobów siatki lub tekstury.Uniemożliwia to instancjalizację i może prowadzić do niepotrzebnych wezwań do rysowania.
Wspólną przyczyną tego problemu jest sytuacja, gdy cała scena jest importowana naraz, zamiast importować poszczególne zasoby do Roblox, a następnie je powielić po ich zaimportowaniu, aby złożyć scenę.
Nadmierna złożoność obiektu - Chociaż nie jest tak ważna jak liczba wezwań do rysowania, liczba trójkątów w scenie wpływa na to, jak długo potrwa renderowanie ramki.Sceny z bardzo dużą liczbą bardzo skomplikowanych siatek są powszechnym problemem, podobnie jak sceny z właściwością MeshPart.RenderFidelity ustawioną na Enum.RenderFidelity.Precise na zbyt wielu siatkach
Nadmierne rzucanie cienia - Przetwarzanie cieni jest kosztowne, a mapy zawierające dużą liczbę i gęstość światła, które rzucają cienie (lub dużą liczbę i gęstość małych części wpływanych przez cienie), prawdopodobnie będą miały problemy z wydajnością.
Wysoka przejrzystość przeciągnięcia - Umieszczenie obiektów o częściowej przejrzystości w pobliżu siebie zmusza silnik do renderowania pokrywających się pikli wielokrotnie, co może zaszkodzić wydajności.Aby uzyskać więcej informacji na temat identyfikacji i naprawy tego problemu, zobacz Usuń przeźroczystości warstwowe.
Złagodzenie
- Instancjonowanie identycznych siatek i zmniejszanie ilości unikalnych siatek - Jeśli zapewnisz, że wszystkie identyczne siatki mają te same ID zasobów podstawowych, silnik może je rozpoznać i wyrenderować w jednym połączeniu wywołania.Upewnij się, że każdą siatkę przesyłasz tylko raz na mapie, a następnie powielasz je w Studio, aby je ponownie wykorzystać, zamiast importować duże mapy jako całość, co może spowodować, że identyczne siatki będą miały odrębne ID zawartości i zostaną rozpoznane przez silnik jako unikalne zasoby.Pakiety są przydatnym mechanizmem do ponownego wykorzystania obiektów.
- Oczyszczanie - Oczyszczanie opisuje proces usuwania wezwań do obiektów, które nie wchodzą w skład ostatecznego renderowanego obrazu.Domyślnie silnik pomija wezwania do rysowania dla obiektów poza polem widzenia kamery (przerzucanie frustum), ale nie pomija wezwań do rysowania dla obiektów zakrytych z widoku przez inne obiekty (przerzucanie zakrycia).Jeśli twoja scena ma dużą liczbę wezwań do rysowania, rozważ wdrożenie własnego dodatkowego przesiewania dynamicznie na czasie dla każdej ramy, takiego jak zastosowanie następujących wspólnych strategii:
- W przypadku środowisk wewnętrznych wdroż system pokoju lub portalu, który ukrywa obiekty nie zajęte obecnie przez żadnych użytkowników.
- Zmniejszanie wierności renderowania - Ustaw wierność renderowania na Automatyczną lub Wydajność .Pozwala to siatkom powrócić do mniej skomplikowanych alternatyw, które mogą zmniejszyć liczbę poligonów, które należy narysować.
- Wyłączanie rzucania cieni na odpowiednich częściach i lekkich obiektach - Złożoność cieni w scenie można zmniejszyć, wyłączając selektywnie właściwości rzucania cieni na lekkich obiektach i częściach.Można to zrobić w czasie edycji lub dynamicznie podczas uruchamiania.Niektóre przykłady to:
Użyj właściwości BasePart.CastShadow, aby wyłączyć rzucanie cieni na małych częściach, na których prawdopodobnie nie będą widoczne cienie.Może to być szczególnie skuteczne, gdy zostanie zastosowane tylko do części znajdujących się daleko od kamery użytkownika.
Wyłącz cienie na poruszających się obiektach, jeśli jest to możliwe.
Wyłącz Light.Shadows na lekkich instancjach, gdzie obiekt nie musi rzucać cieni.
Ogranicz zasięg i kąt światła instancji.
Użyj mniej lekkich instancji.
Zakresy mikroprofilera
Zakres | Powiązane obliczenia |
Przygotuj i wykonaj | Ogólne renderowanie |
Wykonaj/Scena/ computeLightingPerform | Aktualizacje siatki światła i cienia |
ŚwiatłoGridCPU | Aktualizacje siatki światła Voxel |
ShadowMapSystem | Mapeowanie cienia |
Wykonaj/Scenę/Zaktualizuj widok | Przygotowanie do renderowania i aktualizacji cząstek |
Wykonaj/Scenę/RenderView | Renderowanie i post-przetwarzanie |
Sieciowanie i replikacja
Sieciowanie i replikacja opisują proces, w którym dane są wysyłane między serwerem a połączonymi klientami.Informacje są wysyłane między klientem a serwerem co ramę, ale większe ilości informacji wymagają więcej czasu obliczeniowego.
Powszechne problemy
Nadmierny ruch zdalny - Wysyłanie dużej ilości danych za pośrednictwem lub obiektów lub wzywanie ich bardzo często może doprowadzić do dużej ilości czasu CPU poświęcanego na przetwarzanie otrzymanych pakietów w każdym ramie.Powszechne błędy obejmują:
- Replikowanie danych każdego ramu, który nie musi być replikowany.
- Replikowanie danych na wejściu użytkownika bez żadnego mechanizmu ograniczającego ich ilość
- Wysyłanie większej ilości danych niż jest wymagane.Na przykład wysyłanie całego ekwipunku gracza, gdy kupują przedmiot, a nie tylko szczegóły zakupionego przedmiotu
Tworzenie lub usuwanie złożonych drzew instancji - Kiedy dokonana zostanie zmiana w modelu danych na serwerze, zostanie ona odzwierciedlona w połączonych klientachOznacza to, że tworzenie i niszczenie dużych hierarchii instancji, takich jak mapy, może być bardzo intensywne w zakresie sieci.
Wspólnym winowajcą jest tutaj złożone dane animacji zapisane przez wtyczki edytora animacji w szablonach.Jeśli nie zostaną one usunięte przed opublikowaniem gry i animowany model będzie regularnie kopiowany, duża ilość danych zostanie powielona niepotrzebnie.
Serwis tweeningu strony serwera - Jeśli TweenService jest używany do tweenowania obiektu po stronie serwera, właściwość tweenowana jest replikowana do każdego klienta co każdą ramę.Nie tylko powoduje to, że nastolatek jest zdenerwowany, gdy zmienia się opóźnienie klientów, ale powoduje również dużo niepotrzebnego ruchu sieciowego.
Złagodzenie
Możesz wykorzystać następujące taktyki, aby zmniejszyć niepotrzebną replikację:
- Unikaj wysyłania dużej ilości danych naraz za pomocą zdalnych wydarzeń .Zamiast tego wysyłaj tylko niezbędne dane przy niższej częstotliwości.Na przykład, dla stanu postaci, powtórz go, gdy zmieni się, a nie za każdym razem, gdy się zmieni.
- Pobierz skomplikowane drzewa instancji tak jak mapy i rozładowuj je w kawałkach, aby rozdzielić pracę replikującą te na wiele ram.
- Wyczyść metadane animacji , szczególnie katalog animacji rigów po ich zaimportowaniu
- Ogranicz kopiowanie niepotrzebnych instancji , szczególnie w przypadkach, gdy serwer nie musi mieć wiedzy o tworzonych instancjach.Obejmuje to:
- Efekty wizualne, takie jak wybuch lub strzał magicznego zaklęcia.Serwer musi znać lokalizację tylko po to, aby określić wynik, podczas gdy klienci mogą tworzyć wizualizacje lokalnie.
- Modele widoku przedmiotów w pierwszej osobie.
- Przedmioty przejściowe na klientzie zamiast na serwerze.
Zakresy mikroprofilera
Zakres | Powiązane obliczenia |
Pakiety procesowe | Przetwarzanie wchodzących pakietów sieciowych, takich jak wezwania zdarzeń i zmiany właściwości |
Zarezerwuj przepustowość i uruchom nadawców | Wydarzenia wychodzące istotne na serwerach |
Zużycie pamięci zasobu
Najwyższy mechanizm wpływu dostępny dla twórców do poprawy zużycia pamięci klienta polega na włączeniu przesyłania instancji.
Przekazywanie instancji
Transmisja instancji wybierowo ładowuje części modelu danych, które nie są wymagane, co może doprowadzić do znacznie zmniejszonego czasu obciążenia i zwiększenia zdolności klienta do zapobiegania awariom, gdy znajdzie się pod presją pamięci.
Jeśli napotykasz problemy z pamięcią i masz wyłączoną transmisję instancji, rozważ aktualizację swojego doświadczenia, aby je wspierać, szczególnie jeśli twój świat 3D jest duży.Transmisja instancji opiera się na odległości w przestrzeni 3D, więc większe światy naturalnie więcej z tego korzystają.
Jeśli transmisja instancji jest włączona, możesz zwiększyć jej agresywność. Na przykład rozważ:
- Zmniejszenie wykorzystania trwałego StreamingIntegrity .
- Zmniejszanie promienia strumieniowania .
Aby uzyskać więcej informacji o opcjach przesyłania i ich korzyściach, zobacz Właściwości przesyłania.
Inne częste problemy
- Duplikacja zasobów - Pospolitym błędem jest przesłanie tego samego zasobu wielokrotnie, co prowadzi do różnych identyfikatorów zasobów.Może to doprowadzić do tego, że ta sama treść zostanie zapisana w pamięci wiele razy.
- Nadmierna objętość zasobów - Nawet gdy zasoby nie są identyczne, zdarzają się przypadki, w których przegapiane są możliwości ponownego wykorzystania tego samego zasobu i oszczędzania pamięci.
- Pliki audio - Pliki audio mogą być zaskakującym kontyngentem zużycia pamięci, szczególnie jeśli załadujesz je wszystkie do klienta naraz, a nie tylko to, czego potrzebujesz dla części doświadczenia.Dla strategii zobacz Czas ładowania.
- Wysokiej rozdzielczości tekstury - zużycie pamięci graficznej dla tekstury nie jest związane z rozmiarem tekstury na dysku, ale raczej z liczbą pikseli w teksturze.
- Na przykład tekstura o rozmiarze 1024x1024 zużywa cztery razy więcej pamięci graficznej niż tekstura 512x512.
- Przesłane do Roblox obrazy są transkodowane do stałego formatu, więc nie ma korzyści z pamięci z przesłaniem obrazów w modelu kolorów związanych z mniejszą ilością bajtów na pikselu.Podobnie, kompresowanie obrazów przed przesłaniem lub usunięciem kanału alfa z obrazów, których nie potrzebujesz, może zmniejszyć rozmiar obrazu na dysku, ale albo nie poprawia, albo poprawia tylko minimalnie zużycie pamięci.Chociaż silnik automatycznie zmniejsza rozdzielczość tekstury na niektórych urządzeniach, zakres skalowania w dół zależy od cech urządzenia, a nadmierna rozdzielczość tekstury nadal może powodować problemy.
- Możesz zidentyfikować zużycie pamięci graficznej dla danego tekstury, rozszerzając kategorię Pamięć graficzna w konsoli programisty .
Złagodzenie
- Uploaduj tylko raz zasoby - Powtórz ten sam identyfikator zasobów na przestrzeni obiektów i upewnij się, że te same zasoby, szczególnie siatki i obrazy, nie są przesyłane wielokrotnie osobno.
- Znajdź i napraw zduplikowane zasoby - Poszukaj identycznych części siatki i tekstur, które są przesyłane wielokrotnie z różnymi ID.
- Chociaż nie ma API do wykrywania podobieństwa zasobów automatycznie, możesz zebrać wszystkie ID zasobów obrazu w swoim miejscu (ręcznie lub za pomocą skryptu), pobrać je i porównać je za pomocą zewnętrznych narzędzi do porównywania.
- W przypadku części siatkowych najlepszą strategią jest wzięcie unikalnych identyfikatorów siatki i zorganizowanie ich według rozmiaru, aby ręcznie zidentyfikować duplikaty.
- Zamiast używać oddzielnych tekstur dla różnych kolorów, przeslij jedną teksturę i użyj właściwości SurfaceAppearance.Color, aby zastosować różne odcienie do niej.
- Importowanie zasobów na mapie osobno - Zamiast importować całą mapę naraz, importuj i odbuduj zasoby na mapie indywidualnie i odbuduj je.Importer 3D nie dokonuje żadnej de-duplikacji siatek, więc jeśli zaimportujesz dużą mapę z wieloma odrębnymi płytkami podłogowymi, każda z tych płytek zostanie zaimportowana jako odrębny zasób (nawet jeśli są duplikatami).Może to doprowadzić do problemów z wydajnością i pamięcią w dół linii, ponieważ każda siatka jest traktowana indywidualnie i zajmuje pamięć oraz wywołuje wezwania do wyciągania.
- Ogranicz liczbę pikseli obrazów do nie więcej niż niezbędnej ilościChyba że obraz zajmuje dużą ilość przestrzeni fizycznej na ekranie, zwykle potrzebuje maksymalnie 512x512 pikseli.Większość mniejszych obrazów powinna mieć wymiar mniejszy niż 256x256 pikseli.
- Użyj arkuszy obcinających , aby zapewnić maksymalne ponowne wykorzystanie tekstur w mapach 3D.Aby uzyskać kroki i przykłady, jak tworzyć arkusze obcinające, zobacz tworzenie arkuszy obcinających.
Czasy wczytyвания
Wiele doświadczeń implementuje niestandardowe ekrany ładowania i wykorzystuje metodę ContentProvider:PreloadAsync() w celu żądania zasobów, aby obrazy, dźwięki i siatki były pobierane w tle.
Zaletą tego podejścia jest to, że pozwala ci upewnić się, że ważne części twojego doświadczenia są w pełni załadowane bez wyskakiwania.Jednak powszechnym błędem jest przesadne wykorzystanie tej metody do przedsprzedaży większej liczby zasobów niż są rzeczywiście wymagane.
Przykładem złej praktyki jest ładowanie całegoWorkspace.Chociaż może to zapobiec pojawieniu się tekstury, znacznie zwiększa czas ładowania.
Zamiast tego użyj tylko ContentProvider:PreloadAsync() w niezbędnych sytuacjach, które obejmują:
- Obrazy w ekranie ładowania.
- Ważne obrazy w menu doświadczeń, takie jak tła przycisków i ikony.
- Ważne zasoby w obszarze startowym lub spawnowania.
Jeśli musisz załadować dużą liczbę zasobów, zalecamy zapewnienie przycisku Pomiń ładowanie .