Lekcja 1: Nasza pierwsza gra

Tworzenie gier jest proste, kiedy się to już potrafi. Nauczenie się tej sztuki, też może być przyjemne, potrzeba tylko odpowiedniego kursu. Właśnie na niego trafiłeś. Już na tej lekcji zrobisz swoją pierwszą grę. Nie ma na co czekać, zaczynajmy!


Instalacja

Nasze gry będziemy tworzyli przy użyciu silnika Unity 3D. Jest to specjalny program, który ułatwia tworzenie gier. Dlaczego warto korzystać z Unity? Ponieważ posiada on niezliczoną ilość funkcji, których zrobienie samemu zajęłoby ci 30 lat, a i tak nie zrobiłbyś tego tak dobrze jak robi to Unity. Setki ludzi pracują nad tym, żebyś ty mógł robić gry szybciej i lepiej. A na dodatek wszystko dostajesz za darmo (płacisz dopiero kiedy zarobisz na swojej grze ponad 700 000 złotych).

Aby rozpocząć naszą przygodę, musimy ściągnąć Unity. Wejdź na stronę https://store.unity.com/ i ściągnij wersję Personal Free. Nie będę opisywał tutaj dokładnej procedury instalacji, jako przyszły twórca gier, musisz sobie samodzielnie radzić z rzeczami takimi jak instalacja programu. Potraktuj to jako pierwsze wyzwanie w twojej drodze do zostania twórcą gier.

Wskazówka: w trakcie instalacji będziesz musiał wybrać systemy na jakie chcesz tworzyć gry. Unity wspiera wiele platform, w tym również konsole do gier. Na początek wystarczy jeśli wybierzesz system Windows, pozostałe opcje możesz doinstalować później.

Pierwsze uruchomienie

Kiedyś już masz wszystko zainstalowane i udało Ci się uruchomić Unity, program może poprosić cię o rejestrację darmowego konta. Gdy już się z tym uporasz, powinieneś na ekranie zobaczyć okno tworzenia nowego projektu. Jeśli go nie widzisz, z menu File wybierz New Project:


W polu Project Name wprowadź nazwę swojego projektu, na przykład: Moja pierwsza gra. W polu Location wybierz folder, w którym umieszczony zostanie nowy projekt. Po prawej stronie możesz wybrać czy gra, którą tworzysz będzie dwuwymiarowa czy trójwymiarowa. Nasza pierwsza gra będzie zawierała jedynie tekst, dlatego tym razem nie ma znaczenia co tu zaznaczysz. Pamiętaj również, że jest to tylko wstępny wybór i można go zmienić w trakcie prac nad projektem.

Nieco niżej widnieje jeszcze opcja Enable Unity Analytics, która pozwala włączyć statystyki dla tworzonej gry. Naszych lekcji nie będziemy nikomu udostępniali, można więc spokojnie tę opcję wyłączyć i kliknąć przycisk Create Project.

Właśnie utworzyliśmy nasz pierwszy projekt w Unity. Na ekranie widzimy teraz okno programu.


Wiem, że nie masz pojęcia co do czego służy, ale spokojnie. Wszystko wyjaśnimy w tej i kolejnych lekcjach. Na początek skieruj swoją uwagę, na panel Hierarchy widoczny po lewej stronie. Na liście znajduje się jedna opcja o nazwie Untitled. Co to takiego? Jak zapewne wiesz, gry często podzielone są na etapy. Podobnie Unity umożliwia podział gry na części, które nazywają się tu scenami. Do każdej sceny możesz dodawać obiekty i układać z nich etap w swojej grze.

Póki co mamy jedną scenę, która nie jest nigdzie zapisana. Przydałoby się ją zapisać. Z menu File wybierz Save Scenes. Wprowadź nazwę pliku np. Etap1, katalogu nie zmieniaj, niech plik zapisze się w folderze Assets. Folder ten jest częścią naszego projektu i zawierał będzie wszystkie pliki, jakich użyjemy w naszej grze (modele, tekstury, dźwięki, skrypty).

Wszystkie assety (czyli zasoby naszego projektu), widzimy w panelu Project, umieszczonym w dolnej części okna Unity. W tej chwili widnieje tutaj tylko nasza scena. Wróćmy do panelu Hierarchy po lewej stronie i rozwińmy zawartość sceny, klikając w czarny trójkąt po lewej stronie jej nazwy.


