Najlepsze praktyki podczas kodowania w GameMaker Studio 2

W tym artykule omówimy kilka „najlepszych praktyk”, gdy używasz GameMaker Language (w skrócie GML ) do kodowania gry, a jednocześnie wyjaśniasz trochę o wewnętrznych działaniach GameMaker Studio 2.

Zanim jednak przejdziemy dalej, warto zwrócić uwagę na dwa bardzo ważne punkty:

Jest to przewodnik , a nie metoda „wszystko-na-koniec-wszystko-definitywna-doskonała” do napisania gry! Rzeczy wymienione tutaj są bardziej na temat skali organizacyjnej i mikro-optymalizacji i powinny być włączone do twoich nawyków kodowania, gdy czujesz się dobrze z GML i uważasz, że są one odpowiednie.

Jeśli twoja gra działa dobrze i jesteś zadowolony z rzeczy takich, jakimi są, nie spiesz się, aby zmienić wszystko, tylko wycisnąć kilka dodatkowych FPS. Musisz znaleźć równowagę między czytelnym, elastycznym i modułowym kodem z czasem i energią wymaganą do zmiany rzeczy, a także ogólnym zyskiem na końcu. Zasadniczo, jeśli nie jest zepsuty, nie naprawiaj go i zachowuj to, czego się tutaj uczysz, do następnego projektu.

Powiedziawszy to, przejdźmy dalej i spójrzmy na ogólne wskazówki dotyczące pisania dobrego kodu GML, który można zastosować w dowolnym momencie …
Styl programowania

Jeśli chodzi o pisanie kodu, każdy ma swój styl . Styl, w którym programujesz, to sposób, w jaki umieszczasz nawiasy, jak wcinasz linie i jak deklarujesz zmienne itp., I jest niezbędny, aby Twój kod był jasny i czytelny dla innych ludzi (i dla twojego przyszłego siebie, kiedy musisz wrócić do tego projektu po jakimś czasie).

Istnieje wiele, wiele stylów programowania , a niektórzy twierdzą, że ich styl jest najlepszy do użycia, ale prawda jest taka, że ​​prawie każdy styl jest w porządku, pod warunkiem, że jesteś konsekwentny podczas korzystania z niego i jest jasne i oczywiste, co jest wszystkim i robi .

Powyższy obrazek to przykładowy skrypt ilustrujący powyższe punkty. Widać, że używa on komentarzy w stylu JSDoc , aby jasno wyjaśnić, co to wszystko robi, a styl kodowania jest spójny, z 4 wcięciami spacji, podkreśleniami używanymi dla lokalnych vars itp.

Zauważ również, że możesz użyć #region i #endregion aby #endregion części kodu i znacznie zwiększyć czytelność, zwłaszcza w przypadku większych skryptów zawierających wiele części. Regiony można również komentować – zobacz sekcję Edycja tej strony w podręczniku ):

Pisząc kod, powinieneś mieć świadomość, że podczas kompilacji ostatecznej gry GameMaker Studio 2 usuwa komentarze, usuwa niepotrzebne podziały wierszy i białe znaki, zastępuje wartości stałe / makro / wyliczenia i generalnie kompresuje kod w ramach procesu. Oznacza to, że możesz dodać tyle spacji wokół swojego kodu, ile potrzeba, i nie musisz się martwić o krótkie komentarze lub tylko oszczędnie.
Użyj zmiennych lokalnych

Kontynuując od powyższego punktu na temat stylu programowania, jedną z rzeczy, które wielu początkujących robi, jest wkuwanie jak największej liczby kodów w jedną linię. Na przykład:

Pamięć i zasoby wymagane do utworzenia tych zmiennych lokalnych są pomijalne i są znacznie przeważone przez natychmiastową korzyść, którą ty (lub ktokolwiek inny czytający później kod) otrzymuje z jego przejrzystości. Ten sam pomysł należy zastosować również do skryptów, w których należy przypisać argumenty wejściowe do zmiennych lokalnych na górze, ponieważ zobaczenie skryptu pełnego ogólnych zmiennych argumentX jest bardzo mylące i łatwe do popełnienia błędów.

