Poradnik Unity. Co musicie wiedzieć o tym silniku, żeby stworzyć własną grę? [OZDGD #2]

W poprzednim artykule rozpoczęliśmy przygodę z tworzeniem gier, stawiając repozytorium oraz poznając tajniki systemu kontroli wersji. To podstawa przed rozpoczęciem procesu tworzenia gry, którego opisałem tutaj. Zanim sami zaczniemy tworzyć swoją unikalną produkcję (zdradzę już, że będzie to platformówka 2D z dużym potencjałem rozwoju, czyli wcale nie taka najprostsza gra) nadal nie będziemy wchodzić w jej szczegóły, bo najpierw musimy poznać, co do zaoferowania ma sam silnik Unity. 
Poradnik Unity. Co musicie wiedzieć o tym silniku, żeby stworzyć własną grę? [OZDGD #2]

Gra platformowa 2D w Unity Od Zera do Game-Developera [OZDGD]

W ramach serii Od Zera do Game-Developera, w której to chcę zachęcić innych do zainteresowania się nie tylko grami, ale też sferą ich produkcji, powstały już następujące teksty:

Niniejszy tekst jest kontynuacją serii, w ramach to której tworzę pełnoprawną, ale prostą platformową grę 2D:

Czym jest Unity i jakie są alternatywy?

Unity jest aktualnie jednym z dwóch najpopularniejszych darmowych silników gier, który według wielu konkuruje m.in. z Unreal Engine firmy Epic Games. Osobiście jednak uważam, że są to dwa zupełnie odmienne narzędzia przeznaczone dla różnych projektów i różnych deweloperów. Tak jak Unity sprawdza się świetnie w mniejszych projektach zwłaszcza gier 2D i mobilnych, wymagając od programistów nauki języka C#, tak Unreal Engine (UE) to istny kombajn do projektów 3D z rozbudowanymi scenami i zaawansowaną grafiką, w którym tworzy się w języku C++, czyli tym znacznie trudniejszym.

Można nawet pokusić się o stwierdzenie, że rozwój gry na Unity nie będzie tak skomplikowany i tym samym drogi, jak na Unreal Engine, ale z drugiej strony taka produkcja nie będzie tak graficznie dopieszczona i rozbudowana, jak na Unrealu właśnie. Oczywiście biorąc pod uwagę ten sam projekt wykonany na obu silnikach. Dlatego właśnie Unity jest tak popularne wśród początkujących i mniejszych studiów gier, co odzwierciedlają nie tylko statystyki, ale też oferty pracy na m.in. Skillshot. 

Przypomnę tylko, że na Unity powstały takie produkcje jak Hearthstone, Cities: Skylines czy fenomenalnie wyglądające Ori and Blind Forest, podczas gdy Unreal Engine był podstawą dla Bioshocka, Gears of War i będzie dla nowych odsłon serii Wiedźmin od CD Projekt Red. To jednak oczywiście nie tak, że na Unity nie może powstać produkcja AAA, czyli taka bardzo rozbudowana. Może, ale fakt, że nigdy taka nie powstała, mówi sam za siebie. 

Jest to głównie spowodowane tym, że współpraca deweloperów nad jedną sceną w Unity, to katorga, co na Unreal Engine nie jest aż tak dużym problemem. Nie działa to jednak w drugą stronę i na UE mogą powstawać zarówno wielkie gry AAA, jak i te mniejsze, czego przykładem może być np. Astroneer. Dlaczego więc sam wybrałem Unity, choć Unreal Engine wydaje się lepszy? Głównie dlatego, że dla początkujących Unity jest mniej wymagające, ale z drugiej strony nawet na Unity gry mogą wyglądać ładnie.

Jako że przed dwoma laty chciałem skończyć swoją grę tylko po to, żeby aspirować na pozycję game- i narrative-designera, wiedząc co nieco na temat tego, jak zachodzi cały proces łączenia mechanik i narracji w grach, Unity było jedynym sensownym wyborem. Zwłaszcza że zwyczajnie łatwiej jest znaleźć pracę w mniejszym studiu pracującym na tym silniku, niż w tych dużych z programistami wyspecjalizowanymi w Unreal Engine. To jednak temat na inny czas, więc przejdźmy już do tego, co jest najważniejsze, a więc tego, jak korzystać z Unity.

Układ okienek w Unity to płynna, ale ważna kwestia

Po tym, jak założyliśmy już nowy projekt i wiemy, jak mniej więcej działa Unity Hub (od tej pory służy nam głównie do włączania projektu i ewentualnie instalowania do niego nowych dodatków), nadszedł czas na zapoznanie się z jego interfejsem. 

Ten może z początku przestraszyć, bo składa się z masy okienek, menu i przycisków, ale spokojnie. Z każdą kolejną godziną spędzoną na silniku będziecie nabierać wprawy w tym, co i gdzie się znajduje. Zwłaszcza że w gruncie rzeczy na samym początku powinny interesować was cztery główne okienka, z czego dwa posiadają dodatkowe zakładki (Scene/Game i Project/Console). Chociaż domyślny układ ma w ogólnym rozrachunku sens, to lepiej ulepszyć go nieco, żeby ułatwić sobie pracę, dzięki pełnej modułowości, którą na szczęście Unity zapewnia.

Czytaj też: Game Boy na miarę 2023 roku. Ta retrokonsolka przywróciła mi radość z grania

Zalecam więc dodać do prawej kolumny dodatkowe okienko Inspector, czego proces zapoczątkujecie klikając prawym na zakładkę tego domyślnego. Następnie przejdźcie przez menu tak, jak na zrzucie ekranu poniżej i po kliknięciu Add Tab>Inspector doczekacie się drugiego tego samego okienka. Warto od razu przenieść je w niższą część tej samej kolumny i pamiętać o kłódce z prawej strony, która to pozwala Wam blokować podgląd na dany element bez względu na dalsze poczynania. 

Jest to cenniejsze niż z początku może się wydawać, ale nie przywiązujcie się do takiego układu, bo w toku produkcji rozstawienie poszczególnych okienek zmienia się bardzo często. Przykładowo możecie też pójść za moim śladem i rozdzielić okienko konsoli i Game/Scene w podobny sposób, ale to już kwestia wyłącznie osobistych preferencji.

Tak oto macie dostęp do sześciu kompletnie różnych okienek, które są podstawą pracy w Unity. Cztery z nich będziecie wykorzystywać podczas tworzenia, a dwa pozostałe podczas testowania.

Unity Project niczym rozbudowany eksplorator plików

Menu projektu (Project) to tak naprawę wbudowany w Unity eksplorator plików, które składają się na projekt. Do nieinteresującego was folderu Packages trafiają foldery z paczkami funkcji, które dostarcza zwykle bezpośrednio silnik, podczas gdy w folderze Assets powinny (wedle prawideł dobrej dystrybucji plików) znajdować się głównie te foldery, w których znajdują się modyfikowane przez was pliki. 

Na tę chwilę znajduje się tam wyłącznie folder z jedną (domyślną) sceną, ale w toku rozwoju projektu znajdzie się ich tam znacznie więcej. W praktyce sposób rozłożenia plików i folderów nie wpływa na samą grę, ale na proces produkcji już tak, więc dobrze jest dbać o ich odpowiednie rozstawienie (więcej na ten temat opowiem w kolejnym artykule z tej serii), żeby nie tylko pracować wydajniej, ale też pokazać potencjalnemu pracodawcy, że nie jesteście bałaganiarzami, jeśli udostępnicie projekt osobom trzecim. To coś małego, ale jak wiadomo, szczegóły tego typu budują nasz wizerunek.

Klikając prawym przyciskiem na jakiś plik, folder, czy po prostu puste pole, dostajemy dostęp do menu kontekstowego, w którym interesują nas zwłaszcza dwie zaznaczone w czerwonej ramce opcje. Ta druga z kolei uruchomi nam w tle edytor skryptów ustalony w ustawieniach projektu (w domyśle to Visual Studio), a pierwsza zapewni dostęp do wszystkiego, co możemy dodać do projektu po stronie plików, którym zawsze towarzyszy jakiś plik z rozszerzeniem .meta, czyli obejmujący nieinteresujące nas metadane. W gruncie rzeczy na tę chwilę obchodzi nas głównie tworzenie folderów, scen oraz skryptów C#, a z czasem do tego duetu dojdą kolejne elementy. 

Unity Scene, Hierarchy oraz Inspector, czyli trzy główne narzędzia tworzenia gry

Znacznie większą rolę przy procesie tworzenia odgrywa zarówno umieszczona z lewej hierarchia (Hierarchy), jak i scena (Scene). W tej pierwszej strukturze, w której to panuje hierarchia odwróconego drzewa (elementy ustawione niżej są jednocześnie wyżej w hierarchii i tym samym “nachodzą” na te znajdujące się wyżej), znajduje się wszystko, co buduje daną grę. Każdy z elementów określa się mianem “GameObject”, czyli w tłumaczeniu “obiektu gry”, którego możemy dowolnie nazywać i ustawiać za pomocą zarówno sceny, jak i inspektora (oraz skryptów, ale to już historia na inną okazję). 

Tworząc pusty GameObject, ten pojawi się na scenie, a wybierając go, zobaczymy zmianę w panelu inspektora. Pojawią się tam bowiem związane z nim ustawienia, które w pierwszej sekcji (ponad komponentem Transform) dotyczą jego wizualnej formy, aktywności (ptaszek po lewej od nazwy określa to, czy jest aktywny), pozycji w grze (ten po prawej określa, czy ma być za wszelką cenę statyczny w świecie) oraz grupowej przynależności w formie konkretnego tagu czy warstwy, które możemy dowolnie ustawiać, aby uzyskać sposób na odwoływanie się do danych obiektów w masowy sposób. 

Poniżej tych podstawowych ustawień znalazł się jedyny na tę chwile komponent (Transform), który odpowiada za ustawienie obiektu w świecie gry. Określa zarówno pozycję, jak i jego obrót (rotację) oraz skalę w układzie kartezjańskim, czyli na osi X, Y oraz Z. Jest to jednak tylko podstawa, bo chcąc rozszerzyć możliwości danego GameObjectu i zrobić z niego np. postać gracza, przeciwnika lub część środowiska, należy dobrać do niego odpowiednie inne komponenty. Wśród tych najczęstszych znajduje się zdecydowanie komponent ze skryptem napisanym w języku C#, który nadaje obiektowi pożądaną przez nas logikę.

Na całe szczęście nie musimy pamiętać większości komponentów na własną rękę, bo jak możecie zobaczyć na zestawieniu poniżej, różne stworzone elementy w hierarchii mają już podstawowe komponenty potrzebne do działania. Całkowicie zieloni i tak muszą jednak wziąć się za lekturę dokumentacji Unity, żeby wiedzieć, za co odpowiadają poszczególne komponenty i jak osiągnąć coś z wykorzystaniem tych bardziej niestandardowych. 

Można więc powiedzieć, że inspektor, którego dublowaliśmy, to swoisty łącznik między nami, a poszczególnymi obiektami zarówno w hierarchii (i scenie), jak i w projekcie. Jako swoiste menu “właściwości”, zapewnia podgląd na większość opisujących dany obiekt cech, czyli wspomnianych komponentów i odświeża się za każdym razem, kiedy klikniecie w inny GameObject lub plik. Aby dezaktywować to zachowanie, musicie kliknąć w kłódeczkę w prawym górnym rogu inspektora, która to zablokuje podgląd aktualnie zaznaczonego obiektu.

Unity Game i Console, czyli testowania czas

Proces produkcji gry obejmuje wykorzystywanie przede wszystkim trzech wspomnianych wcześniej okien, z czego menu sceny zapewnia już namiastkę wglądu w to, jak będzie wyglądać gra po jej włączeniu. Zapewnia ciągle dostęp do kamery, którą możemy dowolnie przemieszczać się po wirtualnym świecie i ustawiać bezpośrednio na niej konkretne elementy, wykorzystując narzędzia w lewym górnym rogu, które odpowiadają za (kolejno) przemieszczanie kamery, przemieszczanie obiektu, obracanie obiektu, skalowanie go, a wreszcie bardziej skomplikowane manipulowanie jego wielkością i pozycją. W praktyce interesują nas głównie trzy pierwsze funkcje:

Czytaj też: Spędziłem 2 lata z Xbox Series X. Czy nadal warto go kupić?

Jak jednak wreszcie włączyć grę i podejrzeć, jak “działa”? Odpowiedź na to pytanie przynosi umiejscowiony na środku górnej belki zestaw trzech przycisków, wśród których ten po lewej odpowiada za włączenie i wyłączenie gry z poziomu silnika, a ten środkowy za wstrzymywanie/wznawianie jej działania. Dopiero po uruchomieniu gry (to rzeczywiście forma jej włączenia z pliku .exe, ale akurat w środowisku Unity) możemy podejrzeć to, jak działa w praktyce, co pokaże nam okienko Game, podczas gdy w konsoli (Console) mogą pojawić się jakiekolwiek informacje (głównie błędy, ale też ustawione w kodzie informacje za pomocą komend Debug.Log, Debug.LogWarning lub Debug.LogError). 

Będąc w tym trybie, możemy zmieniać ustawienia poszczególnych GameObjectów, ale wszystkie zmiany zostaną zresetowane po wyłączeniu gry. Lepiej też nie modyfikować wtedy skryptów, jeśli nie macie wyłączonego automatycznego zapisywania zmian, bo inaczej Unity odświeży się, a gra “popsuje”, wymagając od was przeprowadzenia restartu. A jeśli już przy skryptach jesteśmy… czas zrobić pierwszy z nich.

Pierwszy prosty program w Unity

Jak powiedzieć obiektowi Unity, że ma coś zrobić? Odpowiedź na to pytanie przynoszą skrypty, które tworzymy poprzez np. wciśnięcie prawym przyciskiem myszy na okienko z plikami w projekcie, a następnie Create oraz C# Script. Tak oto możecie utworzyć swój pierwszy skrypt w Unity, którego nazwałem mianem TestScript:

Teraz musicie uruchomić go, klikając dwa razy bezpośrednio w niego, aby włączył się wasz edytor skryptów, czyli najpewniej Visual Studio:

W tym edytorze powinna was szczególnie zainteresować nie tylko sekcja z kodem, ale też z plikami w projekcie (menu Solution Explorer). Guzik “Attach to Unity”, to z kolei opcja odpalenia skryptów w specjalnym trybie debugowania, który to pozwala nam zweryfikować to, jak działają nasze skrypty “linijka po linijce i instrukcja po instrukcji” lub określić konkretną lokację interesującej nas metody, wskazując ją tą wielką czerwoną “kropką”:

Na temat programowania opowiem znacznie więcej w następnych artykułach, bo dziś interesuje nas tylko fragment “void Start()” z parą klamerek poniżej. To metoda uruchamiana na samym początku włączenia danej sceny, którą możemy wykorzystać np. do zmuszenia konsoli, aby coś nam napisała. 

Po dodaniu tych trzech linijek, musimy wrócić do Unity, poczekać, aż się odświeży i wreszcie przeciągnąć nowy skrypt bezpośrednio na GameObject MainCamera, czyli nasz jedyny obiekt na scenie:

Teraz wystarczy uruchomić grę i voila, w konsoli pojawią się trzy zaprogramowane wcześniej linijki:

Czytaj też: Wszyscy mówili: nie idź do gamedevu. Nie posłuchałem i dziś mogę się pochwalić pierwszą grą

Robiąc to, poznaliśmy tak naprawdę podstawy tego, jak działa Unity i jak możemy zmusić obiekty na scenie, żeby coś robiły. Tym razem to proste logi, ale nic nie stoi na przeszkodzie, żeby zmusić np. Main Camera do robienia tego, co chcemy aktualnie osiągnąć. Przykładowo poruszanie jej, można osiągnąć poprzez manipulowanie komponentem (Transform), a żeby wszystko trzymało się kupy, powinniśmy powiązać ten ruch np. ze strzałkami klawiatury. Brzmi prosto? No… w tym jest już więcej zabawy, ale spokojnie – w następnej odsłonie artykułu w tej części serii Od Zera Do Game-Developera postaram się to rozjaśnić.