Niedzielne Dev-logi

Intensywne prace

Prace nad poprawą ekranu ładowania były tak intensywne, że nawet nie zauważyłem kiedy minęła niedziela. Niestety Unity nie współpracowało ze mną tak jak tego oczekiwałem. Pojawiło się kilka drobnych problemów, które koniec końców urosły do takiej rangi, że będzie wymagane całkowite przebudowanie procesu ładowania wszystkich zasobów.
Niestety asynchroniczność, czy też korutyny z Unity są na tyle specyficzne i wymagające, że należy poświęcim im znacznie więcej uwagi. Pierwotnie część zasobów była umieszczona na scenie przez inspektor. Były to głównie "uchwyty" pod całe dane (gracz, przeciwnicy itd), aby ułatwić sobie życie część skryptów była właśnie w tych obiektach. Na moje nieszczęście ułatwianie sobie pracy powoduje, że tej pracy staje się więcej.
Nie pozostaje nic innego, jak przypisywać skrypty do obiektów przez korutyny ładujące wstępne zasoby (awake), a resztę dograć w korutynie uzupełniającej (start). Jest też druga opcja - wczytywanie wszystkiego w jedej korutynie i to w metodzie start. Ta opcja zakłada, że UI w awake może mieć gdzieś moją potrzebę zatualizowania paska postępu ładowania, a co za tym idzie trzeba będzie całość przenieść do start, gdzie UI powinno już być gotowe.



Przerwa świąteczna i noworoczna

Tworzenie gry jest ważne, ale życie realne jest jeszcze ważniejsze - związku z tym udaję się na dłuższą przerwę swiąteczno-noworoczną.

Do zobacznia w nowym roku - 4 stycznia 2026!

Po(d)stępy ekranu ładowania

Od poprzedniego wpisu prace nad ekranem ładowania znacząco przyśpieszyły i ruszyły... do tyłu. Ilość komplikacji jakie stanęły mi na drodze by doprowadzić cały mechanizm do pełnej funkcjonalności przerosły moje oczekiwania. To tez nie tak, że liczyłem na to, że wszystko pójdzie jak po maśle, ale Unity i jego mechanizm inicjalizacji komponentów nie ułatwił (i nie ułatwia tego zadania).
Po mimo komplikacji, nadal wszystko działa - ekrał ładowania zasłania proces ładowania i generowania sceny, a listy z akcjami i zadaniami do wykonania robią swoje. Problem tylko w tym, że pasek nie może zostać tak ot zaktualizowany. Z działań jakich muszę się podjąc to dopracować metody asynchroniczne (których za bardzo nie lubię stosować w Unity) oraz zrezygnować z metod Awake i Start. Te dwie ostatnie są w dużej mierze przyczyną "ukrytych" błędów, które właśnie utrudniają implementację pasku postępu ładowania w ekranie ładowania.



Co dalej?

Dalej będą kontynuowane prace nad ekranem ładowania. Tym razem chcę przebudować procesy ładowania danych tak aby nie były one zależne od Awake i Start, gdyż obie metody w wariancie asynchronicznym mają tendencje do wywalania się. Nie zawsze jest problem, ale po co ryzykować, że u któregoś z graczy akurat pojawi się taki problem.



Także walka trwa w najlepsze, mam nadzieję, że już w przyszłym tygodniu będę mógł podzielić się wspaniałymi wieściami, że wszystko działa. Widzimy się za tydzień.

Mała przerwa

Od ostatniego wpisu minęło więcej czasu niż się spodziewałem. Chwilowy odpoczynek od projektu pozwolił mi na zebranie myśli i zaplanowanie kolejnych kroków, a na koniec doszła jeszcze choroba, która po dziś dzień dajesię we znaki. Na szczęscie już jest lepiej i mogę wrócić do pracy nad grą.



Ekran ładowania

