Download as pdf or txt
Download as pdf or txt
You are on page 1of 473

Spis treści

Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej
publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną,
fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym
powoduje naruszenie praw autorskich niniejszej publikacji.

Wszystkie znaki występujące w tekście są zastrzeżonymi znakami


firmowymi bądź towarowymi ich właścicieli.

Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje
były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie,
ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz
Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody
wynikłe z wykorzystania informacji zawartych w książce.

Redaktor prowadzący: Małgorzata Kulik

Projekt okładki: Studio Gravite / Olsztyn


Obarek, Pokoński, Pazdrijowski, Zaprucki

Grafika na okładce została wykorzystana za zgodą Shutterstock.com

Wydawnictwo HELION
ul. Kościuszki 1c, 44-100 GLIWICE
tel. 32 231 22 19, 32 230 98 63
e-mail: helion@helion.pl
WWW: http://helion.pl (księgarnia internetowa, katalog książek)

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/unityc
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

Kody źródłowe wybranych przykładów dostępne są pod adresem:


ftp://ftp.helion.pl/przyklady/unityc.zip

ISBN: 978-83-283-4390-0

Copyright © Helion 2018

Printed in Poland.

• Kup książkę • Księgarnia internetowa


• Poleć książkę • Lubię to! » Nasza społeczność
• Oceń książkę
Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Spis treści
Wstęp ................................................................................................................. 9
O czym jest książka? ................................................................................................................... 9
Ale czy na pewno przeciętna osoba bez wrodzonych cech programisty
może się nauczyć programować? ........................................................................................ 11
Struktura książki ....................................................................................................................... 11

Lekcja 1. Programowanie w C# i Unity — szybki start ........................................... 13


Instrukcja instalacji programów Unity i Visual Studio ....................................................... 13
Unity i Visual Studio — pierwsze uruchomienie
i utworzenie pierwszego projektu ....................................................................................... 17
Informacje o Unity i Visual Studio ................................................................................. 17
Utworzenie pierwszego projektu .................................................................................... 17
Główne okna Unity ........................................................................................................... 18
Uruchomienie Visual Studio ........................................................................................... 19
Okna Unity oraz wstawienie pierwszych obiektów na scenę ............................................. 22
Podstawowe okna Unity ................................................................................................... 22
Zasoby i prefabrykaty ....................................................................................................... 23
Wstawienie obiektów na scenę ........................................................................................ 23
Modyfikacja obiektów poprzez okno inspektora .......................................................... 24
Uruchomienie gry ............................................................................................................. 25
Podstawowe komponenty: Transform, Collider, Renderer i Rigidbody .......................... 25
Komponenty ogólnie ........................................................................................................ 25
Komponent Transform .................................................................................................... 26
Komponent Renderer ....................................................................................................... 27
Komponent Collider ......................................................................................................... 27
Komponent Rigidbody ..................................................................................................... 27

Kup książkę Poleć książkę


4 Unity i C#. Podstawy programowania gier

Pierwszy własny skrypt C# i pierwszy własny komponent ................................................. 28


Dodanie własnego komponentu ..................................................................................... 28
Kod źródłowy komponentu ............................................................................................. 28
Komentarze w kodzie programu ..................................................................................... 29
Dodanie parametru do komponentu ............................................................................. 29
Komponent a klasa ............................................................................................................ 30
Funkcje. Specjalne funkcje komponentów Unity.
Użycie funkcji OnCollisionEnter ................................................................................ 31
Obiekty i pobieranie komponentów jako obiektów.
Zmiana parametrów i pól obiektu ............................................................................... 32
Bardziej zaawansowany sposób wykonania zadania (opcjonalnie) ........................... 32
Kompilacja projektu w Unity .................................................................................................. 34
Porady i pomoc w poruszaniu się po programach Unity i Visual Studio ......................... 35
Mam otwarte Unity, ale nie widać sceny i obiektów .................................................... 35
Nie umiem otworzyć Visual Studio tak,
aby otwierało mój projekt i moje pliki źródłowe ...................................................... 35
Zadania do samodzielnego wykonania .................................................................................. 36
Zadanie 1. Rozbudowa projektu ObjectClicker — część I .......................................... 36
Zadanie 2. Rozbudowa projektu ObjectClicker — część II ......................................... 37
Zadanie 3. Rozbudowa projektu ObjectClicker — część III ....................................... 38
Zadanie 4. Rozbudowa projektu ObjectClicker — część IV ....................................... 40

Lekcja 2. Informacja, algorytm, kompilacja ......................................................... 45


Informacja a algorytm .............................................................................................................. 45
W świecie komputerów informacja jest wszystkim ...................................................... 45
W świecie komputerów programista jest najważniejszy ............................................. 46
Sposób zapisu informacji to też informacja .................................................................. 46
Algorytm. Główna rola programisty polega
na zapisaniu algorytmu w języku programowania ................................................... 46
Do przemyślenia ................................................................................................................ 47
Algorytmy .................................................................................................................................. 47
Algorytm Pieczenie ciasta ................................................................................................ 47
Algorytm obliczania pola powierzchni koła .................................................................. 50
Zapis algorytmu w schemacie blokowym na przykładzie algorytmu gry 3-5-8 ....... 51
Zapis algorytmu gry 3-5-8 w pseudokodzie .................................................................. 53
Dokumentacja oraz procesy tworzenia gier .......................................................................... 53
Metody tworzenia gier i programów .............................................................................. 53
Role w projekcie ................................................................................................................ 54
Dokumentacja projektowa ............................................................................................... 56