Zmienne lokalne szybko się przetwarzają w grze, więc wykorzystaj je najlepiej, a jeśli wyrażenie pojawi się w bloku kodu lub skrypcie dwa lub więcej razy, pomyśl o utworzeniu dla niego zmiennej lokalnej. Jeśli używasz celów kompilatora YoYo , jeśli w skrypcie lub bloku kodu odwołujesz się do zmiennych global lub zmiennych instance szczególnie korzystne jest przypisanie ich do zmiennej lokalnej na początku kodu, a następnie odwołanie się do tej zmiennej lokalnej, ponieważ to da znacznie lepsza wydajność.
Tablice

Macierze są szybkie w użyciu i wymagają mniej pamięci niż struktury danych, ale mogą być dalej optymalizowane. Kiedy tworzysz tablicę, pamięć jest przydzielana do niej na podstawie jej rozmiaru, więc powinieneś najpierw zainicjować tablicę do jej maksymalnego rozmiaru, nawet jeśli nie planujesz jej wypełniać aż do później. Na przykład, jeśli wiesz, że potrzebujesz tablicy do przechowywania maksymalnie 100 wartości, od razu zainicjalizujesz ją do 100 slotów, używając funkcji array_create() :

array = array_create(100, 0);

Przydziela to pamięć w jednym „kawałku”, przy czym wszystkie wartości tablic są ustawione na domyślną wartość 0 i pomagają utrzymać szybkość, ponieważ w przeciwnym razie za każdym razem, gdy dodasz nową wartość do tablicy, cała pamięć musi zostać ponownie przydzielona jeszcze raz.

UWAGA : W przypadku celu HTML5 przypisanie takich tablic nie ma zastosowania, a tablice powinny być zainicjalizowane od 0 dla tego celu! Możesz łatwo sobie z tym poradzić, sprawdzając zmienną os_browser , na przykład:

Zauważ również, że tablice są przekazywane przez odniesienie , ale całość zostanie skopiowana po wprowadzeniu zmiany (to zachowanie nazywa się kopiowaniem przy zapisie ). Jeśli więc przekażesz tablicę do skryptu, przekażesz odwołanie do oryginalnej tablicy, a wszystkie odczytane z niej wartości będą pochodzić z oryginalnego źródła. Jest to miłe i szybkie, ale jeśli musisz zmodyfikować dowolną wartość tablicy, sama tablica jest duplikowana w momencie zapisu, a wszelkie zmiany muszą zostać zwrócone ze skryptu lub zostaną utracone. Jest to znacznie wolniejsze i pochłania więcej pamięci, więc należy uważać, jak używać tablic w skryptach.

Można jednak uniknąć tej kopii podczas zapisu, używając specjalnego modułu dostępu @ , ponieważ daje to bezpośredni dostęp do podstawowej tablicy. Na przykład:

Struktury danych

W GameMaker Studio 2 struktury danych zostały zoptymalizowane tak, aby były dużo szybsze niż poprzednie wersje GameMaker. Nadal muszą zostać wyczyszczone (zniszczone), gdy nie są używane do zwolnienia pamięci, i nadal mogą być wolniejsze niż, powiedzmy, tablice, ale łatwość użycia i dodatkowe funkcje do radzenia sobie z danymi, które zawierają, często mogą być ważniejsze niż minimalna różnica prędkości, więc nie bój się ich używać w swoich grach.

Należy zauważyć, że ze wszystkich struktur danych, w szczególności mapy DS , szybko się zapalają, zarówno do odczytu, jak i zapisu, co czyni je doskonałą opcją dla wszystkich typów zadań.