Na liście widnieją dwie pozycje. Main Camera to kamera, przez którą widziane są wszystkie obiekty wchodzące w skład naszej sceny. Directional Light to światło, które oświetla naszą scenę. W przyszłości dodamy tutaj o wiele więcej obiektów. Zostawmy na chwilę ten panel, wrócimy jeszcze do niego. Teraz skierujmy się ponownie do okna projektu na dole programu.


Obok nagłówka Project, znajduje się tajemniczy napis Console. Kliknijmy w niego (jeżeli nie widzisz tego napisu, to z menu Window wybierz opcję Console). Widok zmienił się, teraz na ekranie widzimy tak zwaną konsolę. Póki co jest tu tylko pustka, ale to właśnie tutaj program Unity będzie informował nas o błędach jakie popełnimy w trakcie prac nad projektem. Możemy również sami wyświetlić dowolny napis w oknie konsoli i właśnie ten fakt wykorzystamy tworząc naszą pierwszą grę.

Zapamiętaj, że konsola jest widoczna tylko w programie Unity, nie będziesz mógł zapisać stworzonej tu gry do formatu aplikacji i pochwalić się nią kolegom, chyba, że ściągną edytor Unity. Nie martw się, nasze kolejne gry będą już działały normalnie i będziesz mógł podzielić się nimi z kim tylko zechcesz

Za chwilę stworzymy naszą pierwszą grę! Aby tego dokonać, wykorzystamy skrypt napisany w języku programowanie C# (zwanym też C Sharp). Skrypty to nic innego jak lista poleceń, jakie wydajemy komputerowi. My rozkażemy mu, żeby wyświetlił w konsoli napis.

Aby utworzyć skrypt, wróć do panelu Project, kliknij przycisk Create i z menu wybierz C# Script.


W oknie projektu pojawił się nowy plik. Zmień jego nazwę na Napis. Zmiana nazwy pliku w edytorze Unity wygląda tak samo jak zmiana nazw plików w systemie Windows, można na przykład kliknąć na nazwę, która się podświetli lub nacisnąć przycisk F2.

Nasz pierwszy skrypt

Aby było ci łatwiej korzystać z niniejszego kursu, powinieneś upewnić się, że masz taki sam edytor skryptów jak ja.

Zrób tak: kliknij w menu Edit na górze edytora Unity, a następnie wybierz opcję Preferences. Twoim oczom ukaże się okno, w którym po lewej stronie zaznacz opcję External Tools:


Zmień opcję External Script Editor na MonoDevelop (built-in) i zamknij okno preferencji. Gotowe.

Wracamy do prac nad naszym pierwszym skryptem. Klikamy dwukrotnie na ikonę naszego skryptu. Otworzy się edytor. Naszym oczom ukaże się taki oto widok:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour {

  // Use this for initialization
  void Start () {
  }
  // Update is called once per frame
  void Update () {
  }
}

Bez paniki, zaraz wyjaśnimy co to takiego. Wygląda skomplikowanie, ale nie ma się czego bać, już niedługo będzie to dla ciebie coś zupełnie normalnego i naturalnego.

Zacznijmy od początku. System.Collections to nazwa pewnego zbioru poleceń (funkcji), które możemy wykorzystać. Dzięki temu, że na początku naszego skryptu napiszemy using System.Collections, będziemy mogli wykorzystywać wszystkie polecenia z tego zbioru. Gdybyśmy tego nie zrobili, byłyby one dalej dla nas dostępne, ale każde z nich, należałoby poprzedzić tym długim ciągiem znaków "System.Collections". Generalnie więc słowa using używamy dla często używanych zbiorów poleceń, po to, aby później ułatwić sobie pisanie reszty skryptu.

Średnik na końcu linijki oznacza, że w tym momencie kończy się dana instrukcja. Średniki będziemy stosowali na końcu większości instrukcji, więc zdążysz się z nimi oswoić.

Wskazówka: brak średnika na końcu jest częstym błędem, nie tylko wśród początkujących programistów. Na szczęście jest bardzo łatwy do naprawy - wystarczy dopisać średnik.

