Skocz do zawartości

Optymalizacja gry, wyłączanie i włączanie objektów


MetalowyNerd

Rekomendowane odpowiedzi

Witam. Mam w grze dużo obiektów i generują się kolejne. Powiedzmy, że gdy ekran gry przesuwa się w któryś z boków, tworzone są tam kolejne obiekty. Chciałbym jakoś wyłączać (albo tymczasowo usuwać) te obiekty, których nie widać (są poza widokiem), a gdy są na widoku, ponownie je włączać. Niby zastosowałem kod:

 

GML
instance_activate_object(OBIEKT_KTÓRY_MA_ZNIKAĆ);

instance_deactivate_region(view_xview[0],view_yview[0],view_wview[0],view_hview[0],false,true);

 

, ale działa to tak samo, jak bez tego kodu. Przy około 5.000 obiektów, gra zaczyna powoli tracić fps. Proszę o jakieś rozwiązanie tego problemu, bo nie wiem, czy coś robię nie tak, że to nie działa :/.

 

Pozdrawiam serdecznie.

 

Mała poprawka. ten zamieszczony kod działa tak, jak powinien, bo gdy ponownie są na widoku, to widzę, że się ładują, ale nowe obiekty tworzą się bardzo powoli i tu leży mój problem. Nie wiem, co zrobić, żeby nowe obiekty powstawały z taką samą szybkością, jakby w grze w ogóle nie było tych "niewidocznych/ukrytych".

Odnośnik do komentarza
Udostępnij na innych stronach

Od optymalizacji jest narzędzie zwane Profilerem. Znajdziesz je w debugerze. Profiler dokładnie powie Ci co jest najwolniejszym elementem twojej gry.

 

Martwi mnie to co piszesz że gra zwalnia dopiero przy 5000 obiektów. Masz za dobry komputer i nie czujesz tego co się dzieje pod jego maską.

Odnośnik do komentarza
Udostępnij na innych stronach

Ten kod na aktywację i dezaktywacje na pewno dobry? Może spróbuj tego:

GML
instance_deactivate_all(true);

instance_activate_region(view_xview[0],view_yview[0],view_wview[0],view_hview[0], true);

Edit:

bo gdy ponownie są na widoku, to widzę, że się ładują

instance_activate_region(view_xview[0]-64,view_yview[0]-64,view_wview[0]+32,view_hview[0]+32, true);

Odnośnik do komentarza
Udostępnij na innych stronach

Threef, Debuger mi nic nie mówi, a nie widzę Profilera. Co do czucia tego, co się dzieje pod maską mojego kompa... xD czuję i to słyszę, bo za każdym razem, jak ładują się kolejne obiekty, komp wydaje dziwne dźwięki ze swojego wnętrza xd. To nie jest dobry komputer, zaufaj mi. Muli nawet przy otwieraniu Menadżera Zadań...

 

ediepl, Przetestowałem:

GML
instance_deactivate_all(true);

instance_activate_region(view_xview[0]-64,view_yview[0]-64,view_wview[0]+32,view_hview[0]+32, true);

, ale gdy zostawiłem kompa na chwilę i poszedłem na chwilę na dwór (zostawiając przyciśnięty klawisz poruszania się w prawo xd), po powrocie zobaczyłem 15.500 obiektów, a fps nie wzrastał wyżej, niż do 21 klatek. Nawet, jeśli zatrzymałem postać. Chodzi o to, że te tysiące obiektów to jakby bloki terenu. Jeśli poruszałem się z powrotem w lewo, gra przycinała się tak samo, jak bym generował kolejne nowe obiekty do zapamiętania. Wiem, że istnieje jakieś rozwiązanie, tylko czuję, że jestem za mało doświadczony, żeby mi się ukazało... hmm...

 

Dodatkowo dziwi mnie fakt, że niby na yoyogames.com piszą, że gdy dezaktywujemy jakiś obiekt, to on w ogóle w grze nie istnieje... a gra zachowuje się, jakby istniały, skoro fps spada...

 

Poprawił się spadek fps, teraz przy 9050'ciu obiektach, jest pierwszy spadek fps do 29 klatek.

Odnośnik do komentarza
Udostępnij na innych stronach

ediepl, kod wrzuciłem po prostu do obiektu gracza w Create Event.

 