Wcześniej wspominaliśmy o akcesoriach do macierzy, ale są one również dostępne dla struktur danych, które mogą pomóc w uporządkowaniu kodu i uczynieniu go znacznie łatwiejszym do odczytania. Możesz dowiedzieć się więcej z tego poprzedniego bloga technicznego:

Akcesoria do struktur danych i tablic

Zderzenia

Istnieje wiele sposobów radzenia sobie z kolizjami w GameMaker Studio 2, a większość z nich ma trochę dodatkowego obciążenia procesora. Funkcje collision_ i point_ , funkcje miejscowe i funkcje instance_ wszystkie opierają się na kontrolach obwiedni ze wszystkimi instancjami danego typu w pomieszczeniu i nie ma w tym optymalnego sposobu optymalizacji. Robi się gorzej, jeśli zaczniesz używać precyzyjnych kolizji, ponieważ nie tylko będziesz sprawdzał granice, ale będziesz też sprawdzał piksele, co jest bardzo powolne. Mamy na ten temat starszy blog technologiczny, który warto przeczytać:

Nie znaczy to, że nie powinieneś używać tych funkcji, ponieważ mogą być bardzo przydatne. Jednak powinieneś wiedzieć, których użyć i kiedy, ponieważ wszystkie działają nieco inaczej i będą miały różne prędkości. Szorstka zasada jest taka, że ​​funkcje place_ są szybsze niż funkcje instance_ , które są szybsze niż funkcje collision_ i point_ , więc przeczytaj instrukcję i upewnij się, że point_ najbardziej odpowiednią dla każdej sytuacji.

Alternatywnie, spójrz na stworzenie systemu kolizji opartego na kafelkach, który można utworzyć za pomocą funkcji tilemap lub nawet niestandardowej tablicy 2D lub DS Grid. Będą one bardzo szybkie i pomogą zwiększyć szybkość gry. Jeśli jednak używasz nieregularnego terenu lub ścian i obiektów, które nie są wyrównane do siatki, mogą nie być odpowiednie. Bardzo prosty poradnik na temat kolizji tilemap można znaleźć w następującym artykule Brendana Waylanda:

Kolizje kafelków w GameMaker Studio 2

Zamiany tekstur i partie wierzchołków

Jeśli włączysz nakładkę debugowania , zobaczysz, że podczas testowania w nawiasie u góry ekranu znajdują się dwie cyfry. Pierwszą z nich jest liczba zamienianych tekstur, a druga to liczba partii wierzchołków. Na te liczby wpłynie wiele czynników i nigdy nie sprowadzisz ich do (0) (0), ponieważ silnik wymaga jednego lub dwóch z każdego kroku, ale powinieneś dążyć do obniżenia tych wartości tak nisko, jak to możliwe.

W przypadku zamiany tekstur najlepszym i najskuteczniejszym sposobem na to jest zoptymalizowanie sposobu przechowywania ikonek i tła na stronie tekstury. Odbywa się to z właściwości ikonki i można tworzyć strony tekstury w Edytorze grupy tekstur . Jeśli masz kilka obrazów, które są używane tylko w menu głównym (na przykład), umieść je razem na osobnej stronie tekstury. To samo, jeśli masz obrazy specyficzne dla danego poziomu, lub gracza i wrogów itp. Zasadniczo chcesz je pogrupować według użycia, aby swapy zostały zredukowane w jak największym stopniu. Dodatkowo, aby pomóc zoptymalizować VRAM, możesz użyć innego pobierania wstępnego i koloru, aby załadować i usunąć tekstury z pamięci zgodnie z wymaganiami.

UWAGA : Jak wspomniano na początku tego artykułu, jeśli gra działa dobrze z przyzwoitym FPS, nie przejmuj się zbytnio zamianą tekstur … zwłaszcza podczas tworzenia projektów na komputerach docelowych . Optymalizacje te są najlepsze, gdy są używane z dużymi grami lub urządzeniami mobilnymi niskiej jakości, a gdy są używane nieprawidłowo, mogą mieć negatywny wpływ na wydajność!