Kup książkę Poleć książkę


Spis treści 5

Kompilacja projektu w Unity i Visual Studio, biblioteki, pliki projektu .......................... 58


Kompilacja projektu w Unity .......................................................................................... 58
Pliki bibliotek ..................................................................................................................... 59
Pliki projektu i rozwiązania ............................................................................................. 60
Inne pliki i katalogi ........................................................................................................... 61
Kompilacja kodu źródłowego w Visual Studio ............................................................. 61
Zadania do samodzielnego wykonania .................................................................................. 62
Samodzielne utworzenie dokumentacji projektowej gry ............................................. 62

Lekcja 3. Typy danych, zmienne, funkcje i klasy .................................................... 63


Jak manipulować obiektami na scenie 3D w Unity ............................................................. 63
Przybornik narzędzi .......................................................................................................... 63
Przyciąganie podczas przesuwania ................................................................................. 64
Szybkie debugowanie zmiennych w Unity i VS ................................................................... 64
Typy danych i zmienne ............................................................................................................ 66
Typy danych i zmienne .................................................................................................... 66
Rzutowanie zmiennych .................................................................................................... 69
Funkcje ....................................................................................................................................... 69
Klasy — część I .......................................................................................................................... 72

Lekcja 4. Instrukcje warunkowe .......................................................................... 75


Instrukcje warunkowe — część I ............................................................................................ 75
Zadania do samodzielnego wykonania .................................................................................. 77
Projekt JakimJestemTypem — część I ............................................................................ 77
ProjektRosliny — część I .................................................................................................. 79
ProjektRosliny — część II ................................................................................................ 81
Projekt JakimJestemTypem — część II .......................................................................... 85

Lekcja 5. Typy danych, klasy, instrukcje warunkowe — ciąg dalszy.


Programowanie w Unity .................................................................................... 89
Klasy — część II ........................................................................................................................ 89
Dziedziczenie klas ............................................................................................................. 89
Tworzenie nowych obiektów ........................................................................................... 92
Złożenia wywołań metod i pól ........................................................................................ 92
Słowo kluczowe this .......................................................................................................... 93
Rzutowanie typów obiektowych ..................................................................................... 94

Kup książkę Poleć książkę


6 Unity i C#. Podstawy programowania gier

Instrukcje warunkowe — część II ........................................................................................... 95


Zagnieżdżanie warunków ........................................................................................................ 95
Kolejność obliczeń .................................................................................................................... 96
Operator ! ........................................................................................................................... 96
Zadanie do samodzielnego wykonania .................................................................................. 97
Projekt JakimJestemTypem — część III ......................................................................... 97
Programowanie komponentów Unity ................................................................................. 100
Funkcje Update i OnGUI ............................................................................................... 100
Zmiana pozycji obiektu sceny w hierarchii obiektów ................................................ 102
Aktywność obiektu .......................................................................................................... 103
GameObject.Find ............................................................................................................ 103
Zadania do samodzielnego wykonania ................................................................................ 104
ProjektRosliny — część III ............................................................................................. 104
Gra 3-5-8 .......................................................................................................................... 108

Lekcja 6. Kolekcje i pętle .................................................................................. 113


Kolekcje .................................................................................................................................... 113
Kolekcje ogólnie .............................................................................................................. 113
Deklaracja i używanie tablic .......................................................................................... 113
Ćwiczenie ......................................................................................................................... 114
Pętle for i foreach .................................................................................................................... 115
Pętla for ............................................................................................................................. 115
Przykłady pętli for ........................................................................................................... 116
Zadanie do samodzielnego wykonania ................................................................................ 119
Ćwiczenie pętli for .......................................................................................................... 119
Pętla foreach ............................................................................................................................ 119
Zadania do samodzielnego wykonania ................................................................................ 121
Ćwiczenie pętli foreach .................................................................................................. 121
Projekt ObjectClicker— część V ................................................................................... 122
Pętla while ................................................................................................................................ 123
Pętla while ........................................................................................................................ 123
Zadanie do samodzielnego wykonania ................................................................................ 125
Projekt ObjectClicker — część VI — wersja z pętlą while.......................................... 125
Podsumowanie tematyki pętli ............................................................................................... 125
Zadania do samodzielnego wykonania ................................................................................ 126
ProjektRosliny — część IV ............................................................................................. 126
Gra MicroAbrix ............................................................................................................... 130

Kup książkę Poleć książkę


Spis treści 7

Lekcja 7. Cykl życia obiektów, przestrzenie nazw,


