Jaki jest dobry algorytm obliczania liczby klatek na sekundę w grze? Chcę pokazać to jako liczbę w rogu ekranu. Jeśli spojrzę tylko na to, ile czasu zajęło renderowanie ostatniej klatki, liczba zmienia się zbyt szybko.
Dodatkowe punkty, jeśli twoja odpowiedź aktualizuje każdą klatkę i nie zbiegają się inaczej, gdy liczba klatek rośnie, a spada.
last_frame
nie oznacza (a przynajmniej nie powinno oznaczać) czasu trwania poprzedniej klatki; Powinien oznaczać wartośćtime
, którą obliczyłeś dla ostatniej klatki. W ten sposób zostaną uwzględnione wszystkie poprzednie klatki, przy czym najnowsze klatki mają największą wagę.Tego właśnie używałem w wielu grach.
źródło
tickindex = (tickindex + 1) % MAXSAMPLES;
Cóż, na pewno
Ale, jak zauważyłeś, czas potrzebny do wyrenderowania pojedynczej klatki jest bardzo zróżnicowany, az perspektywy interfejsu użytkownika aktualizacja wartości klatek na sekundę w ogóle nie nadaje się do użytku (chyba że liczba jest bardzo stabilna).
To, czego chcesz, to prawdopodobnie średnia ruchoma lub jakiś rodzaj binningu / resetowania licznika.
Na przykład, możesz zachować strukturę danych kolejki, która zawiera czasy renderowania dla każdej z ostatnich 30, 60, 100 lub ramek typu „co masz” (możesz nawet zaprojektować ją tak, aby limit był regulowany w czasie wykonywania). Aby określić przyzwoite przybliżenie liczby klatek na sekundę, możesz określić średnią liczbę klatek na sekundę ze wszystkich czasów renderowania w kolejce:
Po zakończeniu renderowania nowej klatki kolejkujesz nowy czas renderowania i usuwasz z kolejki stary czas renderowania. Alternatywnie, możesz usunąć z kolejki tylko wtedy, gdy suma czasów renderowania przekroczyła określoną wartość (np. 1 sek.). Możesz zachować "ostatnią wartość fps" i ostatnią aktualizowaną sygnaturę czasową, aby móc wyzwolić, kiedy zaktualizować liczbę fps, jeśli chcesz. Chociaż przy średniej ruchomej, jeśli masz spójne formatowanie, drukowanie „chwilowej średniej” fps dla każdej klatki prawdopodobnie byłoby w porządku.
Inną metodą byłoby posiadanie resetującego licznika. Utrzymuj dokładny (milisekundowy) znacznik czasu, licznik klatek i wartość fps. Po zakończeniu renderowania klatki zwiększ licznik. Kiedy licznik osiągnie ustalony limit (np. 100 klatek) lub gdy czas od znacznika czasu przekroczył określoną wartość (np. 1 sek.), Oblicz fps:
Następnie zresetuj licznik do 0 i ustaw znacznik czasu na bieżący czas.
źródło
Zwiększaj licznik za każdym razem, gdy renderujesz ekran i czyść go przez pewien przedział czasu, w którym chcesz zmierzyć liczbę klatek na sekundę.
To znaczy. Co 3 sekundy zdobądź licznik / 3, a następnie wyczyść licznik.
źródło
Można to zrobić na co najmniej dwa sposoby:
Pierwsza to ta, o której inni wspomnieli wcześniej. Myślę, że to najprostszy i preferowany sposób. Musisz tylko śledzić
Obliczenie fps w tym przypadku jest tak proste, jak oszacowanie tego wzoru:
Jest też super fajny sposób, z którego możesz skorzystać pewnego dnia:
Powiedzmy, że masz do rozważenia ramki typu „i”. Użyję tego zapisu: f [0], f [1], ..., f [i-1], aby opisać, jak długo trwało renderowanie klatki 0, klatki 1, ..., klatki (i-1 ) odpowiednio.
Wtedy matematyczna definicja fps po i klatkach byłaby
I ta sama formuła, ale biorąc pod uwagę tylko klatki i-1.
Teraz sztuczka polega na zmodyfikowaniu prawej strony wzoru (1) w taki sposób, aby zawierała prawą stronę wzoru (2) i zastąpiła ją lewą stroną.
Tak (powinieneś zobaczyć to wyraźniej, jeśli napiszesz to na papierze):
Więc zgodnie z tym wzorem (chociaż moje umiejętności matematyczne są trochę zardzewiałe), aby obliczyć nowe fps, musisz znać fps z poprzedniej klatki, czas trwania renderowania ostatniej klatki i liczbę klatek, które renderowane.
źródło
To może być przesada dla większości ludzi, dlatego nie opublikowałem tego, kiedy go wdrażałem. Ale jest bardzo wytrzymały i elastyczny.
Przechowuje kolejkę z czasami ostatniej klatki, dzięki czemu może dokładnie obliczyć średnią wartość FPS znacznie lepiej niż tylko biorąc pod uwagę ostatnią klatkę.
Pozwala także zignorować jedną klatkę, jeśli robisz coś, o czym wiesz, że sztucznie zepsuje czas tej klatki.
Umożliwia także zmianę liczby ramek przechowywanych w kolejce w trakcie jej działania, dzięki czemu można przetestować w locie, jaka jest dla Ciebie najlepsza wartość.
źródło
Dobre odpowiedzi tutaj. Sposób wdrożenia zależy od tego, do czego jest potrzebny. Sam wolę średnią działającą „time = time * 0.9 + last_frame * 0,1” przez gościa powyżej.
jednak osobiście lubię mocniej ważyć moją średnią w kierunku nowszych danych, ponieważ w grze to KOLCE są najtrudniejsze do zgniatania i dlatego najbardziej mnie interesują. Więc użyłbym czegoś bardziej jak podział .7 \ .3 sprawi, że skok pojawi się znacznie szybciej (chociaż jego efekt również szybciej zniknie z ekranu ... patrz poniżej)
Jeśli skupiasz się na czasie RENDEROWANIA, to podział .9.1 działa całkiem nieźle b / c, zwykle jest bardziej płynny. Chociaż w przypadku gry / sztucznej inteligencji / fizyki skoki są dużo większym problemem, ponieważ to zwykle powoduje, że twoja gra wygląda na niestabilną (co często jest gorsze niż niska liczba klatek na sekundę, zakładając, że nie spadamy poniżej 20 fps)
Więc dodałbym też coś takiego:
(uzupełnij 3,0f dowolną wielkością, którą uznasz za niedopuszczalną wartość szczytową). Pozwoli ci to znaleźć, a tym samym rozwiązać problemy z liczbą klatek na sekundę, na końcu klatki, w której wystąpiły.
źródło
time = time * 0.9 + last_frame * 0.1
średnia kalkulacja, która sprawia, że wyświetlacz zmienia się płynnie.O wiele lepszym systemem niż używanie dużej liczby starych klatek na sekundę jest zrobienie czegoś takiego:
Ta metoda zużywa znacznie mniej pamięci, wymaga znacznie mniej kodu i przywiązuje większą wagę do ostatnich liczby klatek na sekundę niż stare, a jednocześnie wygładza skutki nagłych zmian liczby klatek na sekundę.
źródło
Możesz zachować licznik, zwiększać go po wyrenderowaniu każdej klatki, a następnie resetować licznik, gdy jesteś na nowej sekundzie (zapisując poprzednią wartość jako # wyrenderowanych klatek z ostatniej sekundy)
źródło
JavaScript:
źródło
Oto kompletny przykład użycia Pythona (ale łatwo dostosowany do dowolnego języka). Używa równania wygładzającego w odpowiedzi Martina, więc prawie nie ma narzutu pamięci, a ja wybrałem wartości, które działały w moim przypadku (możesz swobodnie bawić się stałymi, aby dostosować się do twojego przypadku użycia).
źródło
Ustaw licznik na zero. Za każdym razem, gdy rysujesz ramkę, zwiększaj licznik. Po każdej sekundzie wydrukuj licznik. spienić, spłukać, powtórzyć. Jeśli chcesz uzyskać dodatkowy kredyt, zachowaj bieżący licznik i podziel przez całkowitą liczbę sekund, aby uzyskać średnią kroczącą.
źródło
W (podobnym do C ++) pseudokodzie te dwa są tym, czego użyłem w przemysłowych aplikacjach przetwarzania obrazu, które musiały przetwarzać obrazy z zestawu kamer wyzwalanych zewnętrznie. Różnice w „liczbie klatek na sekundę” miały inne źródło (wolniejsza lub szybsza produkcja na pasku), ale problem jest ten sam. (Zakładam, że masz proste wywołanie timera.peek (), które daje mniej więcej liczbę msec (nsec?) Od uruchomienia aplikacji lub ostatniego wywołania)
Rozwiązanie 1: szybkie, ale nie aktualizowane w każdej klatce
Rozwiązanie 2: aktualizacja każdej klatki, wymaga więcej pamięci i procesora
źródło
źródło
Jak to robię!
Innymi słowy, zegar tikowy śledzi tiki. Jeśli jest to pierwszy raz, bierze aktualny czas i umieszcza go w „tickstart”. Po pierwszym tiku powoduje, że zmienna „fps” jest równa liczbie taktów zegara podzielonej przez czas minus czas pierwszego tiku.
Fps to liczba całkowita, stąd „(int)”.
źródło
Oto jak to robię (w Javie):
źródło
W Typescript używam tego algorytmu do obliczania średniej szybkości klatek i czasu klatek:
stosowanie:
Wskazówka: jeśli próbki to 1, wynikiem jest liczba klatek na sekundę i czas klatek w czasie rzeczywistym.
źródło
Jest to oparte na odpowiedzi KPexEA i podaje prostą średnią kroczącą. Uporządkowane i przekonwertowane na TypeScript dla łatwego kopiowania i wklejania:
Deklaracja zmiennej:
Funkcjonować:
Użycie (może się różnić w Twojej aplikacji):
źródło
zapisać czas rozpoczęcia i zwiększyć licznik ramek raz na pętlę? co kilka sekund możesz po prostu wydrukować liczbę ramek / (Teraz - czas rozpoczęcia), a następnie ponownie je zainicjować.
edycja: oops. podwójny ninja
źródło