Następnie mamy public class NewBehaviourScript : MonoBehaviour {. Ta linijka tworzy nam nowy zbiór poleceń o nazwie NewBehaviourScript. Sami będziemy musieli stworzyć polecenia w nim zawarte. Możemy jednak zdecydować, aby część poleceń została odziedziczona z innego zbioru, wtedy należy jego nazwę podać po dwukropku i tak jest też w naszym kodzie : MonoBehaviour. MonoBehaviour to najczęściej używany zbiór poleceń w silniku Unity. Tego co dokładnie oznaczają słowa public i class, dowiesz się z kolejnych lekcji.

Znak { na końcu linijki oznacza, że w tym miejscu zaczyna się część naszego zbioru poleceń, w którym będziemy umieszczali jego zawartość. Znak klamry zamykającej }, widoczny na samym dole, zamyka zawartość zbioru. Wszystkie nasze polecenia, muszą być umieszczone właśnie pomiędzy tymi znakami, dzięki temu komputer wie, gdzie szukać poleceń należących do stworzonego zbioru.

Generalnie bardzo dobrym pomysłem jest nazwanie naszego zbioru w taki sam sposób, w jaki nazwaliśmy nasz plik. Jeżeli po dwukropku występuje MonoBehaviour, to jest to wręcz konieczność. Dlatego powinniśmy teraz zmienić nazwę naszego zbioru na Napis, czyli tak jak nazywa się plik ze skryptem. Nie róbmy jednak tego, przejdźmy dalej, a za chwilę do tego wrócimy. Dzięki temu, nauczysz się czegoś przydatnego, ale o tym za chwilę.

Kolejna linijka to // Use this for initialization. Jest to nic innego jak komentarz. Nie ma on wpływu na działanie programu, jest przeznaczony tylko i wyłącznie dla programisty, możesz tutaj napisać cokolwiek. Każdy komentarz zaczyna się od znaków //. Wszystko od tych dwóch znaków, aż do końca linijki jest ignorowane przez komputer. Można tutaj oczywiście pisać po polsku i używać polskich znaków.

Istnieje również drugi rodzaj komentarza. Jeżeli potrzebujemy napisać wiele linijek, to zamiast poprzedzać każdą z nich znakami //, możemy zrobić to w taki sposób:

/* To jest komentarz.
Ma on kilka linijek.
A to już jego koniec */

Komentarze przydają się do opisywania fragmentów skryptu. Dzięki nim łatwiej zrozumieć do czego służy dana część kodu, kiedy czytamy ją po pewnym czasie i już wszystkiego nie pamiętamy. Generalnie im bardziej doświadczony programista, tym mniej komentarzy potrzebuje, jednak nawet ci najbardziej obeznani wciąż je wykorzystują. Jest to bardzo przydatna rzecz.

Następny wiersz w naszym skrypcie to void Start () {. Jest do deklaracja polecenia (funkcji) o nazwie Start. Naszym funkcjom możemy nadawać dowolne nazwy, jednak Start to nazwa polecenia, występującego w zbiorze poleceń MonoBehaviour, o którym wspomnieliśmy wyżej. Ponieważ nasz zbiór dziedziczy polecenia ze zbioru MonoBehaviour, dlatego dziedziczy również funkcję Start(). Nazywając nasze polecenie w taki sam sposób sprawiamy, że polecenie ze zbioru MonoBehaviour zostaje zasłonięte.

Start() jest specjalnym rodzajem polecenia, ponieważ jego zawartość zostaje uruchomiona przy każdym starcie naszej gry. Podobnie rzecz się ma z poleceniem Update(), jednak ono uruchamiane jest w każdej klatce. Jeżeli więc nasza gra działa w 60 klatkach na sekundę, to polecenie Start() zostanie wywołane tylko raz przy starcie gry, natomiast Update() będzie uruchamiany 60 razy na sekundę.

Nawiasy po nazwie polecenia są konieczne, ponieważ niektóre polecenia zawierają parametry, podawane właśnie w nawiasach. Wyjaśnimy to dokładnie niebawem, dowiesz się także co znaczy słowo void.

Póki co skupmy się na znaku {, widocznym po nawiasach. Jest to znak klamry otwierającej. Każde polecenie (funkcja) składa się z nagłówka np. void Start() oraz treści. Treść to instrukcje, które ma wykonywać komputer po uruchomieniu danego polecenia. Instrukcje te umieszczamy pomiędzy znakami { i }. Zauważ, że niżej jest również klamra zamykająca. Obecnie nasze polecenia nie zawierają żadnych instrukcji, niedługo je napiszemy.

Przeanalizowaliśmy zawartość utworzonego skryptu, powiem jeszcze kilka słów na temat tak zwanych pustych znaków. Są to znaki, których nie widać (spacja, znak tabulacji, znak końca wiersza). W niektórych miejscach konieczne jest wstawienie pustego znaku, tak jak na przykład pomiędzy słowami void i Start, gdybyśmy tego nie zrobili, komputer nie wiedziałby o co nam chodzi. Kiedy wstawiamy pusty znak, to niekonieczne musi być to jedna spacja. Możemy dać trzy spacje, pięć znaków tabulacji i znak końca wiersza. To jakie puste znaki i gdzie damy nie ma dla komputera znaczenia, ma jednak kolosalny wpływ na czytelność kodu dla ludzi, czyli w tym wypadku dla nas. Generalnie w programowaniu stosuje się wcięcia, które ułatwiają odczytywanie kodu. Dlatego linijka void Start() {, poprzedzona jest znakiem tabulacji. Warto jest przyjąć jeden sposób zapisu i się go trzymać. Ułatwia to pisanie kodu, jego czytanie oraz wyszukiwanie.

Wskazówka: wielkość liter ma znaczenie. Start() i start() to dwa różne polecenia. Należy o tym bezwzględnie pamiętać!

Jeżeli chodzi o zapis kodu, to programiści dzielą się na dwa rodzaje:
- ci którzy nie przenoszą klamry otwierającej do nowej linijki
- ci którzy ją przenoszą

Ja należę do drugiej grupy, dlatego w tym kursie programowania, będziemy stosowali taki zapis jak poniżej. Według mnie jest on bardziej czytelny, ale to kwestia indywidualna. Zapraszam do stosowanie tego samego zapisu, który ja stosuję:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
    }
}

Oprócz zmienionego układu klamer, powyższy kod różni się również brakiem spacji pomiędzy nazwą funkcji oraz nawiasami. Zdecyduj, który zapis jest dla Ciebie bardziej czytelny.

Tworzymy naszą pierwszą grę

Naszą pierwszą grę nazwiemy "Skoki żab". Będzie miała bardzo proste zasady. Gracz naciska przycisk, a jego żaba skacze. Gracz, którego żaba skoczy najdalej wygrywa.

Wróćmy do okna edytora Unity. Zmieńmy nazwę naszego skryptu Napis na SkokiZab (nie używamy polskich znaków, są one dozwolone tylko w komentarzach do kodu). Aby nasz skrypt zadziałał, musimy dodać go do sceny. Do sceny można jednak dodawać tylko obiekty, nie ma możliwości bezpośredniego dodania tam pliku ze skryptem. Jak zatem dodać skrypt do sceny? Należy dodać go do obiektu, a dopiero ten obiekt dodać do sceny. Możemy również dodać skrypt do obiektów, które już są na scenie.

My stworzymy nowy obiekt. W tym celu kierujemy kursor do panelu Hierarchy i wybieramy przycisk Create, na liście, która się pojawi klikamy Create Empty. W ten sposób stworzymy pusty obiekt, czyli taki, który nie jest widoczny na scenie i nie zawiera żadnych dodatkowych komponentów (w zasadzie to zawiera jeden, ale każdy obiekt musi go mieć, o tym porozmawiamy za chwilę). Komponentem nazywamy wszystko to, co można dodać do obiektu (wkrótce poznasz ich wiele).


W okienku Hierarchy powinien pojawić się trzeci obiekt, o nazwie GameObject:


Możemy zmienić jego nazwę na coś bardziej przyjaznego, jeśli chcesz to tak zrób. Nazwę zmieniamy zaznaczając obiekt, a później naciskając F2 lub klikając na nazwie.

Zaznaczmy nasz obiekt, a następnie zwróćmy naszą uwagę w kierunku panelu po prawej stronie, zatytułowanego Inspector. W panelu tym widoczne są wszystkie komponenty dodane aktualnie do zaznaczonego obiektu.



Jak widać znajduje się tam obecnie jeden komponent, o nazwie Transform. Jest to komponent, który pozwala ustawić pozycję obiektu na scenie, jego rotację oraz skalę (czyli jak wielki jest). Każdy obiekt posiada komponent Transform i nie można go usunąć. Również pusty obiekt posiada ten komponent.

Oprócz komponentu Transform, w inspektorze możemy również zmienić nazwę obiektu, a także odznaczyć ptaszek widoczny po lewej stronie nazwy, dezaktywując tym samym dany obiekt (stanie się on wtedy niewidoczny i jego komponenty przestaną działać, dlatego teraz tego nie róbmy). 

Pozostałe widoczne tutaj opcje wyjaśnimy w przyszłości, teraz skup się na przycisku Add Component. Umożliwia on dodanie kolejnych komponentów do obiektu. Kliknijmy w niego, a rozwinie się lista dostępnych komponentów.


Dostępna jest również wyszukiwarka. Spróbujmy wpisać w polu nazwę naszego pliku ze skryptem, czyli SkokiZab. Nie uda nam się go znaleźć na liście. Dlaczego?

Powód jest prosty, ale zanim ci go zdradzę, chciałbym, abyś spróbował dodać nasz skrypt do obiektu drugą metodą. Polega ona na przeciągnięciu skryptu z panelu Project na obiekt umieszczony na scenie w panelu Hierarchy. Gdy to zrobimy, naszym oczom ukaże się komunikat:


Wynika z tego, że nie możemy dodać naszego skryptu do obiektu, ponieważ nie zmieniliśmy nazwy naszego zbioru funkcji z NewBehaviourScript na taką, jaką ma plik ze skryptem, czyli SkokiZab. Kliknijmy na skrypt i zmieńmy nazwę teraz. Nasz skrypt powinien wyglądać tak:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SkokiZab : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
    }
}