karolo320, nie mogę tak zrobić, bo chciałbym, żeby gracz mógł tez coś budować na mapie, a usuwanie i generowanie nowych "chunków" terenu się z tym gryzie :/. Bez obiektów nie mam pojęcia jak to zrobić, żeby na przykład były rysowane same sprite'y, czy coś w ten deseń. Powiedzmy, że każdy blok w chunku w swoim Create Event'cie ma najpierw losowanie grafiki, po tym dodatkowo obraca się losowo o 90 stopni. Nie wiem, jak po tym procesie wyłączyć ten obiekt, żeby pożerał najmniej pamięci procesora, a dodatkowo w niektórych miejscach mapy będzie na przykład ściana, przez którą nie będzie można przejść, ale która musi reagować z graczem (na przykład gdy ma dynamit).

 

ediepl, ale chodzi o to, żeby bloki terenu były interaktywne przez cały czas gry, jeśli są na widoku.

 

Uzjel, tylko nie wiem, czy przez takie łączenie obiektów, każdy pojedynczy blok terenu nadal będzie miał własne kolizje i zdarzenia, czy już nie :/.

Odnośnik do komentarza
Udostępnij na innych stronach

kod wrzuciłem po prostu do obiektu gracza w Create Event.
:frusty: Powinno być w step/begin step, jakiegoś obiektu który jest zawsze aktywny( np o_control )

 

ediepl, ale chodzi o to, żeby bloki terenu były interaktywne przez cały czas gry, jeśli są na widoku.

Kolizje można zrobić osobno. nawet kiedyś był przykład( nie pamiętam czego, chyba gry na androida od YYG ) gdzie otoczenie było na tiltsetach( tak to się pisało? :D ) a kolizje na ds_grid

Odnośnik do komentarza
Udostępnij na innych stronach

ediepl, hmm. A da się zrobić jakiś wyjątek dla danego obiektu? Żeby na przykład nie powstawał kolejny chunk na miejscu starego wyłączonego? To już chyba jest to, bo teraz w jakąś minutę gdy postać stoi, zrobiło się na miejscu jednego chunk'a podan 30.000 nowych przedmiotów, które każdy chunk oprócz terenu generuje. Już prawie to jest to, tylko jak by się dało zrobic jakiś wyjątek w tym wyłączaniu dla jednego obiektu na przykład dla samego chunk'a :) .
Odnośnik do komentarza
Udostępnij na innych stronach

Okej nie chce mi się tego wszytskiego czytać, wybaczcie. No ale..

 

Co do czucia tego, co się dzieje pod maską mojego kompa... xD czuję i to słyszę, bo za każdym razem, jak ładują się kolejne obiekty, komp wydaje dziwne dźwięki ze swojego wnętrza xd.

 

To była przenośnia.

Masz bardzo słabą optymalizację gry i nie czujesz tego bo masz komputer zbyt świeży aby zdać sobie sprawe jak kiepski jest twój kod.

Jeżeli nigdy nie robiłeś nic aby poprawić wydajność gry, to w większości przypadków automatycznie oznacza to, że można coś poprawić.

 

W sumie planowałem napisać "Wielką Księgę Optymalizacji" i chyba dzięki Tobie zacznę ją pisać.

 

Niemniej wrócę tutaj do pierwszego, najstarszego chyba przykładu optymalizacji, czyli obiektów typu ściana. Istnieje szansa, że tego nei robisz, istnieje szansa, że to robisz. To tylko przykład, bo nie będę się w tym poście bardziej rozpisywał. I kto wie, może jakiś świeżak to zobaczy i sobie zapamięta.

2ce54197a1.png

 

Na tym screenie widać jakieś 100 obiektów, mniej więcej. Każdy z nich ma oddzielnie sprawdzaną kolizję, oddzielnie rysowany i każdy musi posiadać pewien zestaw wbudowanych zmiennych, którzy nigdy nie użyje. Innymi słowy, słabo.

 

Zamieniając ten obiekt w tile i rozstawiając je w roomie, to tylko lekkie graficzki bez kolizji. Następnie robisz nowy obiekt, jakiś o bardzo łatwo zauważalnym wyglądzie, jak np. czerwone, półprzeźroczyste pudełko, obiekt ten jest prawdziwą ścianą, ale jest niewidzialny. Teraz w room editorze możesz postawić tylko kilka takich i je rozciągnąć aby pokrywały jak największą powierzchnię.

46b1457b4a.png

 

Tutaj zamiast setki obiektów, jest tylko 7.

 

Edit: Pisałeś coś o generowaniu więc zapewne nie jest to użyteczna porada. Niemniej jak masz generator, na stówę wymaga optymalizacji.

Odnośnik do komentarza
Udostępnij na innych stronach

I am vader, racja, nie chodzi mi o to, chodzi mi teraz o ustalenie wyjątku dla instance_deactivate_all.

 