instrukcja switch, typ string, debugowanie ....................................................... 133
Konstruktory i przeciążanie metod ...................................................................................... 133
Konstruktory. Cykl życia obiektów .............................................................................. 133
Przeciążanie metod ......................................................................................................... 134
Widoczność zmiennych ......................................................................................................... 136
Widoczność zmiennych wewnątrz bloków ................................................................. 136
Pola klasy .......................................................................................................................... 137
Inne sposoby przekazywania parametrów: out i ref ................................................... 139
Pola statyczne klasy ......................................................................................................... 141
Przestrzenie nazw ............................................................................................................ 142
Instrukcja switch ..................................................................................................................... 143
Instrukcja switch ............................................................................................................. 143
Instrukcje break i continue ............................................................................................ 144
Typ string ................................................................................................................................. 144
Typy danych string i char ............................................................................................... 144
Metody i pola klasy String .............................................................................................. 145
Klasa StringBuilder ......................................................................................................... 145
Konwersja liczb na tekst i odwrotnie ............................................................................ 146
Debugowanie w Visual Studio .............................................................................................. 146
Podłączenie Visual Studio do gry uruchomionej w Unity ........................................ 146
Stos wywołań ................................................................................................................... 148
Podgląd i modyfikacja wartości zmiennych ................................................................ 148
Kontynuacja wykonania programu po pułapce .......................................................... 149
Zadania do samodzielnego wykonania ................................................................................ 150
Projekt FixMe1 ................................................................................................................ 150
Projekt FixMe2 ................................................................................................................ 152
Uszkodzony ProjektRosliny — część V ....................................................................... 155

Lekcja 8. Typ enum. Użycie gotowego kodu ....................................................... 161


Typ wyliczeniowy — Enum .................................................................................................. 161
Typ enum ......................................................................................................................... 161
Rzutowanie typu enum ................................................................................................... 162
Wyszukiwanie i użycie dokumentacji technicznej.
Wykorzystanie gotowego kodu ......................................................................................... 163
Pomoc techniczna Unity i Visual Studio ..................................................................... 163
Uzyskiwanie pomocy w internecie ............................................................................... 165

Kup książkę Poleć książkę


8 Unity i C#. Podstawy programowania gier

Zakup zasobów. Unity Asset Store ............................................................................... 165


Wady i zalety używania gotowego kodu ...................................................................... 167
Zadania do samodzielnego wykonania ................................................................................ 169
Gotowy projekt Tanks! ................................................................................................... 169

Skorowidz ...................................................................................................... 171

Kup książkę Poleć książkę


Lekcja 4.
Instrukcje warunkowe
Instrukcje warunkowe — część I
Podczas omawiania algorytmów widzieliśmy, jak wykonanie kodu programu może roz-
gałęziać się w zależności od pewnego warunku. Przykładowo, jeśli zmienna X ma war-
tość większą niż 10, dodaj do niej 1, a jeśli mniejszą, dodaj 2. Zapisuje się to tak jak na li-
stingu 4.1.

LISTING 4.1. Przykład instrukcji warunkowej

if (X > 10)
X += 1;
else
X += 2;

W nawiasach po słowie kluczowym if powinien znaleźć się warunek — zestaw obliczeń,


których wynikiem jest true (tak) albo false (nie). Następnie pojawia się operacja (tutaj:
dodania wartości 1 do X), która jest wykonywana, jeśli warunek ma wartość true. Po
słowie kluczowym else możemy wpisać operację wykonywaną, jeśli warunek ma war-
tość false. Część po else nie jest wymagana.

Zamiast pojedynczej operacji można wpisać wiele operacji, umieszczając je w nawiasach


klamrowych jak na listingu 4.2.

LISTING 4.2. Przykład rozbudowanej instrukcji warunkowej

if (X > 10)
{
X += 1;
Y = 0;
}
else
{
X += 2;
Y = -1;
}

Kup książkę Poleć książkę


76 Unity i C#. Podstawy programowania gier

Jako warunku można użyć również zmiennej typu bool.

Operatory, które służą do tworzenia warunków, to:


 ==, czyli operator równości, np. A == B zwraca true, tylko jeśli A ma taką wartość
jak B;
 !=, czyli operator różnicy, np. A != B zwraca true, tylko jeśli A ma inną wartość niż B;

 > lub <, czyli operatory większości i mniejszości, np. A > B zwraca true, tylko jeśli A
jest większe niż B;
 >= lub <=, czyli operatory „większy lub równy” oraz „mniejszy lub równy”, np. A <= B
zwraca true, tylko jeśli A jest mniejsze lub równe B.

Operatory te można bez przeszkód stosować na typach prostych takich jak int czy bool,
ale na typach obiektowych można stosować tylko operatory == i !=, które sprawdzają,
czy dwie zmienne mają przypisany dokładnie ten sam obiekt.

Specjalną wartością dla zmiennych obiektowych jest null. Oznacza ona, że nie jest przy-
pisany żaden obiekt. Uwaga: próba wywołania funkcji dla zmiennej obiektowej o wartości
null zawsze skończy się błędem wykonania programu. Dobrą praktyką jest więc spraw-
dzanie, czy taka wartość jest przypisana do zmiennej, zawsze kiedy nie ma co do tego ab-
solutnej pewności — jak np. na listingu 4.3.

LISTING 4.3. Przykład użycia słowa kluczowego null

void Funkcja(JakasKlasa1 JakasZmienna)


{
if (JakasZmienna != null)
JakasZmienna.CiekawaFunkcja(7);
}

Gdyby do funkcji Funkcja w parametrze JakasZmienna trafiła wartość null, wywołanie