Teraz z menu Build na górze edytora skryptu, wybierz opcję Build All. Jej wybranie spowoduje zapisanie naszego pliku ze skryptem, a także jego komplikację. Kompilacja to proces zamiany kodu pisanego przez nas, na język zrozumiały dla komputera. Jeśli wszystko zrobiliśmy jak trzeba, to w górnej części edytora, nad polem edycji skryptu, powinniśmy zobaczyć taki komunikat:



Jeżeli coś poszło nie tak, to zobaczymy:


Klikamy dwukrotnie w czerwony komunikat, na dole powinna pojawić się konsola z błędami:


Niestety komunikaty nie zawsze są jasne, ale przeważnie pozwalają zorientować się w czym jest problem, zwłaszcza, że po podwójnym kliknięciu na dany komunikat, przekierowani zostajemy do konkretnej linijki kodu, w której tkwi problem. W moim przypadku taki komunikat pojawił się gdy zamiast void Start() wpisałem voidStart(), czyli skasowałem spację pomiędzy void i Start().

Kiedy nabierzesz doświadczenia, znajdowanie takich błędów będzie dla ciebie banalne.

Nie mamy już błędów, możemy więc ponownie spróbować dodać skrypt do obiektu. Zaznaczamy nasz obiekt w Hierarchy i przechodzimy do panelu Inspector, gdzie klikamy Add Component. Tym razem nasz skrypt SkokiZab będzie dostępny po wpisaniu jego nazwy w polu wyszukiwania. Wybieramy go z listy.