Na warsztat wziąłem ekran ładowania. Zwykły statyczny obrazek z napisem "Ładowanie..." nie był wystarczający. Chciałem czegoś więcej. Coś co da graczowi informację o tym, że gra faktycznie coś robi w tle. Więc (tu też za sugestią mojego brata) postanowiłem dodać porady odniośnie rozgrywki oraz pasek postępu ładowania.
Mechanika porad jest prosta - losowo wybierana jest jedna z dostępnych porad i wyświetlana na ekranie ładowania. Porady są przechowywane w dedykowanym skrypcie, co pozwala na łatwe ich dodawanie i modyfikowanie. Zastawiam się jeszcze na opracowaniem formatu porad, sposobie ich wyświetlania. Ekrany ładowania są (na tą chwilę stosunkowo krótkie), więc wyślałem nad dodaniem opcji - "kończenia ładowania" za pomocą klawisza (lub kliknęcia w przycisk). Kiedy zawartość zostanie załadowana, gracz będzie mógł sam zdecydować kiedy chce przejść do gry. Do tego celu posłuży przycisk "Kontynuuj" / "Kliknij aby kontynuować" itp., lub naciśnięcie klawisza (spacja/enter). To pozwoli na przeczytanie porady, a także na przygotowanie się do rozgrywki.
Pasek wczytywania... z nim będzie znacznie więcej pracy. Na chwilę obecną jest on tylko wizualnym elementem, który nie odzwierciedla faktycznego postępu wczytywania. W zasadzie to nie odzwierciedla niczego. Poprostu jest. Wyzwaniem tutaj jednak będzie wybranie jednej z dwóch opcji aktualizacji paska.
1. Będzie on aktualizowany po każdym przygotowanym elemencie, a ilość "kroków" będzie stała (np. 10 kroków - 10% za każdy krok). Co za tym idzie, dodanie kolejnego elementu do przygotowania będzie wymagało zmiany ilości kroków, oraz dopisanie linijek kodu do aktualizacji paska. Dużo ręcznej pracy, ale bardzo proste w implementacji.
2. Tablice tasków. Każdy element, który musi zostać przygotowany zostanie umieszczony jako funkcja w tablicy. Ilość kroków będzie zliczna na podstawie ilości elementów w tablicy. Ten sposób będzie wymagał więcej pracy przy implementacji, ale za to dodanie kolejnego elementu do przygotowania będzie wymagało tylko dopisania funkcji do tablicy. Nie będzie potrzeby zmiany ilości kroków, ani dopisywania linijek kodu do aktualizacji paska.



Co dalej?

Po za ekranem ładowania planuję jeszcze zrobić system ustawień oraz dodać mechanikę ulepszania postaci i broni.

Do zobaczenia w następnym devlogu za tydzień!

Błędy, których nie powinno być

W tym tygodniu skupiłem się tylko na poprawie istniejących w grze błędów. Istniejących dzięki mojej twórczości (no a jak). Na pierwszy ogień poszła optymalizacj a kodu pod większą czytelność. Nie jest to może błąd, ale spora poprawa. Pogrupowanie eventów wedle klas, a to wszystko wewnątrz globalnej klasy eventów - spora czytelność, a może i nawet drzwi do czegoś nowego.

Dodanie czegoś nowego nie zawsze oznacza tylko pozytywy. Przypadkiem wykryłem krytyczny błąd tylko przez to, że przypadkiem nacisnąłem klawisze ruchu postacią... na elranie ładowania. To wystarczyło by kod się wykrzaczył, bo jeden z istotnych elementów, pomimo bycia - nie był. Klasyczny przypadek wywołania czegoś, czego jeszcze nie ma.
Eventy doczekały się także własnego interface. Nie dotyczy on dokładnie samych eventów, ale wymusza on konkretne metody do subskrybcji i wyłączenia subskrypcji eventów. Daje to gwarancję, że w kodzie zawsze będzie taka i taka metoda, w której taki i taki event zostanie zasubskrybowany i odsubsrybowany. Jest jeszcze zmienna kontrolna, która blokuje wywowałenie owych metod. Nie ma powodu do ponownej subkrybcji eventów jeśli one już są w subskrybcji i vice versa.
Miałem z tym sporo frustracji, dlatego system bootrapów okazał się zbawienny. Powolił mi on zredukować jakiekolwiek błędy tego typu do zera. Jestem tak pewien tego systemu, że mógłbym usunąć wszelkie dodatkowe "osłony".