metody CiekawaFunkcja zwróciłoby błąd. Sprawdzamy jednak za pomocą warunku, czy
w zmiennej znajduje się null. Jeśli nie, na pewno jest to jakiś obiekt, dla którego możemy
wywołać metodę CiekawaFunkcja.

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 77

Zadania do samodzielnego wykonania

Projekt JakimJestemTypem — część I


Czas: około 30 – 40 minut.

Zadanie
Zadaniem kursanta jest utworzenie prostej gry (można wykorzystać jeden z projektów
z lekcji 1.), w której będzie się znajdować kilka brył 3D mających jeden z trzech kom-
ponentów:
 komponent z polem typu całkowitego,
 komponent z polem typu zmiennoprzecinkowego,
 komponent z polem typu bool.

Obiekt RigidbodyFPSController z gry powinien posiadać komponent o nazwie Gracz,


którego zadaniem będzie zbadanie po zaistnieniu kolizji z jedną z brył, jaki komponent
posiada bryła, a następnie pobranie z niego wartości i dodanie do wewnętrznej sumy:
 wartości pola całkowitego,
 wartości pola zmiennoprzecinkowego zrzutowanej na typ całkowity,
 1, jeżeli wartość pola typu bool to true.

Po każdym dodaniu Gracz powinien wypisać na konsoli aktualną wartość wewnętrznej


sumy.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();

Kup książkę Poleć książkę


78 Unity i C#. Podstawy programowania gier

if(ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
} else if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
else if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Plik KomponentZLiczbaCalkowita.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaCalkowita : MonoBehaviour {


public int Liczba;
}

Plik KomponentZLiczbaZmiennoprzecinkowa.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZLiczbaZmiennoprzecinkowa : MonoBehaviour {


public float Liczba;
// Update is called once per frame
void Update () {
int JestemIntem;
float JestemFloatem = 2.7f;
JestemIntem = (int)JestemFloatem;
}
}

Plik KomponentZPolemBool.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 79

public class KomponentZPolemBool : MonoBehaviour {


public bool PoleBool;
}

ProjektRosliny — część I
Czas: około 45 – 60 minut.

Zadanie
W lekcji 2. jedno z zadań dodatkowych związane było z projektem o nazwie ProjektRosliny.
Kursant miał za zadanie utworzenie dokumentacji projektowej do takiej właśnie gry.
Nadszedł teraz czas na utworzenie rozwiązania dla pierwszej wersji tej gry.

Celem gry jest podniesienie sadzonek (po jednej) i zaniesienie ich do doniczek. Kliknięcie
w doniczkę, gdy gracz niesie sadzonkę, powoduje zasadzenie drzewa. Gra kończy się, gdy
gracz zasadzi poprawnie co najmniej 3 drzewa.

W projekcie o nazwie ProjektRosliny_szablon znajdziesz puste sceny zawierające zasoby


graficzne niezbędne do realizacji gry, w tym m.in. sadzonki w grupie obiektów Sadzonki,
rośliny dorosłe w grupie obiektów Rosliny oraz doniczki w grupie obiektów Doniczki.

Podpowiedź
Utwórz komponenty Doniczka, Sadzonka i Gracz. Niech komponent Gracz będzie przypi-
sany do obiektu FPSRigidbodyController i niech zapamiętuje, czy gracz niesie sadzonkę,
za pomocą publicznej zmiennej typu Sadzonka. Komponent Doniczka może reagować na
dotknięcie swojego obiektu na scenie uruchomieniem funkcji OnCollisionEnter i wprowa-
dzeniem odpowiednich zmian związanych z obiektami sadzonek i roślin. Powiąż sadzonkę
z odpowiadającą jej rośliną, dodając w klasie Sadzonka publiczne pole typu GameObject.
Do pola typu GameObject w edytorze Unity możesz przypisać dowolny obiekt, posiadający
dowolną liczbę i typ komponentów.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoRosline()
{

Kup książkę Poleć książkę


80 Unity i C#. Podstawy programowania gier

// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy


NiesionaSadzonka = null;

// sprawdzamy, ile roślin zostało już posadzonych


LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// uwaga! sprawdzamy, czy gracz cokolwiek niesie, aby próba wejścia na doniczkę bez sadzonki nie
// spowodowała błędu
if (obiektGracz.NiesionaSadzonka != null)
{
Sadzonka doZasadzeniaSadzonka = obiektGracz.NiesionaSadzonka;
GameObject doZasadzeniaRoslina = doZasadzeniaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, aby znalazła się w doniczce
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.PosadzonoRosline();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 81

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
Transform transformSadzonki = GetComponent<Transform>();
Renderer rendererSadzonki = transformSadzonki.GetComponentInChildren<Renderer>();
Collider colliderSadzonki = transformSadzonki.GetComponentInChildren<Collider>();
rendererSadzonki.enabled = false;
colliderSadzonki.enabled = false;
}
}

ProjektRosliny — część II
Czas: około 90 minut.

Zadanie
Grę utworzoną w poprzednim zadaniu, ProjektRosliny, rozbuduj do drugiej wersji. W kilku
miejscach na ziemi powinny leżeć konewki. Gracz może podnieść konewkę i nieść ją
równocześnie z sadzonką. Dotknięcie doniczki, gdy gracz niesie sadzonkę, powinno spowo-
dować posadzenie sadzonki (w doniczce powinna pojawić się mała roślina), a dotknięcie
doniczki, gdy jest w niej sadzonka i gracz niesie konewkę, powinno powodować, że wy-
rośnie drzewo. Warunki zwycięstwa nie zmieniają się, ale gracz może też przegrać — za-
blokuje się, jeżeli weźmie więcej niż jedną konewkę naraz.