Jeśli wszystko poszło jak trzeba, w inspektorze powinien pojawić się nasz skrypt:


Teraz z menu File wybierz opcję Save Scenes, aby zapisać zmiany na scenie.

Piszemy mechanikę gry

Wracamy do edycji naszego skryptu. Poniżej znajduje się gotowy skrypt, za chwilę przeanalizujemy go linijka po linijce.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SkokiZab : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
        int dlugoscSkoku = 0;

        if (Input.GetKeyDown(KeyCode.Space))
        {
            dlugoscSkoku = Random.Range(5, 100);
            Debug.Log("Twoja żaba skoczyła " + dlugoscSkoku + " metrów!");
        }
    }
}

Nie jest długi. Zaczynamy.

Wiersz int dlugoscSkoku = 0; to definicja zmiennej. Zacznijmy od tego czym jest zmienna.

Aby to zrozumieć, należy najpierw uświadomić sobie w jaki sposób przechowywane są dane w pamięci komputera. Komputer nie ma możliwości zapisania nigdzie liczby 5, tak jak my robimy to na przykład w zeszycie, potrafi jedynie przechowywać wartości składające się z dwóch stanów. Wyobraź sobie kratkę w zeszycie. Każdą komórkę możesz zamalować lub pozostawić pustą. Komputer tylko w taki sposób potrafi przechowywać dane.