Dziś strasznie leniwie, ale większość czasu to było rozwiązywanie problemu, który sam stworzyłem przez olanie kliku linijek kodu... To tyle, widzimy się za trzy tygodnie, przerwa techniczna :).

Masa zmian

Co to był za tydzień, tyle planów do zrealizowania w grze, a ostatecznie zrobiłem coś zupełnie innego. Na pierwszy ogień niech pójdzie sposób zapisu wersji. Na swoje potrzeby (częste poprawki) zdecydowałem się na własny zapis, nie jest unikalny (tzn nie był), ale w miarę czytelny "DDMMYYHHVC". Zapis prosty, ale doszedłem do wniosku, że mógłby powodować on drobne problemy w orientacji między kolenymi wersjami, dlatego nowy zapis - "YYMMDDVVCC". Prostota zachowana i nie będzie już problemów w orientacji.

Dźwięki

Niby tylko zwykłe dźwięki, ale jak znacząco wpływają na rozgrywkę. Dodanie do menu głównego utworu pogrywającego w tle nie daje już takiego efektu pustki (tak wiem, UI tam dalej woła o wypełnienie). Długo kombinowałem jakiego utworu potrzebuję, ostatecznie padło na motyw horroru, co idealnie będzie się komponowało z tym co gracz spotka w trakcie rozgrywki. Arena również dostała utwór, który pogrywając w tle wypełnia "coś" czego po części brakowało. Do tego dodanie dźwięków dla broni i podnoszenia zasobób sprawia, że coś dzieje się więcej niż tylko poruszające obrazki.

Nowe zasoby

Zasoby - monety i doświadczenie bojowe. Pierwsze do ulepszania broni i reszty wyposarzenia, a drugie do ulepszania postaci. Na chwilę obecną nie mają one zastosowania, ale dzięki testom będę mógł już za jakiś czas dodać możliwość ulepszania postaci i sprzętu.

Wydajność, jakość i funkcjonalność

Wydajność jest kluczowa, ale nie można zapominać o tym jak dobrze ma to działać. Musiałem sporo popracować nad scenami, a także nad oknami UI, aby nie tylko wydajność była właściwa, ale także aby to działało. Wpadłem na ciekawy pomysł - Bootstrap - źródło, które znacząco pomoże w inicjalizacji obiektów, a także łącznik między nimi. Separacja odpowiedziałności jest kluczowa, dlatego łącznik będzie miał sporo do roboty, tak jak ja oddzielając warstwe logiczną od wizualnej. Samo rozdzielenie tego sprawiło, że kod stał się nie tylko mniejszy ale także czytelniejszy. Wiadomo teraz kto z kim na co i po co. Kolejną robotą nawego bohatera separacji jest inicjalizacja obiektów, a dokładnie pilnowanie tej kolejności. Do tej pory musiałem bardzo ostrożnie działać z elementami UI, ponieważ bardzo łatwo było o problem z kolejnością łądowania. Dane dla UI były gotowe, tylko, że UI nie było gotowe. To w zasadzie było główną siłą napędową potrzeby refaktoryzacji i separacji. Bootstrap przyjmując wszystkie komponenty kolejno je uruchamia (po upewnieniu się, że są wyłączone). Nie które wymagają specjalnego traktowania - UI, przy UI musiałem mieć 100% pewności, że jest załadowane więc z pomocą przyszły magiczne sztuczki - async i Task. To właśnie dzięki nim było możliwe wymuszenie "cierpliwego" oczekiwania na pełne załadowanie się interfejsu. To oczekiwanie dało mi pewien pomysł - ekran wczytywania. Ogólnie ładowanie się sceny to była nie cała sekunda oczekiwania. Praktycznie nie widoczna różnica, ale dodanie ekranu ładowania pokazało jak bardzo byłem w błędzie. Proczes ładowania zaczyna się od wybrania (zatwierdzenia wyboru) postaci, aż do pełnego załadowania komponentów przez Bootstraper. Kiedy wszystko załaduje, ostanie co robi to likwiduje ekran ładowania ujawniając scenę. Sam proces ostatecznie pokazuje, że scena sama w sobie łaaduje się o wiele dłużej. Ale dzięki temu gracz ma gwarancję, że "wchodzi na gotowe". Przed wprowadzeniem ekranu ładowania, gracz mógł zacząć rozgrywkę momentalnie po zobaczeniu postaci, ale były małe problemy - sporadyczne przycięcia. Dawało to jednoznacznie informację o tym, że coś tam się jeszcze doczytywało. Teraz, po zniknięciu procesu wczytywania i wejściu na scenę, gracz nie doświadczy już przycięć, tylko płynną rozgrywkę - wszystko co miało się załadować zostało załadowane przy wsparciu Bootstrapera, który dbał o to by się dod załadowało.