Informacje o wierzchołkach są wysyłane „partiami” do GPU w celu rysowania, a ogólnie im większa partia, tym lepiej. Podczas rysowania należy unikać „łamania” partii, ponieważ zwiększy to liczbę partii wierzchołków wysyłanych do GPU. Istnieje wiele rzeczy, które przerwieją partię, z których główne to tryby mieszania , ustawianie koloru rysowania , ustawianie rysowania alfa i rysowanie wbudowanych kształtów i prymitywów .

Więc jeśli masz kilka instancji pocisków, które rysują za pomocą trybu mieszania bm_add – na przykład – będziesz tworzył nową partię wierzchołków dla każdego z nich, co jest zdecydowanie złą rzeczą! Zamiast tego, w grze należy mieć obiekt kontrolera, który zamiast tego rysuje wszystkie kule, w ten sposób:

gpu_set_blendmode(bm_add); with (obj_BULLET) { draw_self(); } gpu_set_blendmode(bm_normal);

UWAGA : Dotyczy to nie tylko używania bm_add – każda zmiana mieszania spowoduje przerwanie partii i spowoduje trafienie wydajności.

W ten sposób wszystkie kule zostaną narysowane w tej samej partii. Metodę tę można również zastosować do koloru alfa i rysowania, a właściwie rozsądne użycie funkcji gpu_set_blendenable() , gpu_set_alphatestref() i gpu_set_alphatestenable() może znacznie poprawić wydajność i można je włączyć / wyłączyć zgodnie z wymaganiami w całym kodzie projektu, chociaż mogą nie być odpowiednie dla wszystkich typów grafiki lub projektów.

UWAGA : Jeśli nie potrzebujesz, aby instancja rysowała się podczas korzystania z kontrolera w ten sposób, możesz po prostu dodać komentarz do zdarzenia rysowania, aby pominąć domyślny rysunek lub uczynić instancję niewidoczną (chociaż uniemożliwi to uruchomienie całego kodu) na przykład we wszystkich losowaniach).

Innym sposobem zmniejszenia tych liczb jest wyłączenie opcji Oddzielna strona tekstury dla ikonek, chyba że jest to absolutnie konieczne. Każdy zapisany w ten sposób obraz jest wysyłany na własną stronę tekstury i grupowany w inny sposób, więc lepiej mieć te obrazy na zwykłej stronie tekstury. Następnie można uzyskać współrzędne UVS za pomocą funkcji sprite_get_uvs() i zapisać je w zmiennych do późniejszego wykorzystania. Może to być niewielka ilość dodatkowego kodu, ale zwiększenie, które otrzymasz, jest tego warte. Pamiętaj, że ta metoda nie zezwoli na powtarzanie tekstur!

Podobnie jak w przypadku wszystkich tych wskazówek, jeśli utrudnia to życie, a gra działa dobrze, nie przejmuj się tym zbytnio …
Cząstki

Cząsteczki oferują bardzo szybki i skuteczny sposób tworzenia dynamicznych efektów w grze, a generalnie dają dobrą wydajność. Jednak warto zauważyć, że mieszanie addytywne, mieszanie alfa i mieszanie kolorów na cząstkach może obniżyć tę wydajność, szczególnie na ruchomych obiektach, więc jeśli nie potrzebujesz, nie używaj jej! Mieszanie dodatków, w szczególności, może znacznie zwiększyć partie wierzchołków i powinno być stosowane ostrożnie.

Zauważ, że w celu innym niż HTML-HTML5, posiadanie wielobarwnych, zanikających cząstek będzie wymagało dużo buforowania obrazu i będzie bardzo powolne. Jednakże, ponieważ duszki cząstek mogą być animowane, można utworzyć animowaną ikonkę, która ma obrazy podrzędne, które zmieniają kolor, a następnie używają go do cząstki. Nadal będzie wyglądać jak stopniowa zmiana koloru, ale nie wymaga ciągłego tworzenia obrazów pamięci podręcznej.