Pamięć jest podzielona na takie właśnie komórki, niektóre są zapełnione, inne nie. Tym wypełnionym przypisuje się wartość 1, a tym pustym wartość 0. Każda taka komórka, przyjmująca dwa możliwe stany (pusty lub pełny) nazywana jest bitem. Problem polega na tym, że my posługujemy się liczbami składającymi się z 10 cyfr (10 możliwych stanów komórki), a nie tylko z dwóch. Nasz system liczbowy nazywa się dziesiętny, system używany przez komputer, nosi miano binarnego. Aby zatem zapisać liczbę 45 w pamięci komputera, należy ją najpierw przekształcić z systemu dziesiętnego na binarny. Na szczęście robi to za nas program, w którym piszemy nasze skrypty, nie musimy więc wiedzieć w jaki sposób się to odbywa.

Aby posługiwanie się danymi było łatwiejsze, bity pogrupowano w bajty. Każdy bajt to nic innego jak grupa ośmiu bitów.


Każdy bajt pozwala na zapisanie liczby od 0 do 255 (czyli 256 możliwych wartości). Aby zrozumieć, dlaczego właśnie tyle, będziemy sobie kolejno wyobrażali co by było gdyby:

Gdyby bajt składał się tylko z 1 bitu, jakie liczby dałoby się na nim zapisać?


Moglibyśmy zapisać liczby 0 lub 1, czyli w sumie 2 wartości.

A gdyby bajt składał się z 2 bitów,  jakie wartości wtedy można by w nim zapisać?


Moglibyśmy zapisać liczby: 0, 1, 2, 3, czyli w sumie 4 wartości.

Gdyby bajt składał się z 3 bitów, moglibyśmy zapisać liczby od 0 do 7 czyli 8 wartości.
Gdyby bajt składał się z 4 bitów, moglibyśmy zapisać liczby od 0 do 15 czyli 16 wartości.
Gdyby bajt składał się z 5 bitów, moglibyśmy zapisać liczby od 0 do 31 czyli 32 wartości.
Gdyby bajt składał się z 6 bitów, moglibyśmy zapisać liczby od 0 do 63 czyli 64 wartości.
Gdyby bajt składał się z 7 bitów, moglibyśmy zapisać liczby od 0 do 127 czyli 128 wartości.
Gdyby bajt składał się z 8 bitów, moglibyśmy zapisać liczby od 0 do 255 czyli 256 wartości.

Tak się składa, że bajt ma właśnie 8 bitów, czyli mamy naszą odpowiedź. Po prostu liczba możliwych kombinacji kratek pełnych i kratek pustych wynosi 256, dlatego można zapisać właśnie tyle danych. Najłatwiej obliczyć to podnosząc 2 do potęgi 8.

Dobra wiadomość jest taka, że nie musisz dokładnie rozumieć jak działa pamięć, aby pisać gry. Warto jednak mieć przynajmniej ogólny pogląd na tą kwestię i już go masz.

Wróćmy teraz do linijki z naszego skryptu int dlugoscSkoku = 0; Wspomniałem, że jest to definicja zmiennej. Teraz mogę Ci powiedzieć czym jest zmienna. Otóż zmienna to nazwa fragmentu pamięci (jednego lub kilku bajtów). Jest to jakby wskaźnik, który mówi nam: Gdy napiszesz dlugoscSkoku = 0, to zapiszesz liczbę 0 w pamięci, w miejscu na które wskazuje zmienna dlugoscSkoku.

Każda zmienna posiada typ. Typ zmiennej mówi nam jak wiele bajtów mamy do dyspozycji. Nasza zmienna dlugoscSkoku jest typu int, czyli daje nam dostęp do 4 bajtów w pamięci. Gdyby zmienna była typu byte, wtedy mielibyśmy dostęp do jednego bajtu, a definicja zmiennej wyglądałaby tak:

byte dlugoscSkoku = 0;

Typ int daje nam dostęp do 4 bajtów, czyli do 32 bitów. Możemy zatem przechować na nim 2³² = 4294967296 możliwych wartości (ponad 4 miliardy kombinacji). Ponieważ jednak typ int pozwala na przechowywanie również wartości ujemnych, zakres liczb jakie możemy zapisać wynosi od -2147483648 do 2147483647 (połowa możliwych kombinacji na wartości ujemne, a druga połowa na dodatnie i zero).