Postanowiłem też zminić mapę Areny - nie tylko jest mniejsza, ale także w pełni generowana losowo. Co prawda losowa jest tylko podłoga - no to zawsze coś. Arena ma stałe wymiary - 30x30. Nie pamiętam ile miała przed zmianą, bo była ona malowana ręcznie, także nie była nawet kwadratowa. Poprawie uległy także granice, które są dopasowane, a jak prędzej - robione na oko.

To tyle. Zmian sporo, można je zobaczyć w changelogu, a my widzimy się za tydzień.

Paski zdrowia

Mieliśmy UI dla wyboru postaci i dla broni, czas zabrać się za postacie w samej grze. Podczas rozgrywki gracz trafienie rozpoznać może tylko przez to, że zniknął przeciwnik. Nie wiedomo czy się trafiło czy może zasięg broni właśnie się skończył i efekt zniknął. Dlatego aby rozwiązać ten problem postanowiłem zaimplementować "pasek zdrowia". Jednak Unity nie dało mi żadnych złudzeń - nie będzie to takie proste. Pierwotny plan zakładał zastosowanie klasycznego slidera, którego drobna modyfikacja pozwoliłaby na bezproblemowe wyświetlanie stanu zdrowia danej postaci.

HP Bar
HP Bar postaci

Struktura wewnętrzna slidera to jawny koszmar. Zmiana jednego elementu dewastowała wizualnie resztę, ciężko było też ustalić co do czego. Skoro jeden plan runął było trzeba sięgnąć po plan "B" - własny pasek HP.

Własny pasek ma jedną istotną cechę - wiesz co w nim jest i wiesz jak tego użyć. Dlatego jego stworzenie było dziecinnie proste - dwa elementy, jeden jako "kontener", a drugi jako właściwy pasek. Następnym krokiem było już tylko zrobienie przyjemnego dla oka stylu. To też nie było jakimś wyzwaniem, ot czerwony kolor paska, ciemniejsze tło, aby było widać ubytek i gotowe. Ostatnim zadaniem było już tylko jego implementacja w kodzie. No i tu zaczęły się przysłowiowe wiosła. Okazało się, że UI nie chciało zbytnio współpracować z kodem - pasek był widoczny... ale go nie było - nie był on widoczny dla kodu. Osadzenie czegoś oczywistego w nieoczywistym miejscu. Przeciwnicy (bo to na nich był testowany ów pasek) nie są generowani normalnie, a co za tym idzie nie mogłem "nienormalnie" zaimplementować paska. Brzmi to zagmatwanie, ale skracając to można powiedzieć - metoda "Start" nie była stosowana. Tak się też złożyło, że to właśnie ta metoda była kluczem do rozwiązania problemów, osadzony tam kod UI paska pozwolił go nie tylko zobaczyć wizualnie, ale także ze strony kodu. Następnie wprowadziłem kilka poprawek, aby pasek nie był zbyt długi oraz nieco zwiększyłem jego szerokość.
Nie można także zapomnieć o tym, że gracz również otrzymał pasek zdrowia, dzięki czemu gracz będzie widział czy może sobie pozwolić na jakieś błędy, czy pozostaje mu już tylko bezbłędna rozgrywka.

HP Bar postaci 2
HP Bar postaci 3

Tym o to akcentem kończę na dziś i do zobaczenia już za tydzień.

Jeszcze lepsze UI