Możesz dowiedzieć się więcej o cząstkach z bloga technicznego Guide To GameMaker Particles .
Powierzchnie

Na koniec krótko omówimy użycie powierzchni, ponieważ – począwszy od aktualizacji wersji 2.2.3 Beta – GameMaker Studio 2 wprowadził dość znaczącą optymalizację podczas korzystania z nich w grach: możliwość włączania i wyłączania bufora głębi .

Kiedy używasz zwykłych powierzchni, GMS2 faktycznie stworzy powierzchnię i towarzyszący jej bufor głębokości, aby zapewnić właściwe sortowanie głębokości podczas rysowania czegokolwiek w 3D. Jednak w większości gier 2D ten dodatkowy bufor głębokości nie jest po prostu wymagany, a więc zajmuje dodatkowe miejsce w pamięci i czas przetwarzania, które można wykorzystać na inne rzeczy. W tym miejscu wchodzi funkcja surface_depth_disable() …

Tę funkcję można wywołać przed utworzeniem powierzchni w celu wyłączenia generowania bufora głębokości, a wszystkie powierzchnie utworzone później nie będą miały utworzonego dla nich bufora głębi. Możesz włączyć / wyłączyć tę funkcję zgodnie z wymaganiami, a nawet wywołać ją raz na początku gry, aby wyłączyć bufory głębi dla wszystkich kolejnych wywołań powierzchniowych (w większości gier 2D jest to w porządku). Nie da to większego wzrostu wydajności, ale z pewnością należy pamiętać o tym, że twoja gra w dużym stopniu opiera się na powierzchniach i może uniemożliwić wyczerpanie pamięci na urządzeniach o niższych parametrach.
streszczenie

Mamy nadzieję, że dowiecie się czegoś z tego artykułu o tym, jak działa GameMaker i jak poprawić wydajność gry. Są też inne bardziej ogólne rzeczy, które mogą pomóc:

nie bój się używać funkcji trygonometrycznych jako (wbrew powszechnemu przekonaniu), że są one dość szybkie, zwłaszcza w porównaniu z cząstkami, zderzeniami, łańcuchami itp …

nie umieszczaj kodu, który nie służy do rysowania rzeczy w wydarzeniach Draw

użyj alarmu do wywołania dowolnego kodu, który nie musi być wywoływany na każdym kroku (a nie po prostu dodawania go do zdarzenia Step)

Ale, jak wspomnieliśmy na początku artykułu, wszystkie te optymalizacje są opcjonalne i jeśli gra działa dobrze z 60 partiami wierzchołków, 80 zamianą tekstur, mieszaniem addytywnym itp., Nie martw się tym zbytnio ! Po prostu pamiętaj o tym podczas programowania kolejnej gry …

http://www.americanbar.pl/
http://100mb.pl/
http://jesiennedzieciaczki.pl/
http://www.cpenergia.pl/
http://www.brugo.pl/
http://www.twojaprawda.pl/

https://dogin.pl/
http://www.angelofdeath.pl/
http://www.grykubusia.pl/
http://www.faberfaber.pl/
http://kzpr.pl/
http://podrozetv.pl/

http://poteganatury.pl/
http://terazwsieci.pl/
http://www.gajg.pl/
http://www.3pionki.pl/
http://www.bud-len.pl/
http://www.dcgroup.pl/

http://www.grajcarnia.pl/
http://www.glus.pl/
http://www.gryfbet-gielda.pl/
http://www.ann-design.pl/
https://www.redsonia.pl/
http://zlotypionek.pl/

http://www.pandasc.pl/
http://www.planszowadabrowa.pl/
http://www.gamesworld.com.pl/
http://uzyrafy.pl/
http://www.ajma.pl/
http://pansolo.pl/