ediepl, mogę załączyć kod, ale co to zmieni w tym, że po prostu chcę, żeby instance_deactivate_all obejmowało jakiś wyjątek obiektów? xd. Na przykład, żeby nie działało to na obiekt chunk, a na pozostałe wszystkie.

Odnośnik do komentarza
Udostępnij na innych stronach

Czyli w sumie mam taki kod:

 

GML
instance_deactivate_all(true);

instance_activate_object(o_CHUNK);

instance_activate_region(view_xview[0]+32,view_yview[0]+32,view_wview[0]-32,view_hview[0]-32, true);

 

I tak, jak napisał Amaterasu, będzie zamulała gra xd. Faktycznie, już po 3.000 obiektów, fps znacznie spada. Da się może ustawić region aktywacji tylko dla jednego obiektu? Chodzi o to, żeby chunki ładowały się znacznie dalej od widoku, niż reszta obiektów.

 

Coś na styl: instance_activate_region(view_xview[0]+32,view_yview[0]+32,view_wview[0]-32,view_hview[0]-32, true, obiekt);

 

ediepl, tak wiem, że nie są dosłownie usuwane ;).

Odnośnik do komentarza
Udostępnij na innych stronach

Wiesz, gdy masz 5000 obiektów "blok", to nawet jeżeli dezaktywujesz te, które są poza viewem, to trzeba się zastanowić: jak GM robi, że obiekty poza viewem są dezaktywowane?

Do tego są różne metody (brute force, BSP itp.), ale niezależnie od metody, wewnętrzny czas potrzebny na wykonanie akcji na N obiektach (np. dezaktywacja lub aktywacja) rośnie wraz ze wzrostem N. Teraz, jeżeli pomnożysz czas wykonania tej akcji przez ilość klatek na sekundę, dostaniesz coś w stylu f(N)*room_speed akcji na sekundę (f(N) zależy od metody, którą stosuje GM).

Dla N=5000, f(N)=200log2(N) (dla BSP, optymistyczne założenie, 200 może być inną wartością zależnie od szybkości metody) i room_speed=30 dostajesz coś w stylu 72000 akcji na sekundę, każda zabiera ileś cykli procesora. Nie ma nic za darmo. Gdyby dało się zrobić tak, że aktywacja/dezaktywacja obiektów następowała tylko wtedy, gdy jest to absolutnie konieczne, gra mocno by przyspieszyła. A da się.

Odnośnik do komentarza
Udostępnij na innych stronach

Amaterasu, no to teraz nie wiem, co myśleć o Twojej odpowiedzi xd, bo przez całą odpowiedź piszesz, że to będzie słabe, bo procesor i tak będzie mulił, a pod koniec piszesz cytuję:

 

Gdyby dało się zrobić tak, że aktywacja/dezaktywacja obiektów następowała tylko wtedy, gdy jest to absolutnie konieczne, gra mocno by przyspieszyła. A da się.

 

To teraz znowu robisz mi nadzieję xD.

Odnośnik do komentarza
Udostępnij na innych stronach

No bo możesz na przykład robić tak jak minecraft który przechowuje w pamięci chunki których nie potrzebuje na razie i zwalnia je dopiero po jakimś czasie. W ten sposób gra nie sprawdza non stop czy może je zapomnieć. Jasne to wymaga więcej pamięci niż zwalnianie pamięci non stop, ale oszczędza cykle procesora.

 

NO I RUSZ TYŁEK I NAUCZ SIĘ KORZYSTAĆ Z PROFILERA!

Odnośnik do komentarza
Udostępnij na innych stronach

xD dobra dobra, tylko mi powiedzcie dokładnie, gdzie ten Profiler jest x'D. Myślicie, że go nie szukałem xd? A co do tego tematu, to myślę, że można go uznać za zamknięty, gdyż ponieważ przeszedłem 30.050 bloków terenu (1202 chunki) i fps ani razu nie spadł nawet o jedną klatkę z 30 :3. Wykorzystałem po prostu kod:

 

GML
instance_deactivate_all(true);

instance_activate_region(view_xview[0]-96,view_yview[0]-96,view_wview[0]+96,view_hview[0]+96, true);

Gra działa cudownie :'). Idę dalej, a fps nie ma zamiaru spadać xD. Dziękuję bardzo za pomoc w temacie i niech mi kurde ktoś pokaże na ss'ie, gdzie ten Profiler jest, bo nie mogę znaleźć za cholerę xd. Przyda się to też innym, którzy nie mogą go znaleźć tak, jak ja ;) .

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...