Wygląd "Wyboru postaci" został zdecydowanie poprawiony. Jednak nie tylko na samych postaciach bazuje ta scena. Broń. Broń ma równie wielkie znaczenie co sama postać.
Do tej pory gracz miał możliwość wyboru broni na podstawie ikonki, która pojawiała się po wybraniu danej postaci. To było zdecydowanie za mało. Brak informacji o tym co to za broń (obrazek broni sporo mówił, ale dalej za mało), jakie ma parametry i ulepszenia. Jedynie co można było zrobić to zwyczajnie wybrać broń A lub broń B.
Pierwszy plan zakładał tooltip wyświetlany po najechaniu na ikonę danej broni, ale ze względu na ilość dostępnych (i planowanych) atrybutów - byłoby to nieczytelne. Dlatego planem awaryjnym była rozbudowana dawka informacji o broni, która swoje miejsce miała mieć między ikoną broni, a przyciskiem zatwierdzającym wybory. Jednak poprawa (a co za tym idzie powiększenie) kart postaci sprawiło, że ten plan równiesz poleciał do kosza. Na papierze wyglądało wszystko ładnie, ale końcowe szlify pokazały wady w innych miejscach.
Brak miejsca na to by pokazać broń wymusił stworzenie dedykowanego okna dla wyboru broni. W poprzednim devlogu wspominałem o dodaniu przycisku "wybierz broń". Nie będzie go. Zamiast dawać przycisk postanowiłem pokazać najważniejsze informacje o broni. Gracz może klikną ikonę broni, co pozwoli mu otworzyć okno, w którym będzie miał możliwość zobaczyć wszystkie dostępne bronie dla danej postaci, poznać dokładne parametry danej broni, a także stopień biegłości w danej broni.


Biegłość w broni

Całkowicie nowa funkcja, która miała być dodana później, ale z powodu zmiany wyglądu procesu wyboru postaci uznałem, że warto to wprowadzić prędzej. Pozwoli ona graczowi zwiększyć możliwości bojowe danej broni. Każda broń będzie miała cztery etapy biegłość, a każdy z nich będzie wymagał zabicia określonej ilości przeciwników. Im lepszy tier broni, tym większe będą wymagania. Bigłość będzie na stałe zwiększać konkretne atrybuty broni.

Opracowywana jest także metoda obliczania BR dla broni.


Battle Rank

Broń ma otrzymać swoje BR, ale i postacie (w tym wrogowie) muszą mieć je poprawione. Obecny sposób obliczania BR jest bardzo uogólniony, co może prowadzić do pewnych komplikacji. BR gracza jest obliczane inaczej niż BR przeciwników, mimo, że działa na podobnej zasadzie. Zmiany będą dotyczyć nie tylko potencjałów (jak ma to miejsce obecnie), ale atrybutów. Gracza potencjał był obliczany kompletnie (wszystkie 5), zaś u wrogów tylko 3 (S, C i D), głównie za sprawą, że P i W nie miały dla przeciwników zastosowania. W końcu wrogowi nie potrzeba percepcji, jeśli ten zawsze idzie do gracza, ani nie potrzeba wiedzy, bo nie ma ona w niczym zastosowania. Muszę znaleźć jakiś lepszy sposób przeliczania BR, aby przeciwnicy byli odpowiednio dobierani na arenach, a gracz odpowiednio był nagradzany doświadczeniem.

Na dziś to tyle, widzimy się za tydzień.

Lepsze UI

Przynajmniej chciałbym aby było można je nazwać lepszym. Wybór postaci to też doświadczenie gry, dlatego chciałem zrobić coś co będzie wyglądało miło dla oka. Tak właśnie powtało nowe UI dla wyporu postaci.
Stare UI nie powalało wyglądem, ale było w nim coś co wymagało poprawek i to nie wizulanych - kod. Kod był straszny. Miał on coś w sobie, gdyż całość była generowana, ale ciężko projektować CSS dla czegoś czego nie widać.

Nowe UI
Kod UI