Istnieje wiele typów zmiennych, oprócz liczb, w pamięci przechowywać można również ciągi znaków, które też zamieniane są przez komputer na liczby. Zmienne tego typu ułatwiają pracę na danych programiście w trakcie pisania kodu. Pamiętajmy, że komputer może zapisywać tylko 0 i 1, czyli puste lub zapełnione kratki, to my pisząc skrypt decydujemy co te kratki reprezentują, czy liczbę, czy znak, czy też może fragment obrazka albo dźwięk.

Skąd nazwa "zmienna"? Stąd, że wartości zapisywane w pamięci pokazywanym przez nazwę zmiennej ulegać mogą zmianie. Najpierw możemy zapisać tam na przykład wartość 44, a za chwilę zamienić ją na 217. W programowaniu istnieją również tak zwane stałe. W przeciwieństwie do zmiennych, nie ulegają one nigdy zmianie i mają taką samą wartość, przez cały czas działania programu. Powiemy sobie o nich w kolejnych lekcjach.

Przejdźmy do kolejnego wiersza naszego skryptu:

if (Input.GetKeyDown(KeyCode.Space))

If znaczy po polsku "jeżeli". Jest to tak zwana instrukcja warunkowa. Najłatwiej zrozumieć jej działanie tłumacząc linijkę na język polski: jeżeli (naciśnięto przycisk spacji), to wtedy wykonaj instrukcje umieszczone pomiędzy klamrami { i }.

Dzięki instrukcji if zyskujemy możliwość wykonania danego fragmentu kodu tylko wtedy, gdy spełniony zostanie określony warunek. W naszej grze, po naciśnięciu przycisku spacji, wyświetlana jest liczba metrów jakie skoczyła żaba. Gdyby nie było instrukcji if, liczba metrów wyświetlała by się w każdej klatce naszej gry, czyli 60 razy na sekundę. Gracz nie mógłby w żaden sposób wejść w interakcję z grą.

Instrukcja if jest najważniejszą instrukcją w całym programowaniu. Jest prosta do zrozumienia, będziesz stosował ją setki razy w każdej swojej grze.

W nawiasie podajemy warunek. Warunkiem jest wszystko to, co może przyjąć wartość prawda lub fałsz. Moglibyśmy na przykład napisać taką instrukcję warunkową:

if (dlugoscSkoku > 30)

Oznacza to: jeżeli zmienna dlugoscSkoku ma wartość większą od 30, wtedy...

Gdy zmienna dlugoscSkoku będzie wynosiła na przykład 74, wtedy po podstawieniu tej wartości przez komputer (74 > 30), warunek przyjmie wartość logiczną oznaczającą prawdę (angielskie "true"), gdyż prawdą jest, że 74 jest większe od 30.

Gdyby zmienna dlugoscSkoku wynosiła 12, wtedy warunek przyjmie logiczną wartość oznaczającą fałsz (angielskie "false"), ponieważ nie jest prawdą, że 12 jest większe od 30. W takim przypadku kod w klamrach po instrukcji if, nie wykona się.

W naszej grze, warunkiem jest naciśnięcie spacji, odpowiada za to następująca instrukcja:

Input.GetKeyDown(KeyCode.Space)

Input to nazwa zbioru funkcji (poleceń), który zawiera polecenia związane z obsługą klawiatury, myszki oraz pada. GetKeyDown to funkcja ze zbioru poleceń Input. Podczas jej wywoływania, w nawiasie podajemy parametr, mówiący jaki klawisz chcemy sprawdzić. Funkcja sprawdza, czy podany w jej parametrze klawisz, został wciśnięty, jeżeli tak, to funkcja zwraca wartość true (prawda), jeżeli nie, zwraca false (fałsz).

Kropka pomiędzy Input oraz GetKeyDown to oznaczenie, które mówi nam, że funkcja GetKeyDown pochodzi ze zbioru poleceń Input. Jeżeli w edytorze skryptów wpiszemy Input i kropkę, to po jej postawieniu, powinna pokazać nam się lista wszystkich poleceń z tego zbioru. Podpowiedzi tego typu są na porządku dziennym, a ich zadaniem jest ułatwienie i przyśpieszenie twojej pracy w trakcie pisania skryptu.