W materiałach dołączonych do książki znajdziesz katalog WateringCan, a w nim zasoby


graficzne dla konewki (w tym gotowy do użycia na scenie obiekt-prefabrykat o nazwie
WateringCanPrefab).

Podpowiedź
Rozmiar kodu źródłowego rośnie i niektóre jego fragmenty są coraz bardziej rozbudo-
wane albo wykonywane kilka razy. Przykładowo, z pewnością trzeba będzie kilka razy
zmieniać ustawienie, czy sadzonka jest widoczna, czy nie. W takich przypadkach do do-
brych praktyk należy przeniesienie fragmentu kodu, który za dane działanie odpowiada,

Kup książkę Poleć książkę


82 Unity i C#. Podstawy programowania gier

do osobnej funkcji. Dobrym miejscem jest klasa Sadzonka. Takie modyfikacje kodu źró-
dłowego pod wpływem nowych wymagań są typowe dla programowania zwinnego i na-
zywają się refaktoryzacją.

Gra zawiera już sporo logiki działań i nie jest całkowicie liniowa. Może się zdarzyć, że
źle zakodujesz któryś z warunków i w trakcie testowania gry pojawi się błąd spowodo-
wany odwołaniem do pola w obiekcie null. Unity wyświetla wówczas w konsoli szcze-
gółową informację o tym, w którym pliku źródłowym i w której jego linii wystąpił błąd, np.:
NullReferenceException: Object reference not set to an instance of an object
Doniczka.OnCollisionEnter(UnityEngine.Collision collision) (at Assets/Doniczka.cs:22)

W tym przypadku warto zajrzeć do pliku Doniczka.cs (komponent Doniczka), do linii


o numerze 22 (numery linii wypisane są po lewej stronie okna z kodem źródłowym).
W dalszej części kursu dowiesz się jeszcze, jak zatrzymywać wykonanie programu w kon-
kretnej linii i jak badać stan zmiennych w tym momencie.

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