Plan był następujący - zamiast bawić się w tworzenie sztucznych obiektów by na nich testować CSS - zrobić prefab UI i go kopiować. No nic lepszego spotkać mnie już nie mogło jeśli chodzi o plan z UI.
Kolejną przeszkodą do stworzenia dobrego UI było to jak i ile pokazać ze stratystyk wyświetlanej postaci. Stara wersja pokazywała tylko atrybuty, a do tego czytelność była... no była średnia.

Kod UI

Skoro sama karta postaci została znacząco powiększona (z 300 na 400 px) to może warto byłoby też dodać więcej informacji o danej postaci. Postać jest określana nie tylko przez atrybuty, ale też przez potencjały. Liczba potencjałów jest stała - 5, a liczba atrybutów stoi jeszcze pod znakiem zapytania. Jednak zdecydowałem się na `sztywne` ulokowanie w kodzie UI zarówno potencjałów jak i atrybutów. Jeżeli kiedyś przyjdzie mi dodać jeszcze jakieś atrybuty to i tak bym musiał poprawić UI pod to, więc ostatecznie decyzja ta wydaje się być jak najbardziej słuszna i rozsądna. Odpada mi w ten sposób część kodu, a to plus - czytelniejsze klasy i metody.

Kod UI

Samo zwiększenie czytelności nie wystarczyło. Pobawiłem się trochę na testowych obiektach i udało mi się uzyskać ciekawy efekt. O nim będzie przy okazji omówienia "nowych szat króla". W skrócie efekt nie jest jeszcze wybitny, ale daje sporo możliwości w przyszłości, gdy przyjdzie robić już bardziej precyzyjną grafikę dla gry.

Wracając do czytelności - udało się uzyskać wszystkie oczekiwane rezultaty. Gracz od tej pory będzie widział zarówno potencjały danej postaci, jak i jej atrybuty. I to wszystko z jeszcze mniejszą liczbą kodu, niż miało to miejsce poprzednio.



Nowe szaty króla

Może i żadna z grywalnych postaci nie jest królem, ale zostały one znacząco odświerzone. Poprzednie były wyciągnięte z odmętów innych projektów, przez co średnio pasowały (były ładne, ale tylko tyle). Teraz postacie przypominają wojowników (temtyka zbliżona do średniowiecza), nie są piękni, bo na śmierć raczej miss lub mister piękności nie pójdzie. Jednak na wyglądzie samych potretów się to nie kończy. Poprzedenie portrety jak i sprite'y postaci były... powiedzmy, że były "takie se", teraz mają zbliżone wyglądy do siebie. Widzisz na portrecie typa w hełmie i z brodą, to sprite też będzie miał typa z brodą i w hełmie. Nie jest to 1:1, ale z odległości nie widać aż takich różnic.

Kod UI
Kod UI

Do tego wszystkiego nakładamy dowolne tło i można szaleć z kontekstem. No przynajmniej tak sobie to wyobrażam, rzeczywistość zweryfikuje. Bawiąc się jeszcze obramowaniem UI może uda się uzyskać jeszcze jakiś ciekawszy efekt.

Pozostaje teraz już tylko kwestia broni. Wyboru broni. Tutaj będzie ciekawiej - bo trudniej. Mało miejsca z powodu większych kart postaci, a same bronie również mają atrybuty. Do tego inne niż te, które ma gracz. Do tej pory gracz dostawał ikonkę broni i to musiało mu wystarczyć, brak wiedzy o jej parametrach mógłby mieć negatywny wpływ na odbiór gry. Dlatego też wpładłem na ciekawszy pomysł - jeśli brakuje mi miejsca - to muszę je sobie zrobić. Na całe szczęscie nie będzie to wymagało przebudowy UI na scenie, czy przeniesienia kard postaci. Po wyborze postaci, ta otrzyma swoją domyślną broń (w planach jest aby była to ostatnio użyta) a pod jej portretem (postaci) pojawi się przycisk "Wybierz broń". Jego zadaniem będzie aktywacja okienka z wyborem broni. W tym okienku gracz będzie miał wszystkie odblokowane dla danej postaci bronie, oraz będzie mógł w końcu zobaczyć czym różnią się bronie.

Do zobaczenia za tydzień!