Następnie w naszym skrypcie mamy klamrę otwierającą, która rozpoczyna blok instrukcji, jaki wykona się w przypadku gdy warunek instrukcji if okaże się prawdą. W bloku znajdują się dwie instrukcje, omówmy pierwszą z nich:

dlugoscSkoku = Random.Range(5, 100);

Range to instrukcja ze zbioru Random. Zbiór ten zawiera zestaw poleceń, związanych z generowaniem liczb losowych. Funkcja (polecenie) Range generuje liczbę losową, zależnie od podanych parametrów. W naszym przypadku wygeneruje liczbę od 5 do 99. Dlaczego do 99, a nie 100? No cóż, nie ma w zasadzie żadnego, wyraźnego powodu, po prostu w taki sposób to polecenie zostało napisane, przez jego twórców.

Wygenerowana liczba jest zwracana przez funkcję. W praktyce oznacza to, że ciąg znaków Random.Range(5, 100), zostanie przez komputer zamieniony na losową liczbę i otrzymamy na przykład:

dlugoscSkoku = 89;

Oczywiście zamiana ta dzieje się tylko tymczasowo w pamięci komputera i tylko w trakcie działania programu, pliki naszego skryptu nie zostaną w żaden sposób zmodyfikowane. Wartość zwróconą przez funkcję, zapisujemy do zmiennej dlugoscSkoku. Jeżeli byśmy tego nie zrobili, stracilibyśmy dostęp do wygenerowanej wartości losowej, a tak mamy do niej dostęp i możemy dalej coś ciekawego z nią zrobić (my akurat ją po prostu za chwilę wyświetlimy).

Została nam do omówienia już tylko jedna linijka kodu:

Debug.Log("Twoja żaba skoczyła " + dlugoscSkoku + " metrów!");

Funkcja Log, ze zbioru Debug, pozwala wyświetlić dowolny ciąg znaków w konsoli edytora Unity (panel Console widoczny na dole). O ile liczby zapisujemy normalnie, pisząc po prostu daną liczbę, o tyle ciąg znaków zapisujemy pomiędzy znakami cudzysłowu. Musimy tak zrobić, aby komputer wiedział, że dane słowo jest ciągiem znaków wpisanym przez nas, a nie poleceniem lub instrukcją, będąca częścią języka programowania, którego używamy. Jeżeli zapomnimy o znaku cudzysłowu, wtedy edytor skryptu będzie próbował szukać poleceń o nazwie: Twoja, żaba, skoczyła, metrów. Oczywiście nie znajdzie ich i próba uruchomienia gry zakończy się błędem.

W naszym przykładzie robimy coś niezwykłego. Dodajemy do siebie ciąg znaków i liczbę, która znajduje się w zmiennej dlugoscSkoku. Jakim cudem komputer jest w stanie dodać do siebie coś takiego jak litery i liczby? Przecież nie ma takiego działania matematycznego. Rzeczywiście nie ma, dlatego komputer nie traktuje tego dodawania w taki sam sposób jak dodawanie matematyczne. Dla niego takie dodawanie oznacza doklejenie liczby przechowywanej w zmiennej dlugoscSkoku, do ciągu znaków przed plusem.

Skrypt gotowy. Zapisujemy go teraz wybierając z menu w edytorze skryptów File i opcję Save. Możemy też go skompilować (przerobić z kodu zrozumiałego dla człowieka, na kod zrozumiały dla komputera), wybierając menu Build i opcje Build All. Nie jest to jednak konieczne, bo będzie działo się automatycznie, gdy za chwilę każemy naszej grze się uruchomić.

Aby uruchomić naszą grę, wracamy do edytora Unity i naciskamy przycisk play (z ikoną trójkąta, widoczny w górnej części okna):


Jeśli wszystko poszło dobrze, przyciski zmienią swój kolor.


Nasza gra jest uruchomiona. Upewnijmy się, że widzimy zawartość konsoli wybierając z menu Window opcję Console.

Zanim zagramy w naszą grę, musimy koniecznie kliknąć gdzieś w środek okno z widokiem sceny:


Robimy to po to, żeby gra była aktywna i wciskane klawisze działały poprawnie. Jeżeli teraz naciśniemy spację, w konsoli pojawi się:


Gratulacje! Twoja pierwsza gra skończona.

Komentarze

Popularne posty z tego bloga

Lekcja 2: Nasza druga gra, tym razem w 3D

Jak zrobić grę?