public Sadzonka NiesionaSadzonka;
public bool NiesionaKonewka;
private int LiczbaPosadzonychRoslin;
// Use this for initialization
void Start () {
LiczbaPosadzonychRoslin = 0;
}
public void PosadzonoSadzonke()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy
NiesionaSadzonka = null;
}
public void WyrosloDrzewo()
{
// przestajemy nieść sadzonkę, właśnie ją zasadziliśmy, nie niesiemy też już konewki
NiesionaSadzonka = null;
NiesionaKonewka = false;
// sprawdzamy, ile roślin zostało już posadzonych
LiczbaPosadzonychRoslin++;
if(LiczbaPosadzonychRoslin == 3)
{ // zwycięstwo!
Debug.Log("Zwycięstwo!!!");
Collider ColliderGracza = GetComponent<Collider>();
ColliderGracza.enabled = false;
}
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 83

Plik Doniczka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Doniczka : MonoBehaviour {


public Sadzonka posadzonaSadzonka;
// Use this for initialization
void Start () {
posadzonaSadzonka = null;

// Update is called once per frame


void Update () {
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
// sprawdzamy, czy gracz próbuje podlać sadzonki w doniczce
if (posadzonaSadzonka != null && obiektGracz.NiesionaKonewka)
{
NiechWyrosnieDrzewo(obiektGracz);
}
// sprawdzamy, czy gracz niesie sadzonkę do posadzenia;
// uwaga: gracz może posadzić sadzonkę na miejscu innej sadzonki — przegra wówczas grę
else if (obiektGracz.NiesionaSadzonka != null)
{
posadzonaSadzonka = obiektGracz.NiesionaSadzonka;
// przenosimy sadzonkę w nowe miejsce
Transform transformSadzonki = posadzonaSadzonka.GetComponent<Transform>();
Transform transformDoniczki = GetComponent<Transform>();
Vector3 pozycja = transformSadzonki.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformSadzonki.position = pozycja;
posadzonaSadzonka.WlaczRenderer(true);
obiektGracz.PosadzonoSadzonke();
}
else
Debug.Log("Gracz nie ma sadzonki.");
}
// jeśli wszystkie warunki zostaną spełnione, wywołamy tę funkcję, aby wyrosło drzewo;
// w 1. wersji projektu kod ten znajdował się w funkcji OnCollisionEnter,
// ale gdy rozmiar kodu pojedynczej funkcji rośnie, dla czytelności warto go podzielić
private void NiechWyrosnieDrzewo(Gracz obiektGracz)
{
GameObject doZasadzeniaRoslina = posadzonaSadzonka.Roslina;
// włączamy roślinę
Transform transformRosliny = doZasadzeniaRoslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = true;
// przemieszczamy roślinę, tak aby znalazła się w doniczce

Kup książkę Poleć książkę


84 Unity i C#. Podstawy programowania gier

Transform transformDoniczki = GetComponent<Transform>();


Vector3 pozycja = transformRosliny.position;
pozycja.x = transformDoniczki.position.x;
pozycja.y = transformDoniczki.position.y;
pozycja.z = transformDoniczki.position.z;
transformRosliny.position = pozycja;
// wyłączamy sadzonkę w doniczce
posadzonaSadzonka.WlaczRenderer(false);
// powiadamiamy obiekt gracza, że została posadzona roślina
obiektGracz.WyrosloDrzewo();
// rośnie już drzewo, a nie sadzonka
posadzonaSadzonka = null;
}
}

Plik Sadzonka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Sadzonka : MonoBehaviour {


public GameObject Roslina;
// Use this for initialization
void Start () {
// sprawdzamy, czy w edytorze na pewno zostało ustawione pole Roslina
if (Roslina == null)
Debug.LogError("Brak ustawienia pola Roslina! ");
// na starcie dorosła roślina ma zniknąć
Transform transformRosliny = Roslina.GetComponent<Transform>();
// GetComponentInChildren<Renderer>() szuka komponentu Renderer w podobiektach tego obiektu;
// szukamy renderera obiektu o nazwie RoslinaX_Obiekt
Renderer rendererRosliny = transformRosliny.GetComponentInChildren<Renderer>();
rendererRosliny.enabled = false;
}
private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaSadzonka = this;
// wyłączamy sadzonkę
WlaczRenderer(false);
WlaczCollider(false);
}
public void WlaczCollider(bool CzyWlaczyc)
{
Collider ColliderSadzonki = GetComponentInChildren<Collider>();
ColliderSadzonki.enabled = CzyWlaczyc;
}
public void WlaczRenderer(bool CzyWlaczyc)
{
Renderer RendererSadzonki = GetComponentInChildren<Renderer>();
RendererSadzonki.enabled = CzyWlaczyc;
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 85

Plik Konewka.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Konewka : MonoBehaviour {


private void OnCollisionEnter(Collision collision)
{
Gracz obiektGracz = collision.collider.GetComponent<Gracz>();
obiektGracz.NiesionaKonewka = true;
// wyłączamy tę konewkę
Collider colliderKonewki = GetComponent<Collider>();
gameObject.SetActive(false);
colliderKonewki.enabled = false;
}
}

Projekt JakimJestemTypem — część II


Czas: około 60 minut.

Zadanie
Projekt JakimJestemTypem należy rozbudować o nowy komponent, który zamiast pola
z typem prostym będzie zawierał trzy pola z typami obiektowymi. Tymi typami będą klasy,
które utworzyliśmy w trakcie lekcji (a więc komponenty z typami prostymi).

Inaczej mówiąc, w rozwiązaniu powinien pojawić się następujący schemat:


 KomponentzPolemObiektowym,

 pole ObiektZIntem typu KomponentZLiczbaCalkowita,


 pole ObiektZFloatem typu KomponentZLiczbaZmiennoprzecinkowa,
 pole ObiektZBoolem typu KomponentZPolemBool.

KomponentzPolemObiektowym powinien mieć funkcję, która sama wyznaczy sumę dla po-
siadanych przez niego obiektów.

Gdy skończysz, poeksperymentuj według własnego uznania, dodając więcej obiektów na


scenę, dodatkowe złożone komponenty itp.

Podpowiedź
Pola obiektowe uzupełnij w edytorze (w przyszłości dowiesz się, jak tworzyć nowe obiekty
w kodzie). Aby to zrobić, najpierw musi istnieć obiekt na scenie z odpowiednim kom-
ponentem. Utwórz kilka ukrytych obiektów bez reprezentacji graficznej, które będą po-
siadały wyłącznie komponent Transform i ten z komponentów z lekcji, który chcesz za-
stosować i przypisać do pola obiektowego.

Kup książkę Poleć książkę


86 Unity i C#. Podstawy programowania gier

Rozwiązanie
Plik Gracz.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gracz : MonoBehaviour {


private float Suma;
// Use this for initialization
void Start () {
Suma = 0f;
}
private void OnCollisionEnter(Collision collision)
{
KomponentZLiczbaCalkowita ObiektZLiczbaCalkowita =
collision.collider.GetComponent<KomponentZLiczbaCalkowita>();
KomponentZLiczbaZmiennoprzecinkowa ObiektZLiczbaZmiennoprzec =
collision.collider.GetComponent<KomponentZLiczbaZmiennoprzecinkowa>();
KomponentZPolemBool ObiektZPoleBool =
collision.collider.GetComponent<KomponentZPolemBool>();
KomponentZPolemObiektowym ObiektZObiektami =
collision.collider.GetComponent<KomponentZPolemObiektowym>();
if (ObiektZLiczbaCalkowita != null)
{
int wartosc = ObiektZLiczbaCalkowita.Liczba;
Debug.Log("Trafiony ma typ z liczbą całkowitą: " + wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZLiczbaZmiennoprzec != null)
{
int wartosc = (int)ObiektZLiczbaZmiennoprzec.Liczba;
Debug.Log("Trafiony ma typ z liczbą zmiennoprzecinkową, zmieniamy ją na: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
if (ObiektZPoleBool != null)
{
int wartosc = 0;
if(ObiektZPoleBool.PoleBool == true )
{
wartosc = 1;
Debug.Log("Trafiony ma typ z polem bool o wartości true, dodajemy 1 do sumy");
} else Debug.Log("Trafiony ma typ z polem bool o wartości false");
Suma = Suma + wartosc;
}
if (ObiektZObiektami != null)
{
int wartosc = ObiektZObiektami.PodajSwojaSume();
Debug.Log("Suma dla komponentu z polami obiektowymi wynosi: " +
wartosc.ToString());
Suma = Suma + wartosc;
}
Debug.Log("Suma wynosi: " + Suma.ToString());
}
}

Kup książkę Poleć książkę


Lekcja 4.  Instrukcje warunkowe 87

Plik KomponentZPolemObiektowym.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KomponentZPolemObiektowym : MonoBehaviour {


public KomponentZLiczbaCalkowita ObiektZIntem;
public KomponentZLiczbaZmiennoprzecinkowa ObiektZFloatem;
public KomponentZPolemBool ObiektZBoolem;
public int PodajSwojaSume()
{
int Suma = 0;
if (ObiektZIntem != null)
Suma += ObiektZIntem.Liczba;
if (ObiektZFloatem != null)
Suma += (int)ObiektZFloatem.Liczba;
if (ObiektZBoolem != null)
if (ObiektZBoolem.PoleBool == true)
Suma++;
return Suma;
}
}

Pliki KomponentZLiczbaCalkowita.cs, KomponentZLiczbaZmiennoprzecinkowa.cs i Komponent


ZPolemBool.cs są takie same jak w zadaniu „Projekt JakimJestemTypem — część I”.

Kup książkę Poleć książkę


88 Unity i C#. Podstawy programowania gier

Kup książkę Poleć książkę


Skorowidz
A techniczna, 163
wizja projektu, 56
agile, 54
wymagań, 57
aktywność obiektu, 103
dostęp
algorytm, 46
do metod, 91
obliczania pola powierzchni koła, 50
do renderera, 32
Pieczenie ciasta, 47
dziedziczenie klas, 89
architektura projektu, 58

B F
FPS, frame per second, 100
biblioteka, 59
funkcja, 31, 69
błędy, 147
OnCollisionEnter, 31
breakpoint, 147
OnGUI, 100
C Parse, 146
Update, 100, 101
cykl życia
funkcje
obiektu, 133
prywatne, 71
projektu, 54
publiczne, 71
D G
debugowanie, 64
gra MicroAbrix, 130
breakpoint, 147
GUI, 102
kontynuacja wykonania programu, 149
modyfikacja wartości zmiennych, 148 H
podgląd wartości zmiennych, 148
hierarchia obiektów, 102
w Visual Studio, 146
deklaracja I
tablic, 113
indeks, 113
zmiennych, 67
informacja, 45
destruktor, 134
instalacja
diagram klas, 57
Unity, 13
dodanie
Visual Studio, 13
parametru do komponentu, 29
instrukcja
własnego komponentu, 28
break, 143
dokumentacja, 53
continue, 144
fabuła gry, 57
switch, 143
mechanika gry, 56
instrukcje warunkowe, 75, 95
projektowa, 56

Kup książkę Poleć książkę


172 Unity i C#. Podstawy programowania gier

K O
klasa, 30, 32, 89 obiekty, 32, 72
GameObject, 103 aktywność, 103
OpelAstra, 72 na scenie, 32
String, 145 obracanie, 64
StringBuilder, 145 tworzenie, 92
klasy zwracanie, 139
dziedziczenie, 89 okna Unity
ogólne, 89 główne, 18
szczegółowe, 89 podstawowe, 22
kolejność obliczeń, 96 okno
kolekcje, 113 hierarchii obiektów, 18
komentarze, 29 inspektora, 18, 24
kompilacja projektu, 34 kompilacji, 59
w Unity, 58 widoku sceny, 18
w Visual Studio, 61 operator
komponent, 30, 32 !, 96
Collider, 27 !=, 76
Renderer, 27 ||, 68
Rigidbody, 27 <, 76
Transform, 26 <=, 76
komponenty ==, 76
ogólne, 25 >, 76
Unity, 100 >=, 76
konstruktor, 133 &&, 68
domyślny, 134 as, 94
przeciążanie, 135 is, 95
konwersja liczb, 146 otwieranie projektu, 20

M P
metoda ToString, 146 pętla
metodologia for, 115, 116, 125
Scrum, 54 foreach, 119, 126
tradycyjna, 54 while, 123, 126
zwinna, 54 pętle
metody, 71 instrukcja break, 144
przeciążanie, 134 instrukcja continue, 144
klasy String, 145 pierwszy
modyfikacja komponent, 28
obiektów, 24 projekt, 17
wartości zmiennych, 148 skrypt, 28
modyfikator platforma .NET, 17
out, 139, 140 plik
ref, 140 DoDestrukcji.cs, 131
Doniczka.cs, 80, 106, 128, 159
GlownySkrypt.cs, 150, 152
GlownySkryptPoprawnie.cs, 151, 154

Kup książkę Poleć książkę


Skorowidz 173

Gracz.cs, 77, 79, 82, 86, 98, 105, 127, 131 pseudokod, 53
Jablko.cs, 99 pułapka w kodzie, 147, Patrz także
Klikacz.cs, 122, 125 debugowanie
KomponentGracza.cs, 109, 119, 121
KomponentZLiczbaCalkowita.cs, 78 R
KomponentZLiczbaZmiennoprzecinkowa.cs, ramki graficzne, 100
78 refaktoryzacja, 82
KomponentZPolemBool.cs, 78 rola
KomponentZPolemObiektowym.cs, 87 Analityk, 54
Konewka.cs, 85, 108 Designer, 55
Owoc.cs, 99 Dokumentalista, 55
Pojemnik.cs, 110 Lider zespołu, 56
Sadzonka.cs, 80, 84, 107, 155 Menedżer, 56
pliki Programista, 55
bibliotek, 59 Projektant, 55
projektu, 60 Tester, 55
podgląd wartości zmiennych, 148 Wdrożeniowiec, 55
pola klasy, 71 rozciąganie obiektu, 64
dostępność, 138 rozwiązania, 60
statyczne, 141 rzutowanie
String, 145 typów, 66
użycie, 137 typów obiektowych, 94
widoczność, 138 typu enum, 162
pomoc techniczna, 163 zmiennych, 69
prefabrykaty, 23, 32
programowanie S
ekstremalne, 54 scena, 23
komponentów Unity, 100 3D, 63
projekt otwieranie, 36
FixMe1, 150 przesuwanie, 63
FixMe2, 152 zmiana pozycji obiektu, 102
ObjectClicker, 122 schemat blokowy, 51, 52
ProjektRosliny, 79, 104, 126, 155 Scrum, 54
Tanks!, 169 skalowanie obiektu, 64
przeciążanie skok warunkowy, 143
konstruktorów, 135 słowo kluczowe
metod, 134 break, 143
przekazanie parametrów do funkcji, 70, 139 continue, 144
modyfikator out, 139 if, 75
modyfikator ref, 140 new, 92
przestrzenie nazw, 142 null, 76, 93
przesuwanie private, 91
obiektu, 63 protected, 91
sceny, 63 public, 91
przybornik narzędzi, 63 static, 141
przyciąganie podczas przesuwania, 64 this, 93
przypadki użycia, 57 using, 142

Kup książkę Poleć książkę


174 Unity i C#. Podstawy programowania gier

sortowanie, 117 pola statycznego, 141


specyfikacja, Patrz także dokumentacja przestrzeni nazw, 142
wewnętrzna programu, 56 tablic, 113
zewnętrzna programu, 57 typu string, 145
stos wywołań, 148 typu wyliczeniowego, 162
szybkie GUI, 102 zmiennych, 67, 68

T V
tablice, 113 Visual Studio, 17
deklaracja, 113
sortowanie elementów, 117 W
użycie, 114 wartość null, 76, 93
tworzenie warunek, 75
gier i programów, 53 widoczność
obiektów, 92 metod i pól, 91
projektu, 17 zmiennych, 136
typ danych wyszukiwanie błędów, 147
bool, 66, 68 wyszukiwarka zasobów, 166
float, 66, 67 wywołania
enum, 161 przeciążonej metody, 135
int, 66 wielokrotne, 92
obiektowy, 92
string, 144 Z
typy zagnieżdżanie warunków, 95
proste, 66 zakładka Project, 19
wyliczeniowe, 161 zakup zasobów, 165
zasoby, 23, 32
U zmienne, 66
UML, Unified Modeling Language, 57 modyfikacja wartości, 148
Unity, 17 podgląd wartości, 148
Unity Asset Store, 165 typu obiektowego, 73
uruchomienie użycie, 67
gry, 25 zwracanie obiektu, 139
Visual Studio, 19
uzyskiwanie pomocy, 165
użycie
dokumentacji technicznej, 163
funkcji OnCollisionEnter, 31
gotowego kodu, 167
instrukcji break, 144
instrukcji continue, 144
instrukcji switch, 143
klasy StringBuilder, 146
modyfikatora out, 140
pętli for, 117
pętli while, 123
pola klasy, 72, 137

Kup książkę Poleć książkę


Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej
publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną,
fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym
powoduje naruszenie praw autorskich niniejszej publikacji.

Wszystkie znaki występujące w tekście są zastrzeżonymi znakami


firmowymi bądź towarowymi ich właścicieli.

Autor oraz Wydawnictwo HELION dołożyli wszelkich starań, by zawarte w tej książce informacje
były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie,
ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz
Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody
wynikłe z wykorzystania informacji zawartych w książce.

Redaktor prowadzący: Małgorzata Kulik

Projekt okładki: Studio Gravite / Olsztyn


Obarek, Pokoński, Pazdrijowski, Zaprucki

Grafika na okładce została wykorzystana za zgodą Shutterstock.com

Wydawnictwo HELION
ul. Kościuszki 1c, 44-100 GLIWICE
tel. 32 231 22 19, 32 230 98 63
e-mail: helion@helion.pl
WWW: http://helion.pl (księgarnia internetowa, katalog książek)

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/unityc
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

Kody źródłowe wybranych przykładów dostępne są pod adresem:


ftp://ftp.helion.pl/przyklady/unityc.zip

ISBN: 978-83-283-4390-0

Copyright © Helion 2018

Printed in Poland.

• Kup książkę • Księgarnia internetowa


• Poleć książkę • Lubię to! » Nasza społeczność
• Oceń książkę

You might also like