You are on page 1of 311

Tytuł oryginału: Practical Game Development with Unity and Blender

Tłumaczenie: Zbigniew Waśko

ISBN: 978-83-283-0272-3

© 2015 Cengage Learning PTR.

CENGAGE and CENGAGE LEARNING are registered trademarks of Cengage Learning, Inc., within the United
States and certain other jurisdictions.

ALL RIGHTS RESERVED. No part of this work covered by the copyright herein may be reproduced,
transmitted, stored, or used in any form or by any means graphic, electronic, or mechanical, including but not
limited to photocopying, recording, scanning, digitizing, taping, Web distribution, information networks,
or information storage and retrieval systems without the prior written permission of the publisher.

Unity is a registered trademark of Unity Technologies. Blender is a trademark of Blender. All other trademarks
are the property of their respective owners.

All images © Cengage Learning unless otherwise noted.

© 2015 Helion S.A.


All rights reserved.

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 bierze jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym
ewentualne naruszenie praw patentowych lub autorskich. Wydawnictwo HELION nie ponosi również żadnej
odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce.

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)

Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/unible.zip

Drogi Czytelniku!
Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres
http://helion.pl/user/opinie/unible_ebook
Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję.

 Poleć książkę na Facebook.com  Księgarnia internetowa


 Kup w wersji papierowej  Lubię to! » Nasza społeczność
 Oceń książkę
Książkę tę dedykuję wszystkim, którzy przyczyniają się
do powstawania wspaniałych narzędzi programistycznych dostępnych
za darmo dla szerokiej rzeszy twórców gier komputerowych na całym świecie.
P ODZIĘKOWANIA

Wielu ludzi pracowało, aby ta książka ujrzała światło dzienne i była należytej jakości.
Jestem im wszystkim bardzo wdzięczny, ale szczególnie pragnę podziękować Emi Smith
za pomoc w opracowywaniu książki i nadzorowanie całego procesu wydawniczego.
Dziękuję też Kate Shoup za jej pracę redakcyjną i wiele cennych uwag, Michaelowi
Dugganowi za fachową korektę techniczną i tym wszystkim, którzy w jakikolwiek sposób
przyczynili się do powstania tej publikacji. Jest ich zbyt wielu, aby każdego wymienić
z osobna. Oczywiście chciałbym podziękować również Tobie, drogi Czytelniku, za za-
interesowanie tworzeniem gier i wybranie mojej książki jako źródła wiedzy na ten temat.
Mam nadzieję, że okaże się przydatna.

Alan Thorn
Londyn 2014
S PIS TREŚCI

O autorze .....................................................................................................................11
Wstęp . .........................................................................................................................13
Niezbędne oprogramowanie ...................................................................................................................14
Czytelnik docelowy ......................................................................................................................................15
Czy taka książka jest rzeczywiście potrzebna? ...................................................................................17
Czy w tej książce jest wszystko na temat tworzenia gier? .............................................................17
Jak należy czytać tę książkę? ....................................................................................................................18
Czy ta książka jest jeszcze aktualna? ......................................................................................................19
Dziesięcioetapowy tok pracy ...................................................................................................................19
Pliki powiązane z książką ...........................................................................................................................20

Rozdział 1. Dziesięcioetapowy tok pracy . ................................................................21


Wprowadzenie do dziesięcioetapowego toku pracy ......................................................................22
Etap 1. Burza mózgów ................................................................................................................................24
Etap 2. Projekt wstępny ..............................................................................................................................27
Zarys gry ...................................................................................................................................................28
Opis szczegółów ....................................................................................................................................29
Załączniki .................................................................................................................................................29
Etap 3. Tworzenie prototypu ....................................................................................................................29
Etap 4. Dopracowanie projektu ..............................................................................................................30
Zarządzanie projektem ..............................................................................................................................31
Zinwentaryzuj środki ...........................................................................................................................32
Zmniejsz odległości .............................................................................................................................32
Zaplanuj pracę .......................................................................................................................................33
Etap 5. Tworzenie elementów gry ..........................................................................................................33
Etap 6. Importowanie elementów gry do silnika ..............................................................................34
Etap 7. Projektowanie poziomów ...........................................................................................................36
Etap 8. Kodowanie .......................................................................................................................................37
Etap 9. Testowanie .......................................................................................................................................39
Etap 10. Budowanie .....................................................................................................................................40
Zalecenia praktyczne ..................................................................................................................................41
Podsumowanie .............................................................................................................................................42

5
6 Spis treści

Rozdział 2. Od Blendera do Unity . ............................................................................45


Konfigurowanie interfejsu Blendera ......................................................................................................46
Ciemny motyw .......................................................................................................................................46
Etykietki bez pythonowych instrukcji ...........................................................................................48
Kontrolki z programu Maya ..............................................................................................................49
„Błąd” zamykania bez zapisu ....................................................................................................................51
Przenoszenie modeli z Blendera do Unity ...........................................................................................53
Pliki .blend ...............................................................................................................................................54
Ćwiczenie: ręczny eksport do FBX ..................................................................................................55
Zawartość pliku FBX ....................................................................................................................................70
Ćwiczenie: importowanie plików FBX w Unity ..................................................................................71
Współrzędne UV mapy światła ........................................................................................................71
Współczynnik skali ...............................................................................................................................73
Podsumowanie .............................................................................................................................................74

Rozdział 3. Modułowe środowiska i siatki statyczne . .............................................77


Zalety metody modułowej .......................................................................................................................79
Rozpoczynanie prac nad środowiskiem modułowym ...................................................................79
Używanie klocka podstawowego ...........................................................................................................83
Opracowywanie modułów w Blenderze ..............................................................................................83
Odwracanie normalnych ....................................................................................................................84
Ukrywanie ścianek odwróconych tyłem . .....................................................................................85
Funkcja przyciągania ...........................................................................................................................85
N-kąty ........................................................................................................................................................88
Wyszukiwanie n-kątów .......................................................................................................................91
Cofanie operacji i usuwanie duplikatów ......................................................................................92
Mirroring ..................................................................................................................................................93
Grupowanie wierzchołków ...............................................................................................................94
Parametry wyświetlania siatki ..........................................................................................................97
Mapowanie UV i tworzenie tekstur ........................................................................................................98
Wyznaczanie szwów, mapowanie UV i modelowanie ............................................................98
Atlas tekstur i pokrywanie się współrzędnych UV ................................................................. 100
Ustalanie gęstości tekselowej . ..................................................................................................... 102
Importowanie i konfigurowanie środowisk w Unity .................................................................... 104
Stosowanie prefabrykatów . .................................................................................................................. 107
Wsad statyczny . ......................................................................................................................................... 109
Podsumowanie . ........................................................................................................................................ 109

Rozdział 4 . Teren ..................................................................................................... 111


Tworzenie terenu w Unity . .................................................................................................................... 111
Parametry terenu . ............................................................................................................................. 113
Rzeźbienie terenu . ............................................................................................................................ 114
Malowanie terenu teksturami . ..................................................................................................... 115
Ocena terenów generowanych przez Unity . .................................................................................. 118
Spis treści 7

Modelowanie terenu w Blenderze . .................................................................................................... 119


Metoda edycji proporcjonalnej .................................................................................................... 121
Metoda tekstury przemieszczeń .................................................................................................. 124
Metoda rzeźbienia . ........................................................................................................................... 127
Rozdzielczość terenu . .............................................................................................................................. 130
Malowanie terenu teksturą . .................................................................................................................. 131
Wyznaczanie współrzędnych UV terenu . ................................................................................. 132
Generowanie tekstury . .................................................................................................................... 132
Malowanie w oknie UV/Image Editor . ....................................................................................... 134
Malowanie w oknie 3D View . ........................................................................................................ 138
Malowanie teksturami . ................................................................................................................... 140
Tworzenie dróg i ścieżek . ....................................................................................................................... 143
Modelowanie dróg ............................................................................................................................ 144
Podsumowanie . ........................................................................................................................................ 148

Rozdział 5 . Tok pracy animacyjnej ........................................................................ 149


Klatka kluczowa jako jednostka animacji . ....................................................................................... 150
Przygotowanie Blendera do tworzenia animacji . ......................................................................... 151
Wykorzystaj specjalny, animacyjny układ interfejsu Blendera .......................................... 152
Uważaj na automatyczne kluczowanie . .................................................................................... 152
Wstawiaj pojedyncze klatki kluczowe . ...................................................................................... 153
Długość animacji . .............................................................................................................................. 155
Eksportowanie animacji do formatu FBX . ................................................................................ 156
Praca z wieloma animacjami . ....................................................................................................... 156
Prosta animacja kluczowana — od Blendera do Unity . ............................................................. 158
Animowanie ruchu wzdłuż ścieżki i wypalanie animacji . .......................................................... 166
Miksowanie kształtów i klucze kształtu . ........................................................................................... 172
Kości i rigowanie . ...................................................................................................................................... 177
Zawsze nadawaj nazwy poszczególnym kościom . ............................................................... 178
Szkielety symetryczne a funkcja X-Axis Mirror ........................................................................ 178
Kinematyka prosta i odwrotna . .................................................................................................... 180
Kości deformowane i sterujące . ................................................................................................... 182
Eksportowanie zrigowanych postaci .......................................................................................... 182
Importowanie zrigowanych postaci do Unity ......................................................................... 184
Podsumowanie .......................................................................................................................................... 186

Rozdział 6. Obiekty, zależności i programowanie zdarzeniowe . ........................ 187


Zależności zaprogramowane . .............................................................................................................. 188
Rozwiązanie DI — projektowanie komponentowe i komunikaty ........................................... 190
Projektowanie komponentowe . .................................................................................................. 190
Komunikaty . ........................................................................................................................................ 191
Funkcja BroadcastMessage i hierarchie . .......................................................................................... 194
Wysyłanie komunikatów do wybranych obiektów ....................................................................... 195
Wysyłanie komunikatów do obiektów nadrzędnych ................................................................... 197
8 Spis treści

System powiadomień .............................................................................................................................. 197


NotificationsManager w szczegółach ................................................................................................ 200
Singletony .................................................................................................................................................... 201
Komunikaty a obiekty aktywne ............................................................................................................ 202
Przemierzanie hierarchii obiektów ..................................................................................................... 203
Podsumowanie . ........................................................................................................................................ 204

Rozdział 7. Retopologizacja ................................................................................... 205


Siatki high-poly, czyli o dużej gęstości . ............................................................................................ 206
Siatki wysokorozdzielcze a gry czasu rzeczywistego ................................................................... 208
Retopologizacja w praktyce . ................................................................................................................ 209
Etap 1. Wymodeluj metodą pudełkową wstępną wersję obiektu ................................... 209
Etap 2. Zwiększ rozdzielczość siatki . .......................................................................................... 212
Etap 3. Rzeźbij i dziel . ....................................................................................................................... 216
Etap 4. Retopologizuj . ..................................................................................................................... 221
Dziesiątkowanie ......................................................................................................................................... 231
Podsumowanie .......................................................................................................................................... 234

Rozdział 8 . Zapisywanie stanu gry a trwałość danych . ....................................... 235


Dane trwałe . ............................................................................................................................................... 236
Preferencje gracza . ................................................................................................................................... 237
Preferencje gracza — ciąg dalszy ........................................................................................................ 238
Wybieranie danych trwałych . ............................................................................................................... 239
Pliki XML — a może JSON lub binarne . ............................................................................................ 240
Pliki JSON . ............................................................................................................................................ 241
Pliki binarne . ....................................................................................................................................... 241
Serializacja klasy . ....................................................................................................................................... 242
Przygotowanie danych do serializacji ................................................................................................ 243
Przesyłanie danych do pliku XML ........................................................................................................ 245
Odczytywanie danych z pliku XML ..................................................................................................... 246
Dodatkowe uwagi na temat klasy SaveState .................................................................................. 248
Podsumowanie .......................................................................................................................................... 249

Rozdział 9 . Wypalanie ............................................................................................ 251


Czym jest wypalanie? . ............................................................................................................................. 252
Wypalanie oświetlenia statycznego . ......................................................................................... 252
Wypalanie oświetlenia dynamicznego . .................................................................................... 252
Wypalanie nawigacji . ....................................................................................................................... 253
Przygotowanie mapowania światła w Unity ................................................................................... 255
Mapowanie światła. Rozdzielczość mapy światła . ........................................................................ 257
Tryb mapowania światła . ....................................................................................................................... 259
Oświetlenie pośrednie i okluzja otoczenia . .................................................................................... 260
Wypalanie map światła . ......................................................................................................................... 263
Wypalanie map w Blenderze . ............................................................................................................... 265
Spis treści 9

Komponowanie renderingów w GIMP-ie . ....................................................................................... 271


Wypalanie oświetlenia dynamicznego z użyciem próbników światła ................................... 274
Wypalanie nawigacji . .............................................................................................................................. 278
Podsumowanie . ........................................................................................................................................ 285

Rozdział 10 . Unity, Blender i inne programy . ...................................................... 287


Inne programy . .......................................................................................................................................... 287
MakeHuman . .............................................................................................................................................. 288
GIMP . ............................................................................................................................................................. 288
Inkscape . ...................................................................................................................................................... 290
MyPaint i Krita . ........................................................................................................................................... 292
Synfig Studio . ............................................................................................................................................. 293
Tiled . .............................................................................................................................................................. 293
MonoDevelop . ........................................................................................................................................... 294
BMFont . ........................................................................................................................................................ 295
TexturePacker . ........................................................................................................................................... 296
LibreOffice . .................................................................................................................................................. 297
Anime Studio Pro ...................................................................................................................................... 298
Audacity ........................................................................................................................................................ 298
SFXR . .............................................................................................................................................................. 299
Podsumowanie . ........................................................................................................................................ 300

Dodatek A Inne źródła wiedzy ............................................................................... 301


Witryny internetowe ................................................................................................................................ 301
Książki . .......................................................................................................................................................... 302
Filmy wideo . ............................................................................................................................................... 302

Skorowidz . .............................................................................................................. 303


10 Spis treści
O AUTORZE

Alan Thorn jest niezależnym twórcą gier z ponad 12-letnim doświadczeniem w tej dzie-
dzinie. Jest założycielem londyńskiej wytwórni Wax Lyrical Games i autorem nagradza-
nej wielokrotnie gry przygodowej Baron Wittard: Nemesis of Ragnarok. Jako wolny
strzelec brał udział w realizacji ponad 500 projektów, wśród których były nie tylko gry,
ale również symulatory, infokioski i systemy poszerzonej rzeczywistości przeznaczone
dla wytwórni gier, muzeów i tematycznych parków rozrywki.
Przemawiał na wielu konferencjach poświęconych tworzeniu gier i napisał kilkanaście
książek o tej tematyce, m.in.: Teach Yourself Games Programming, Unity 4 Fundamentals
i UDK Game Development. Obecnie pracuje nad mającą się wkrótce ukazać grą zatytu-
łowaną Mega Bad Code. Więcej informacji o Alanie Thornie i jego firmie Wax Lyrical
Games znajdziesz na stronach: www.alanthorn.net i www.waxlyricalgames.com.

11
12 O autorze
W STĘP

Tematem tej książki jest tworzenie gier komputerowych. Ma ona charakter praktyczny
i holistyczny. Jest holistyczna, ponieważ dotyka niemal wszystkich dyscyplin, które
bezpośrednio wiążą się z grami komputerowymi, od programowania i projektowania
poziomów aż po modelowanie 3D i edycję obrazów cyfrowych. Opisuje też wiele pro-
gramów, głównie Unity i Blender, ale jest w niej mowa również o GIMP-ie i innych
tego typu narzędziach.
Praktyczność tej książki przejawia się w dwóch aspektach:
■ Czytelnik nie tylko przyswaja przekazywaną mu wiedzę, ale dzięki zamieszczonym
wskazówkom może również sprawdzić ją w praktyce.
■ Zagadnienia, programy i pomysły są prezentowane w sposób podkreślający ich
rzeczywiste znaczenie dla twórców gier. Teoria jest przywoływana tylko w takim
wymiarze, jaki jest konieczny do zrozumienia omawianych treści i do pełniejszego
wykorzystania dostępnych narzędzi.
Nie będziemy się zajmowali rozwiązywaniem abstrakcyjnych problemów matema-
tycznych ani roztrząsaniem tego, co jest tylko potencjalnie możliwe; zostawimy to in-
nym książkom i publikacjom. Krótko mówiąc: istotna będzie dla nas tylko ta wiedza,
która może dać konkretne rezultaty praktyczne i którą można zastosować w pracy
z dostępnymi obecnie narzędziami. Jest to wiedza, której możesz użyć tu i teraz, a także
w najbliższej, dającej się przewidzieć przyszłości.
Chcę jednak podkreślić, że mimo swojego holistycznego i praktycznego charakteru
książka ta nie jest typowym poradnikiem pokazującym krok po kroku, jak stworzyć grę
komputerową. Pisząc ją, zakładałem, że czytelnik ma już pewną wiedzę na temat gier
i ich tworzenia, że przynajmniej ogólnie zna stosowane w tej branży narzędzia i techniki.
Moim zamiarem było napisanie książki dla tych, którzy chcieliby się zająć tworzeniem
gier i szukają konkretnych przykładów pokazujących, jak te wszystkie narzędzia, pro-
cedury, pomysły i projekty połączyć w jedną całość i nadać im określony realny wymiar.

13
14 Wstęp

Podręcznik użytkowania programu Unity uczy posługiwania się programem Unity, pod-
ręcznik użytkowania Blendera uczy posługiwania się Blenderem, ale ta książka po-
winna być traktowana jako podręcznik wyższego rzędu. Jej zadaniem jest pokazanie, jak
używając wielu narzędzi, osiągnąć zamierzony rezultat. Opanowanie takiej umiejętności
jest niezwykle ważne i daje swoiste poczucie pewności siebie. A przede wszystkim skłania
do patrzenia na tworzenie gier jak na dziedzinę wielodyscyplinarną. Przez dostrzeganie
współzależności między poszczególnymi narzędziami i technikami oraz przez naby-
wanie biegłości w ich stosowaniu wprowadzasz do swej pracy pewien stopień racjonalno-
ści. Ma to znaczenie nie tylko wtedy, gdy zamierzasz kierować zespołami ludzi realizu-
jącymi konkretne projekty, ale również gdy planujesz pracować w małym zespole
bądź samodzielnie i musisz wszystko sam kontrolować. A zatem celem tej książki nie jest
nauczenie Cię obsługi takich czy innych narzędzi bądź stosowania takich czy innych
technik, lecz uczynienie z Ciebie sprawniejszego twórcy gier.

Niezbędne oprogramowanie
W książce poświęconej tworzeniu gier komputerowych programy muszą grać ważną
rolę. Dlatego większą jej część poświęciłem na opis niezbędnych aplikacji i sposobów
ich użytkowania. Obecnie twórcy gier posługują się tak wielką liczbą rozmaitych pro-
gramów, że opisanie wszystkich byłoby niemożliwe, ale i nie jest też potrzebne. Trzeba
jednak dokonać selekcji. Ja wybrałem Unity i Blendera. Przyjrzymy się również, choć
bardziej pobieżnie, GIMP-owi i jeszcze paru innym aplikacjom. Jeśli nie znasz tych narzę-
dzi, zapoznaj się z nimi. Oto ich strony internetowe:
■ Unity. Jest to silnik gier komputerowych. Więcej informacji znajdziesz pod adresem:
https://unity3d.com/.
■ Blender. Jest to program do modelowania 3D i animowania. Możesz go pobrać ze
strony: www.blender.org.
■ GIMP. Jest to aplikacja służąca do edycji obrazów cyfrowych. Możesz ją pobrać ze
strony: www.gimp.org.
Dlaczego wybrałem te programy, a nie inne? Odpowiedź jest wielopłaszczyznowa:
■ Wymienione programy są całkowicie darmowe (Unity istnieje też w wersji darmowej!).
Możesz więc je natychmiast pobrać i używać beż żadnych opłat. Oczywiście musisz
zainwestować w komputer, połączenie internetowe i naukę obsługi tych narzędzi, ale
same programy nie kosztują nic.
■ Programy te są bardzo rozbudowane i ciągle się rozwijają. Nie tylko ja uważam je za
pełnowartościowe! Są używane przez wiele firm i przyczyniły się do powstania setek
gier komercyjnych, freemiumowych czy darmowych. Przykładami niech będą Yo
Frankie! i Dead Cyborg.
Czytelnik docelowy 15

■ Są to narzędzia ciągle rozwijane i doskonalone przez liczną społeczność zapaleń-


ców. Są też nieźle udokumentowane, a to zawsze daje pewien komfort wynikający
z przekonania, że jeśli podczas użytkowania napotkamy jakiś problem, to rozwiązanie
będzie dostępne w sieci, bo ktoś już je znalazł i opisał.
■ Dzięki temu, że programy te są całkowicie bezpłatne, książka staje się przydatna
dla szerszego grona czytelników. Używać ich może każdy niezależnie od zasobności
portfela.
Mój wybór nie powinien być odczytywany jako negatywna opinia o pozostałych pro-
gramach. Jest wiele aplikacji komercyjnych (Photoshop, Maya, 3DS Max, Strata, ZBrush,
Mudbox i inne), o których nie wspominam, ale nie dlatego, że uważam je za złe. Abso-
lutnie nie. Pomijam je tylko z tego powodu, że ich ceny są poza zasięgiem wielu małych
zespołów i niezależnych twórców gier, a to właśnie do nich przede wszystkim kieruję tę
książkę.
Mam nadzieję, że ta książka przekona Cię (jeśli jeszcze trzeba Cię przekonywać), że
tak naprawdę znaczenie ma nastawienie samego twórcy, jego wyobraźnia, umiejętności
i kreatywność, a nie narzędzia, których używa. Narzędzia mogą mieć znaczenie, gdy
w grę wchodzi wygoda i szybkość pracy, a także gdy trzeba współpracować z ludźmi
używającymi innych narzędzi, ale o ostatecznym wyniku i tak zdecydują Twoje umie-
jętności i determinacja. Największe dzieła tworzą ci, którzy mają talent i umiejętności,
a przy tym potrafią posługiwać się wieloma narzędziami, zarówno tymi darmowymi,
jak i komercyjnymi. Nic nie stoi na przeszkodzie, abyś za pomocą narzędzi całkowicie
darmowych stworzył grę na profesjonalnym poziomie. Przez poziom profesjonalny ro-
zumiem taki, który pozwoli produktowi zwrócić na siebie uwagę szerszej rzeszy klien-
tów. Tak, używając takich narzędzi, możesz stworzyć grę, która będzie się sprzedawać!

Czytelnik docelowy
Każda książka ma swojego czytelnika docelowego i ta wcale nie jest inna. Krótko mówiąc:
jeśli myślisz o tworzeniu gier, ale nie masz pieniędzy na drogie programy i chciałbyś
zobaczyć na konkretnych przykładach (ze szczegółowymi podpowiedziami i wskazów-
kami), jak mimo to można takie rzeczy robić, to ta książka jest prawdopodobnie dla Ciebie.
Jeśli masz znakomity pomysł na grę, lubisz pracować samodzielnie i zrobisz wiele, by
zrealizować swoją wizję, to tym bardziej ta książka jest dla Ciebie.
Takich ludzi jest dość dużo. Są wśród nich studenci, hobbyści, niezależni twórcy, pra-
cownicy średnich i małych firm, projektanci indywidualni, a nawet doświadczeni twórcy
gier chcący poszerzać swoje umiejętności przez sięganie po nieznane jeszcze narzędzia
i techniki. Gdziekolwiek jesteś w tym szerokim spektrum, na pewno dostrzeżesz i doce-
nisz wielodyscyplinarny charakter tej książki. Jest to odzwierciedleniem wymagań, jakie
są stawiane profesjonalistom przez współczesny przemysł gier komputerowych. Dużą
wszechstronnością muszą się wykazać głównie twórcy pracujący w małych i średnich
zespołach.
16 Wstęp

Tworzenie gier komputerowych jest dyscypliną techniczną obejmującą wiele rozma-


itych dziedzin, takich jak: programowanie, fizyka, sztuczna inteligencja, grafika, mo-
delowanie 3D, animacja, nagrywanie muzyki, testowanie oprogramowania itp. Dlatego
w małych studiach o niewielkich budżetach szybko okazuje się, że pracownicy muszą być
niemalże omnibusami. W zespołach naprawdę małych (jedno- lub dwuosobowych)
wszechstronność jest wręcz konieczna. I to właśnie do takich małych i średnich zespołów
kieruję tę książkę.
A zatem oznacza to, że z książki tej nie dowiesz się, jak zostać „ekspertem” w jednej
dziedzinie, ale raczej jak zdobyć wszechstronność — bez której niezależny twórca ma
małe szanse na sukces. Książka jest o tym, jak zostać „ekspertem od wszystkiego” lub
„specjalistą w każdej dziedzinie”. Nauczysz się trochę programowania, projektowania
poziomów, modelowania w trzech wymiarach, animowania i wielu innych rzeczy. Nie
jest to łatwe, ale musisz pójść tą ścieżką, jeśli masz zamiar uczynić tworzenie gier swoim
zajęciem etatowym na dłuższy czas.
Oczywiście nauka nie skończy się na lekturze tej książki. To musi być proces ustawiczny.
Celem mojej książki jest jedynie pokazanie, od czego i jak zacząć tworzenie gier.
Obecnie bardziej niż kiedykolwiek wcześniej do głosu dochodzą małe zespoły i twórcy
indywidualni. Coraz częściej właśnie tacy wszechstronnie przygotowani indywidualiści
odnoszą komercyjne sukcesy, tworząc gry na różne platformy, a zwłaszcza na kom-
putery stacjonarne i urządzenia mobilne. Możesz być jednym z nich. Z tej książki do-
wiesz się, od czego i jak zacząć.
Napisałem, dla kogo jest ta książka, ale czy jest ktoś, kto nie odniesie żadnej korzyści
z jej przeczytania? Chociaż nie jest moim zamiarem odwodzenie kogokolwiek od
czytania, wymienię dwie grupy czytelników, którzy najprawdopodobniej nie uznają tej
książki za szczególnie przydatną. Pierwszą stanowią ci, którzy nigdy wcześniej nie in-
teresowali się tworzeniem gier — nigdy nie programowali, nie zajmowali się grafiką
komputerową i nawet nie zastanawiali się, jak gry działają. Z pewnością każdy kiedyś
musi zacząć się uczyć, ale ta książka nie będzie chyba najlepszym źródłem umiejętności
dla takich ludzi, przy jej pisaniu zakładałem bowiem, że czytelnik dysponuje już pewnym
zasobem wiedzy i nie muszę wszystkiego tłumaczyć od podstaw. Mam tu na myśli
elementarne rozumienie, czym jest silnik gry i jak się do niego mają te wszystkie na-
rzędzia służące do tworzenia wizualnej strony gry, jak chociażby programy do mode-
lowania obiektów 3D. Założyłem również pewną znajomość języków programowania
(najlepiej C#, JavaScript lub C++) i obycie z elementarnymi pojęciami grafiki 3D, takimi
jak wierzchołek, krawędź czy wielokąt. Jeśli nie masz takiej wiedzy, sięgnij najpierw po
inne książki, jak chociażby te, które wymieniłem w dodatku A.
Do drugiej grupy zaliczam tych, którzy są już twórcami gier, ale chcą zostać ekspertami
i szukają wiedzy specjalistycznej z jednej tylko dziedziny, np. z programowania grafiki
trójwymiarowej. Przykładowo: jeśli widzisz siebie wyłącznie jako programistę lub je-
dynie artystę i szukasz publikacji poświęconej tylko tej jednej dziedzinie, moja książka
Czy taka książka jest rzeczywiście potrzebna? 17

prawdopodobnie nie da Ci tego, czego oczekujesz. Jak już wspominałem, napisałem ją


głównie z myślą o uniwersalistach, a nie specjalistach. Oczywiście tak naprawdę nie
wierzę, że nie można jednego z drugim połączyć. Nie są to przecież rzeczy, które by się
wzajemnie wykluczały. Możesz być specjalistą w jednej dziedzinie i jednocześnie mieć
rozległą wiedzę w wielu innych obszarach. Ale wtedy z tej książki skorzystasz tylko
połowicznie — jako uniwersalista.

Czy taka książka jest rzeczywiście potrzebna?


Książka ta ma szczególną wartość głównie ze względu na całościowe podejście do tematu.
Przy ciągle rosnącej liczbie małych zespołów i indywidualistów pragnących tworzyć gry
rośnie też zapotrzebowanie na źródła wiedzy całościowej — takiej, która pozwala swo-
bodnie operować rozmaitymi narzędziami i wykonywać najróżniejsze zadania, aby jed-
noosobowo lub w małej grupie stworzyć grę od początku do końca. Jeśli efektem
końcowym ma być produkt rynkowy, a cały proces produkcyjny ma się zamknąć w okre-
ślonych ramach czasowych i budżetowych, ludzie ci muszą opanować bogaty arsenał
umiejętności z wielu różnych dziedzin.
Oczywiście można taką wiedzę zdobyć, ucząc się na własnych błędach i studiując rozma-
ite książki czy poradniki. I rzeczywiście, część arsenału trzeba zgromadzić w ten sposób.
Ale jeśli masz być uniwersalistą, ta książka może Ci bardzo pomóc. Dlaczego? Bo pisałem
ją z myślą właśnie o takim odbiorcy. Omawiam w niej problemy, które napotykają
twórcy gier, a które można rozwiązać pod warunkiem, że ma się kosztowne zaplecze
specjalistów lub jest się osobą wszechstronnie przygotowaną.
Jeśli chcesz tworzyć gry z prawdziwego zdarzenia, a nie masz licznego zespołu specja-
listów, musisz sam stać się uniwersalistą — takim „szwajcarskim scyzorykiem”. W tej
książce znajdziesz mnóstwo wskazówek podpowiadających, jak to osiągnąć — by móc
swobodnie zmieniać tryby pracy i wykonywać to, co na danym etapie procesu produk-
cyjnego jest niezbędne. Pomoże Ci to zaoszczędzić mnóstwo pieniędzy i innych zasobów,
bo nie będziesz musiał zatrudniać innych, żeby zrobili to, co przecież możesz zrobić
sam. Poza tym, jako człowiek o wszechstronnej wiedzy i szerokim zakresie umiejętności,
łatwiej znajdziesz zatrudnienie, zwłaszcza w branży gier niezależnych. Łatwiej Ci też
będzie poprowadzić własny biznes w tej branży, bo będziesz doskonale wiedział, jak mają
wyglądać poszczególne etapy procesu produkcyjnego i co jest potrzebne, aby wszystko
przebiegało bez większych zakłóceń.

Czy w tej książce jest wszystko na temat tworzenia gier?


Jeśli weźmiesz jakąkolwiek książkę o tematyce komputerowej i przejrzysz w internecie jej
recenzje, zobaczysz, że pewien zarzut jest wciąż powtarzany, a wygląda to mniej więcej tak:
Książka nie jest wyczerpująca. Pewne rzeczy są w niej pominięte. Wszystko, co zawiera,
można za darmo znaleźć w internecie.
18 Wstęp

Chciałbym się od razu rozprawić z takim zarzutem w odniesieniu do mojej książki.


Owszem, książka ta nie zawiera wszystkiego, co trzeba wiedzieć na temat tworzenia
gier. Nie zawiera też wszystkiego, co można by powiedzieć o współpracy Blendera i Uni-
ty. Z prostej przyczyny: w żadnej książce, w żadnym filmie, kursie czy poradniku nie
da się zawrzeć tego wszystkiego. Możliwości wykorzystania tych narzędzi są wprost
nieograniczone, tak jak nieograniczone są możliwości posługiwania się pędzlem ma-
larskim czy dłutem rzeźbiarskim.
Nie zamierzałem napisać szczegółowej recepty na tworzenie gier, a raczej starałem się
podać praktyczne wskazówki, jakie mi się nasuwają po ponad 12 latach działalności
w tej branży. Każdą osobiście przetestowałem i mogę zapewnić, że wszystkie przyczyniły
się wydatnie do osiągnięcia sukcesu przy produkcji gier zarówno w moich własnych
firmach, jak i u moich klientów.
Tak, prawie wszystkiego, co jest w tej książce (ale chyba nie zupełnie wszystkiego),
można się nauczyć za darmo online. Jednak nikogo nie powinno to dziwić, ani tym
bardziej nie powinno być powodem do krytykowania. Tworzenie gier jest dziedziną łą-
czącą naukę ze sztuką. Nie jest to wcale jakaś tajemna wiedza, do której dostęp mogą
mieć tylko nieliczni. Niemal wszystko, co tutaj piszę, zostało już w takiej czy innej formie
powiedziane lub napisane. Wartością tej książki nie jest oryginalność tego, co napisa-
łem, lecz sposobu, w jaki to zaprezentowałem. Możesz się tego wszystkiego nauczyć,
przeglądając internet przez wiele dni, tygodni, a może nawet miesięcy, ale możesz też po
prostu przeczytać tę książkę.
Jej szczególna wartość bierze się stąd, że zawiera to, do czego sam, niekiedy z wielkim
trudem, doszedłem. Całą swoją wiedzę zawarłem w jednej poręcznej publikacji i na-
dałem jej formę jak najbardziej przejrzystą, łatwo przyswajalną i zapadającą w pamięć.
Nie jest to oczywiście wiedza kompletna ani tym bardziej ezoteryczna. Niemniej jednak
sądzę, że dzięki tej książce Twoja nauka i praca mogą przebiegać sprawniej i szybciej.

Jak należy czytać tę książkę?


Książka jest tak napisana, że można ją czytać podręcznikowo lub selektywnie. Czytel-
nicy podręcznikowi chcą przyswajać sobie nowe rzeczy stopniowo, jak na lekcjach
w szkole, zapoznając się z każdym tematem oddzielnie. Taki czytelnik podchodzi do
książki w sposób systematyczny i czyta ją od początku do końca, rozdział za rozdziałem.
Natomiast zwolennik czytania selektywnego często korzysta ze skorowidza i stosuje tech-
niki szybkiego czytania, aby jak najprędzej pozyskać wiedzę na temat, który go w danej
chwili interesuje; często też wraca do tych samych miejsc, żeby zweryfikować jakieś
szczegóły.
Tę książkę można czytać na oba sposoby, ale moim zdaniem najwięcej pożytku odnie-
siesz, wybierając metodę podręcznikową. Jeśli będziesz czytał w sposób uporządkowany
i systematyczny, zetkniesz się z tematami, które przy czytaniu selektywnym uszłyby
Czy ta książka jest jeszcze aktualna? 19

Twojej uwadze, bo może już je znasz albo uważasz za mało istotne, a które jednak mogą
zawierać „perełki”, o jakich nie miałeś pojęcia. Czasami nawet pozornie drobna infor-
macja może się okazać niezwykle cenna. Ponieważ zależy mi na tym, aby lektura tej
książki dała Ci jak najwięcej korzyści, proponuję, abyś przyjął strategię podręcznikową.

Czy ta książka jest jeszcze aktualna?


Prawie każda książka techniczna (jak np. ta) ma określony czas „przydatności”. Czytelnik,
sięgając po nią, zazwyczaj chce się z niej jak najwięcej dowiedzieć. I chce, żeby ta wie-
dza była obowiązująca nie tylko tu i teraz, ale również w dającej się przewidzieć przyszło-
ści. Zanim ta książka trafi do Twoich rąk, minie trochę czasu, a w branży gier kom-
puterowych czas biegnie niezwykle szybko. Rodzi się więc uzasadnione pytanie, czy
zawarte w niej treści będą jeszcze miały dla Ciebie jakąś wartość.
Trzeba też dodać, że książka jest nie tylko o metodach pracy, ale również o programach
komputerowych, a te, jak wiadomo, są ciągle rozwijane i udoskonalane. Ich twórcy
ciągle dodają nowe funkcje i usprawniają istniejące. Jest zatem niemal pewne, że gdy
pobierzesz najnowszą wersję opisanego przeze mnie programu, nie będzie on już do-
kładnie taki sam jak teraz.
Jednak kwestią zasadniczą jest, czy to ma istotny wpływ na wartość wiedzy zawartej
w książce. Na podstawie obserwacji czynionych w przeszłości mogę śmiało odpowie-
dzieć, że nie. Przecież gdyby każda modyfikacja programu obalała całą dotychczasową
wiedzę, to nikt nie byłby w stanie porządnie opanować żadnego programu. Programy
się zmieniają, ale te zmiany są zawsze wkomponowywane w istniejący już interfejs i stali
użytkownicy jakoś radzą sobie z tym bez większych problemów.
Prawdopodobnie będzie tak, że w wyniku tych zmian będziesz miał do dyspozycji
więcej opcji, ustawień i kontrolek niż ja mam teraz, ale to w żaden sposób nie prze-
szkodzi Ci w wykonywaniu opisanych przeze mnie czynności. Co więcej, będziesz mógł
przecież pójść dalej, wykorzystując funkcje, których ja jeszcze używać nie mogłem.

Dziesięcioetapowy tok pracy


Książka składa się z dziesięciu rozdziałów, a każdy z nich zawiera dokładne opisy
rozmaitych programów i technik stosowanych przy tworzeniu gier. Rozdziały są dość
zróżnicowane pod względem treści, jednakże jest jeden temat, który przewija się we
wszystkich i łączy je w spójną całość. Nazwałem go „Dziesięcioetapowy tok pracy”,
a szczegółowo opisałem w rozdziale 1., który właśnie tak zatytułowałem. W tym roz-
dziale znajdziesz dokładny opis każdego z dziesięciu etapów, przez jakie trzeba przejść,
aby pomysł zamienić w prawdziwą grę. Nie jest to żaden standard ani wymóg, ale ra-
czej rezultat moich obserwacji poczynionych w trakcie prac nad wieloma rozmaitymi
projektami w branży gier komputerowych. Oczywiście zawsze może się zdarzyć jakiś
projekt czy okoliczności, które nie będą pasować do tego dziesięcioetapowego wzorca.
20 Wstęp

Z tym trzeba się liczyć, biorąc pod uwagę wielką różnorodność współczesnych gier.
Zauważyłem jednak, że pamiętanie o tych etapach zawsze pomaga w utrzymaniu wła-
ściwego tempa prac, niezależnie od charakteru danego projektu. Do szczegółów wrócę
w rozdziale 1., a tutaj chciałem tylko zasygnalizować temat i podkreślić jego znaczenie.

Pliki powiązane z książką


Książka zawiera opisy programów komputerowych i ćwiczenia do samodzielnego
wykonania, a więc nie mogło zabraknąć plików z niezbędnymi materiałami. Znajdziesz
w nich wszystko, co jest potrzebne do przećwiczenia prezentowanych przeze mnie tech-
nik i uzyskania takich samych rezultatów, jakie pokazałem na zrzutach ekranu. Pliki po-
chodzą z wszystkich omawianych programów, czyli z Unity, Blendera, GIMP-a, Inksca-
pe’a i Audacity, a zatem żeby je otworzyć, musisz mieć te programy zainstalowane. Cały
zestaw plików ćwiczeniowych możesz pobrać ze strony: ftp://ftp.helion.pl/przyklady/
unible.zip.
R OZ DZ I AŁ 1

D ZIESIĘCIOETAPOWY
TOK PRACY

Sztuka programowania jest sztuką porządkowania złożoności…


— Edsger W. Dijkstra

Po przeczytaniu tego rozdziału:


■ zrozumiesz, na czym polega dziesięcioetapowy tok pracy;
■ będziesz umiał zastosować ten tok w swoich własnych przedsięwzięciach;
■ uświadomisz sobie znaczenie planowania i projektowania;
■ będziesz w stanie stworzyć właściwą dokumentację dla swojego przedsięwzięcia;
■ będziesz umiał zarządzać produkcją gier.
Tworzenie gier nie jest sprawą łatwą. Nieważne, czy gra wydaje się prosta, czy skom-
plikowana, zawsze jest ona rezultatem poważnego przedsięwzięcia inżynieryjnego.
Musisz to sobie uświadomić, zanim sam spróbujesz jakąś stworzyć. Nie będziesz wtedy
zaskoczony rozmiarem prac, jakie trzeba wykonać. A właśnie to zaskoczenie jest jedną
z najczęstszych przyczyn porzucania rozpoczętych przedsięwzięć — nadmiar pracy zwykle
prowadzi do zniechęcenia.
Oczywiście już samo rzucenie się w wir pracy bez żadnego planu i spędzanie długich go-
dzin i dni z kolegami lub samotnie nad grą może być ekscytującym, a nawet pouczającym
doświadczeniem, bez względu na to, czy ten wysiłek zakończy się sukcesem, czy nie.
Lecz jeśli poważnie myślisz o zarabianiu pieniędzy na tworzeniu gier, to musisz swoje
projekty doprowadzać do końca. Żaden gracz nie da ani grosza za niekompletną grę.
No, może czasem, ale nie powinieneś na to liczyć, bo takie sytuacje są naprawdę wy-
jątkowe. (Czasami gracze płacą za wersje alfa i za wersje rozwojowe, ale oczekują, że
wkrótce otrzymają dzieło ukończone). A zatem bez doprowadzenia prac do końca nie
masz co liczyć na sukces.

21
22 Rozdział 1  Dziesięcioetapowy tok pracy

Gdyby przejrzeć wszystkie projekty gier, włącznie ze „studenckimi” i z „hobbystycz-


nymi” (nie widzę powodu, dla którego mielibyśmy je pomijać), najprawdopodobniej
okazałoby się, że większość z nich nigdy nie została ukończona. Prace nad nimi zo-
stały zamrożone, wstrzymane lub przerwane. Musisz więc sprawę doprowadzenia prac
do końca potraktować bardzo poważnie. Jak to osiągnąć? Przede wszystkim przez do-
kładne poznanie wszelkich faz, przez jakie gra musi przejść w całym procesie produk-
cyjnym. Pomaga to w uzyskaniu klarownego obrazu wszystkich prac, jakie trzeba wyko-
nać na drodze od pomysłu do finalnego produktu.
Być może brzmi to zbyt naukowo i akademicko. Pewnie tak. Jednak implikacje praktyczne
takiej wiedzy są trudne do przecenienia. To one decydują, czy przedsięwzięcie jest udane,
czy nie. Dlatego w tym rozdziale przyjrzymy się dokładnie podstawowym fazom pro-
cesu tworzenia gry i ich implikacjom. Z grubsza cały ten proces można podzielić na
dziesięć etapów. Nie jest to podział ustandaryzowany ani nawet „branżowo uzgodnio-
ny” i o ile mi wiadomo, nie został jeszcze w żadnej książce opisany. Po prostu istnienie
takich właśnie faz stwierdziłem, uczestnicząc przez ostatnie 12 lat w realizacji ponad
500 projektów. Oczywiście zawsze może się zdarzyć jakiś przypadek wyjątkowy, który
nie będzie pasował do przedstawionego przeze mnie wzorca — niewykluczone, że bę-
dzie to akurat Twoja gra. Jednakże opisany przeze mnie tok pracy jest tak ogólny i abs-
trakcyjny, że z powodzeniem można go zastosować w większości przypadków.

Uwa ga
Ponieważ w książce prezentuję mnóstwo praktycznych wskazówek i porad, ktoś może odnieść wrażenie,
że promuję swój tok pracy i swoje pomysły jako najlepsze i jedynie słuszne. Naturalnie jest to niepraw-
da. Nie istnieje jeden, „najlepszy” tok pracy. Ten sam cel można osiągnąć, podążając różnymi ścieżkami.
I tak też uważam, ale w książce postanowiłem skupić się na jednym rozwiązaniu i wybrałem to, które
w mojej praktyce sprawdziło się wielokrotnie.

Wprowadzenie do dziesięcioetapowego toku pracy


Wyobraź sobie proces tworzenia gry jako oś czasu skierowaną od lewej do prawej, z góry
na dół lub po prostu od początku do końca. Opisywany przeze mnie tok pracy wymaga
wprowadzenia podziału tej osi na dziesięć segmentów. Zazwyczaj będą one różnej długo-
ści, bo czas trwania poszczególnych etapów może być przecież zróżnicowany — jedne
prace można wykonać szybciej, innych nie da się przyspieszyć.
Na rysunku 1.1 jest pokazana taka linia czasu z dziesięcioma fazami, włącznie z pro-
jektowymi. W sumie cały tok pracy składa się z następujących etapów:
■ burza mózgów,
■ projekt wstępny,
■ tworzenie prototypu,
Wprowadzenie do dziesięcioetapowego toku pracy 23

Rysunek 1.1. Dziesięcioetapowy tok pracy dzieli czas tworzenia gry na dziesięć etapów
o niekoniecznie jednakowej długości

■ dopracowanie projektu,
■ tworzenie elementów gry,
■ importowanie elementów gry do silnika,
■ projektowanie poziomów,
■ kodowanie,
■ testowanie,
■ budowanie.
24 Rozdział 1  Dziesięcioetapowy tok pracy

Tok zaczyna się od pomysłu, a kończy na uzyskaniu kompletnego produktu. Zazwyczaj


poszczególne etapy są realizowane po kolei, czyli następny zaczyna się po zakończeniu
poprzedniego. Niektórzy nazywają to metodą kaskadową ze względu na podobieństwo
do wody spadającej z kolejnych progów. Pomińmy jednak tę wodną analogię i skupmy
się na poszczególnych etapach tworzenia gry.

Uwa ga

Czytelnicy obeznani z systemem projektowania zwinnego (agile) mogą poczuć się skrępowani tym
dziesięcioetapowym tokiem pracy z powodu jego liniowej natury (zob. rysunek 1.1). Agile zachęca twór-
ców do stosowania podejścia iteracyjnego, a nie liniowego. Jednakże nic nie stoi na przeszkodzie, aby każdą
iterację czy cykl w systemie agile traktować jako inicjację nowego dziesięcioetapowego toku pracy.

W dziesięcioetapowym toku pracy każdy etap można traktować jako pewien moduł
aktywności. Ma on punkty wejściowe i wyjściowe. W punkcie wejściowym przyjmuje
rezultat wygenerowany przez wszystkie poprzednie etapy, a do punktu wyjściowego
przekazuje to, co zostało wytworzone w bieżącej fazie produkcji. Co konkretnie dzieje
się pomiędzy tymi dwoma punktami, zależy od konkretnej gry i konkretnego studia
produkcyjnego. Nie jest więc takie ważne, co dzieje się wewnątrz modułu, byleby na
jego wyjściu pojawiło się dokładnie to, co powinno. A teraz przejdźmy do bardziej szcze-
gółowego omówienia poszczególnych etapów.

Etap 1. Burza mózgów


Jeśli już zdecydujesz się stworzyć grę, powinieneś zacząć od burzy mózgów. Każdy
twórca gier przechodzi przez tę fazę i zawsze jest to faza pierwsza. Burza mózgów
oznacza głównie kreowanie nowych pomysłów, ale nie tylko. Chodzi nam także o znale-
zienie powiązań między pomysłami. Celem tej fazy jest wygenerowanie fizycznego lub
mentalnego obrazu gry, którą chcemy stworzyć.

Uwa ga
Burzę mózgów — podobnie jak i pozostałe etapy — można przeprowadzić na wiele sposobów. Ważny
jest tylko efekt końcowy. Powinien być zgodny z naszymi intencjami. Jeśli tak nie jest, należy ten etap
powtórzyć z odpowiednimi zmianami. Postępujemy tak dotąd, aż uzyskamy to, o co nam chodziło.

Nie postępuj na tym etapie zbyt pochopnie. Bardzo łatwo o błąd przy ocenie pomysłu,
który na pozór wydaje się klarowniejszy niż jest w rzeczywistości. Stare indiańskie
przysłowie mówi: „Nigdy nie znasz siebie tak dobrze, jak ci się wydaje”. Dlatego podczas
burzy mózgów zapisuj każdy pomysł, bo już sama próba ujęcia go w krótką, ale treściwą
notatkę może znacząco ułatwić jego właściwą ocenę.
Przykładowo: załóżmy, że zamierzasz stworzyć grę fabularną (RPG) i masz już pewne
pomysły, jak gra ma przebiegać, jakie mają być postacie i jak mają wyglądać miasta,
Etap 1. Burza mózgów 25

w których będzie się toczyła akcja. Nie masz jeszcze tylko sprecyzowanych szczegółów
wyglądu tych miast i postaci (nic nie szkodzi). I prawdopodobnie nie wiesz też, na jakiej
platformie ta gra ma działać, jak dużo jej egzemplarzy uda się sprzedać i czy będzie
przeznaczona dla jednego gracza, czy dla wielu.
Odpowiedzi na tego typu pytania są niezwykle istotne, bo od nich w dużej mierze za-
leży implementacja gry i harmonogram jej opracowania. Gry przeznaczone na urzą-
dzenia mobilne muszą mieć określoną rozdzielczość i ograniczone wymagania sprzętowe,
a w przypadku gier kierowanych do użytkowników konsol i komputerów ograniczenia te
są dużo łagodniejsze. Z kolei w grach wieloosobowych występują ograniczenia co do
liczby obiektów i postaci, które mogą jednocześnie wchodzić we wzajemne interakcje.
Tego typu ograniczenia techniczne wyznaczają ramy, w obrębie których możesz się
poruszać, i musisz je poznać, zanim zaczniesz coś konkretnego projektować. Etap burzy
mózgów jest do tego najlepszym momentem.
Poniżej przedstawiam listę najważniejszych zagadnień, które powinno się rozstrzy-
gnąć na etapie burzy mózgów. Zauważ, że niektóre z nich nie będą miały zastosowania
w przypadku gier o określonej specyfice. Na przykład gry sportowe na ogół nie wymagają
żadnej obudowy fabularnej ani listy głównych bohaterów. Lecz jeśli jakieś zagadnienie
jest istotne dla Twojej gry i nie znasz odpowiedzi na wynikające z niego pytania, to
najwyraźniej nie zakończyłeś jeszcze etapu burzy mózgów. Nie przechodź do następnej
fazy, zanim wszystkiego nie ustalisz.
■ Tytuł ostateczny lub roboczy. Zanotuj ostateczny tytuł gry (jeśli go już znasz) lub
chociaż roboczy, którego będzie można używać, dopóki nie zostanie ustalony
ostateczny. Jakikolwiek tytuł będzie potrzebny, żebyś mógł się odnosić do swojej
gry na blogach i w mediach, a także by móc rozpocząć przygotowywanie materia-
łów marketingowych.
■ Gatunek. Może to być jeden z już istniejących gatunków gier albo zupełnie nowy.
Może też być typ mieszany (hybrydowy). Spośród istniejących gatunków najpopular-
niejsze są gry: RPG, strategiczne, symulatorowe, sportowe, przygodowe, platformowe,
FPS, MMORPG i casualowe.

Uwa ga
W grach wideo typy są zdefiniowane bardzo luźno (jeśli w ogóle). Zazwyczaj w grach RPG, takich jak
Skyrim czy Diablo, gracz musi sterować grupą postaci, które eksplorują fantazyjny świat pełen rozma-
itych stworów, rozwiązują zagadki i podejmują wojownicze wyprawy. W grach akcji typu FPS, takich
jak Quake, Doom czy Duke Nukem, gracz steruje działaniami bohaterów, którzy krążą po polach bitwy, ba-
zach kosmitów lub kompleksach wojskowych wrogich armii i strzelają do wszystkiego, co mają w zasięgu
wzroku. Inaczej jest w grach przygodowych, takich jak Myst czy Monkey Island, które mają mocną pod-
budowę fabularną, zawierają mnóstwo dialogów i wymagają rozwiązywania licznych zagadek. Krótko
mówiąc: świat gier jest niezwykle różnorodny, a liczba gatunków rośnie z każdym rokiem wraz z pojawia-
niem się nowych możliwości technicznych.
26 Rozdział 1  Dziesięcioetapowy tok pracy

■ Sceneria, postacie i fabularna otoczka. Przynajmniej w zarysach nakreśl fabułę


gry, opisz jej scenerię i scharakteryzuj bohaterów. Nie musisz na razie podawać takich
szczegółów jak pochodzenie każdej postaci czy dokładna mapa każdego miejsca
akcji; takie detale określisz i dopracujesz w fazie następnej (przy opracowywaniu
projektu wstępnego).
■ Platformy. Są to systemy komputerowe, na których gracze będą uruchamiali Twoją
grę. Mogą być następujące: Windows, Mac, Linux, Android, iOS, Windows Phone
OS, BlackBerry, Web, Flash i konsole. Wybór nie jest łatwy. Każdy system narzuca
własne standardy odnośnie do wymagań sprzętowych, wydajności i dostępności
zasobów.
■ Obsługiwane rozdzielczości. Pod tym pojęciem kryją się wyrażone w pikselach
wymiary okna, w którym gra będzie wyświetlana. Znajomość tych wymiarów będzie
niezbędna przy projektowaniu skalowalnych elementów graficznych należących za-
równo do świata gry, jak i do jej interfejsu. Sprecyzuj te parametry jak najwcześniej,
aby mieć pewność, że gra będzie się dobrze prezentowała we wszystkich docelowych
rozdzielczościach.
■ Model biznesowy. Określa sposób, w jaki zamierzasz sprzedawać swoją grę. Może
to być system przedsprzedaży, model z darmową wersją podstawową i płatnymi
dodatkami, model sponsorowany przez reklamodawców, których ogłoszenia są pre-
zentowane użytkownikom, albo jakiś zupełnie inny system. Istnieje wiele rozwiązań
i na temat ich efektywności toczy się od dawna gorąca dyskusja (ale to nie miejsce
ani czas, by się do tej dyskusji włączać). Rada? Wybierz jeden lub kilka modeli —
im wcześniej to zrobisz, tym lepiej.

Uwa ga
Zainteresowanych zgłębieniem problematyki modeli biznesowych w branży gier komputerowych odsy-
łam do artykułu zamieszczonego na stronie: www.adobe.com/devnet/flashplayer/articles/right-business-
model.html.

■ Grupa docelowa. Czy Twoja gra jest dla wszystkich, bez względu na wiek, wykształ-
cenie, zainteresowania itp.? Czy raczej jest przeznaczona dla określonej grupy gra-
czy, np.: lubiących gry akcji, dorosłych, młodych? Są to kolejne pytania, na które
trzeba jak najwcześniej odpowiedzieć. Odpowiedzi te będą miały wpływ zarówno
na to, co w tej grze umieścisz (i z niej wykluczysz), jak i na to, kto będzie chciał ją
sprzedawać.
Powyższa lista nie jest bynajmniej wyczerpująca. Zapewne będziesz musiał sobie od-
powiedzieć na jeszcze wiele innych pytań związanych z grą, ale będą to już pytania
odnoszące się do jej specyfiki. Udzielone odpowiedzi pozwolą Ci nakreślić obszar do-
zwolonych wartości, w obrębie którego będziesz musiał potem pracować. Wytyczone
granice będą istotnymi wskazówkami szczególnie w fazach projektowania. Dzięki nim
Etap 2. Projekt wstępny 27

będziesz wiedział, jak daleko i w którym kierunku możesz pójść ze swoją wyobraźnią,
aby nie przesadzić.
W istocie rzeczy każdy spośród omawianych dziesięciu etapów wprowadza jakieś nowe
ograniczenia. Im dalej postępujesz w ramach takiego toku pracy, tym bardziej zawęża
się dozwolony obszar, aż w końcu osiągasz ostatni etap i gdy gra jest gotowa, nie możesz
zrobić już nic więcej. Ograniczenia mogą się wydawać czymś niekorzystnym, ale tak
naprawdę są one jak busola pozwalająca utrzymać raz obrany kurs. W tak złożonym
przedsięwzięciu, jakim jest wyprodukowanie gry, można się czasami pogubić, ale właśnie
dzięki wspomnianym ograniczeniom łatwo jest wrócić na właściwą ścieżkę. Oczywiście
pod warunkiem, że będziesz je respektował! A zatem gdy zakończysz fazę burzy mózgów,
potraktuj wszystkie swoje odpowiedzi bardzo poważnie.

Etap 2. Projekt wstępny


Po etapie burzy mózgów przychodzi czas na sporządzenie pierwszej wersji dokumentu
projektowego dla naszej gry (game design document — GDD), w którym będą uwzględ-
nione wszystkie ustanowione do tej pory ograniczenia. Będzie on produktem wyjściowym
pierwszej fazy toku pracy. Powinien zawierać (co najmniej) następujące rodzaje danych:
■ tekst,
■ diagramy,
■ szkice,
■ rysunki,
■ zdjęcia,
■ wykresy,
■ tabele,
■ listy.
O dokumencie tym myśl jak o przeznaczonym jedynie do odczytu pliku PDF, w któ-
rym zamieszczono w maksymalnie skondensowanej formie opis gry ze wszystkimi
istotnymi informacjami. Dokument powinien być tak sporządzony, aby ktoś, kto go
przeczyta, mógł sobie dokładnie wyobrazić, jak gra będzie wyglądała. Jeśli coś takiego
jest możliwe bez żadnych dodatkowych wyjaśnień, to znaczy, że dokument właściwie
spełnia swoją funkcję. Jeśli jednak takie wyjaśnienia są konieczne, potraktuj je jak in-
formację zwrotną i wykorzystaj do wprowadzenia stosownych poprawek. Konieczność
udzielania dodatkowych wyjaśnień będzie oznaczała najprawdopodobniej, że w do-
kumencie czegoś brakuje lub coś jest niejasno sformułowane. Będziesz więc musiał takie
miejsca odnaleźć i uzupełnić braki lub przeredagować zapisy.
28 Rozdział 1  Dziesięcioetapowy tok pracy

Etap projektowania wstępnego trwa zazwyczaj o wiele dłużej niż burza mózgów, po-
nieważ wymaga większej precyzji i sumienności. Mimo to nie należy jego rezultatu, czyli
dokumentu GDD, traktować jako definitywnie zakończonego. To jest dopiero jego
pierwsza wersja. Potem będą powstawały kolejne. Jednak na każdym etapie powinieneś
tworzyć ten dokument w taki sposób, jakby to miała być jego wersja ostatnia. Wtedy
będzie pewne, że jest sporządzony z należytą starannością.
W praktyce GDD jest ciągle udoskonalany. Nie dlatego, że tak sobie zaplanowałeś, lecz
w wyniku późniejszych spostrzeżeń (zwłaszcza po obejrzeniu prototypu), które często
każą spojrzeć na istniejący projekt z nieco innej perspektywy. Nigdy nie jesteś w stanie
przewidzieć, jakie zmiany będą jeszcze konieczne, więc każdą traktuj tak, jakby miała
być ostatnia.
Co taki dokument powinien zawierać? Mówiąc krótko: powinno w nim być wszystko, co
na temat gry można na danym etapie powiedzieć. Gdyby pewnego deszczowego popołu-
dnia ktoś zwrócił się do Ciebie z prośbą: „Opowiedz mi w końcu o tej twojej grze, ale
nie pomijaj żadnych szczegółów”, wówczas mógłbyś mu podsunąć liczący kilkaset stron
egzemplarz GDD. Jego zawartość będzie oczywiście zależała od konkretnej gry, bo
każda gra jest inna i ma swoją specyfikę.
Poniżej podaję, jakie elementy powinny się bezwzględnie znaleźć w GDD. Potraktuj to
jako wskazówkę na temat samej struktury dokumentu. Otóż według mnie „idealny”
dokument projektowy gry powinien składać się z trzech zasadniczych części:
■ zarysu gry,
■ opisu szczegółów,
■ załączników.

Zarys gry
Bez względu na to, jaką grę stworzysz, zawsze znajdzie się ktoś, kto powie, że mu się
nie podoba, mimo że ani razu w nią nie zagrał. Po prostu nie lubi „tego rodzaju gier”.
Taki człowiek spojrzy tylko na wstępne informacje — wymagania systemowe, gatunek,
tytuł, krótkie streszczenie fabuły — a resztę zignoruje jako rzecz niegodną uwagi.
Radzę zatem umieścić w części zwanej zarysem gry wszystkie istotne szczegóły, i to w taki
sposób, aby do zapoznania się z nimi nie trzeba było się specjalnie zmuszać. Po prostu
ta część musi być możliwie najkrótsza. Podchodząc do dokumentu w taki sposób, za-
czynasz też porządkować szczegóły gry.
Zarys gry powinien zawierać informacje, które już wymieniłem (wymagania systemowe,
gatunek itd.), a także to wszystko (albo prawie wszystko), co zostało ustalone na etapie
burzy mózgów. Nie rozwijaj ich jednak — zrobisz to w następnej części. A zatem jeśli
tworzysz grę z gatunku RPG, umieść w tym miejscu jej tytuł, docelową platformę, ga-
tunek, krótkie streszczenie i jeszcze kilka podobnych informacji, ale nie podawaj listy
Etap 3. Tworzenie prototypu 29

wszystkich miejsc akcji, dostępnych rodzajów broni, wrogów, postaci ani zadań głów-
nych i pobocznych (questów i subquestów). Jeśli jest to gra sportowa, nie wymieniaj
wszystkich zawodników, regulaminów rozgrywek, stadionów i strojów. Podobne reguły
zastosuj w odniesieniu do gry każdego innego gatunku.

Opis szczegółów
W tej części musisz się nieco bardziej zagłębić w szczegóły gry. Po przeczytaniu tego, co
napisałeś w zarysie, osoba przeglądająca dokument ma już pewne pojęcie o grze i teraz
oczekuje czegoś więcej. Trzeba więc rozwinąć to, co zostało wcześniej tylko zasygnali-
zowane. Tutaj jest miejsce na wyszczególnienie wszystkich trybów gry, rodzajów broni,
występujących postaci, zastosowanych stylów, obiektów itp. Możesz z tego zrobić całą
powieść (niektórzy tak czynią), rozciągając te informacje i opisy na wiele stron, ale ja
zdecydowanie zalecam nadanie temu wszystkiemu jakiejś przejrzystej struktury z sys-
temem numerowania każdej pozycji, aby nie było problemu z identyfikacją poszcze-
gólnych elementów. Niech każda broń, każde miejsce, każda postać i każdy obiekt mają
swoje nazwy i numery. Bądź systematyczny.

Załączniki
Po przeczytaniu zarysu i opisu szczegółów osoba zainteresowana grą powinna wiedzieć
o niej niemal wszystko. Bądź jednak przygotowany na dodatkowe pytania. W przy-
padku gry z gatunku RPG może paść pytanie: „A jak wygląda plan miasta X?” albo:
„Czy wiadomo już, jak będzie wyglądała postać X?”. Gdy gra będzie należała do ga-
tunku sportowych, pytania mogą brzmieć: „Jak będą wyglądały stroje drużyny X?”
lub: „Jak przedstawia się tabela rozgrywek ligi X?”. Na każde takie pytanie powinieneś
mieć odpowiedź w postaci odpowiednich rysunków, map, planów, zestawień, wykresów,
schematów i innych tego typu materiałów. To powinno być zawartością ostatniej części
głównego dokumentu gry — możesz jej nadać nazwę Suplement.

Uwa ga
Jeśli stanowisz zespół jednoosobowy, nie sądź, że GDD jest Ci niepotrzebny. Dokument ten nie tylko
przyda się w rozmowach na temat szczegółów gry, ale również pomoże Ci w jaśniejszym precyzowaniu
i zapamiętywaniu swoich pomysłów. Dlatego każda gra powinna mieć swój główny dokument.

Etap 3. Tworzenie prototypu


Prototypowanie to nic innego jak studium wykonalności. W tym momencie trzeba
na podstawie GDD wykonać zgrubną, miniaturową wersję gry. Zwykle nazywa się ją
prototypem. Taki prototyp jest dla gry tym czym szkic dla obrazu.
Prototyp nie jest czymś, co istnieje tylko w teorii i na papierze. To jest prawdziwa gra,
w którą można zagrać. Tylko wygląda topornie, nie ma dźwięków, płynnych animacji
30 Rozdział 1  Dziesięcioetapowy tok pracy

i żadnych efektów wizualnych. Postacie, karabiny, pistolety i inne obiekty są zastępowane


szarymi prostopadłościanami lub innymi prymitywami (sferami, stożkami, ostrosłupami
itp.). Zazwyczaj na tym etapie nie wykonuje się żadnych artystycznie wykończonych
elementów. Pokazuje się co najwyżej puste obrazy, zapałczane ludziki i kreskówkowe
stwory. Prototyp nie ma być kompletną grą, ma tylko służyć do sprawdzenia podsta-
wowych założeń gry.
Wykonanie prototypu umożliwia m.in.:
■ Oszacowanie nakładu pracy. Podczas tworzenia prototypu programiści zyskują pewną
wiedzę na temat tego, co ich czeka w przyszłości. Widać też, czy główne założenia
gry dają się łatwo przełożyć na kod zrozumiały dla komputera. Są więc pewne pod-
stawy do podejmowania prób oszacowania, ile czasu zajmie pełna implementacja
gry i ile to będzie kosztowało. W tym momencie można też ocenić, czy trzeba będzie
poszerzyć zespół o dodatkowych fachowców i zakupić dodatkowe oprogramowanie.
■ Usunięcie istotnych błędów. Napotkałeś jakieś techniczne trudności przy sporzą-
dzaniu prototypu? Jeśli tak, to jakie z tego wnioski wyciągnąłeś? Czy te trudności
wynikały ze specyfiki projektu, czy po prostu z niewłaściwego spojrzenia na ten
projekt? Pytania takie jak te pomogą Ci też w spojrzeniu na grę jak na projekt in-
żynieryjny i przewidzeniu potencjalnych problemów, zanim te ujawnią się w go-
towym produkcie. Będziesz miał więc czas, żeby je zawczasu rozwiązać. Niekiedy
wystarczy w tym celu spojrzeć na całość z nieco innej perspektywy i wprowadzić
drobne poprawki, ale czasami trzeba też pewne rzeczy z projektu usunąć lub cał-
kowicie przeprojektować.
■ Wizualizację gry. Prototyp pozwala pokazać innym ludziom, na czym gra będzie
polegała. Teoretycznie powinien do tego wystarczyć główny dokument gry, ale teoria
nie zawsze przekłada się na praktykę. Niektórzy ludzie po prostu nie lubią czytać
tekstów technicznych, inni nie mają na to czasu, a jeszcze inni twierdzą, że wyczy-
tanych informacji nie pamiętają. Dla takich ludzi prototyp może być doskonałym
sposobem na zapoznanie się z projektem gry. Może też być źródłem inspiracji i no-
wych przemyśleń — pożywką dla pomysłów i eksperymentów myślowych, które były
zbyt mgliste i trudne do sprecyzowania, gdy projekt był jedynie na papierze. To
właśnie dopiero przy oglądaniu prototypu często słychać słowa: „No tak, teraz, gdy
widzę, jak to wszystko działa, sądzę, że tę grę można by jeszcze wzbogacić o kilka
nowych funkcji”.

Etap 4. Dopracowanie projektu


Prototypowanie jest fazą praktycznego testu dla GDD. Rezultatem tamtego etapu jest
lista sugestii, poprawek, pomysłów, uzupełnień i udoskonaleń. Celem czwartego etapu
jest wcielenie tych wszystkich sugestii, poprawek, pomysłów, uzupełnień i udoskonaleń
do projektu, czyli uwzględnienie ich w głównym dokumencie gry. W praktyce zazwy-
czaj wykonuje się to w procesie iteracyjnym złożonym z następujących czynności:
Zarządzanie projektem 31

1. Przemyślenie zmiany.
2. Wprowadzenie jej do dokumentu.
3. Ocena skutków.
Jeśli zmiana jest niezadowalająca, powtarzasz proces, aż otrzymasz coś satysfakcjonujące-
go. Postępujesz tak, dopóki nie uzyskasz kompletnej dokumentacji finalnego projektu.
Teoretycznie na wyjściu tego etapu powinien pojawić się dokument ostateczny i nie-
zmienny — taki, którego modyfikacja byłaby i niemożliwa, i niepotrzebna. W nim
powinno być nieodwołalnie rozstrzygnięte, jak gra ma wyglądać i działać. Dokument
ten powinien być stałym punktem odniesienia i nie powinien być zmieniany na póź-
niejszych etapach. Zauważyłem jednak, że w praktyce utrzymanie tej niezmienności jest
bardzo trudne. Życie zawsze sprawiało mi jakieś niespodzianki i zmuszało do modyfi-
kowania projektu. Czasami było to związane z opóźnieniami w pracach niektórych ze-
społów i trzeba było decydować o rezygnacji z jakiegoś elementu gry, aby zmniejszyć
niezbędne nakłady pracy. Zdarzało się też, że twórcy nagle wpadali na jakiś pomysł i ko-
niecznie chcieli go zaimplementować. Tego typu scenariusze nie są wcale rzadkością
i dlatego trzeba się zawsze liczyć z tym, że projekt może być jeszcze zmieniony.
Zmiany same w sobie nie są niczym złym, ale mogą też być niebezpieczne, bo zmody-
fikowany projekt może okazać się częściowo lub nawet całkowicie niefunkcjonalny.
Dlatego jeśli kiedykolwiek staniesz przed koniecznością dokonania zmian w projekcie
już po jego dopracowaniu, sprawdź najpierw, jakie będą skutki takiego posunięcia. Nie
twierdzę, że nie powinieneś się nigdy zgadzać na jakiekolwiek zmiany, ale podchodź do
takich propozycji z rezerwą, a nawet niechęcią. Na przykład zmiana gry przygodowej
na grę akcji już po opracowaniu większości elementów z pewnością nie byłaby najmą-
drzejszym posunięciem, ale wydłużenie gry przez dodanie nowych postaci i miejsc
może być całkiem rozsądnym krokiem, zwłaszcza jeśli w aktualnym stanie gra wydaje się
rzeczywiście zbyt krótka, a zaproponowane zmiany dadzą się zaimplementować bez
większych problemów.

Zarządzanie projektem
Dotąd wszystkie etapy opisywałem po kolei, tak jakby tworzenie gry było procesem
całkowicie liniowym i jednakowym dla wszystkich. Jednakże już po zakończeniu etapu
czwartego proces może przebiegać rozmaicie, w zależności od struktury zespołu wyko-
nawczego. Jeśli jesteś sam, to zapewne będziesz realizował wszystkie dziesięć etapów
w kolejności dokładnie takiej, w jakiej je tutaj opisuję. Lecz jeśli Twój zespół liczy więcej
osób o różnych umiejętnościach i doświadczeniu, prawdopodobnie kilka etapów będzie
realizowanych równolegle, bo każda osoba zajmie się wykonywaniem swoich zadań.
Programiści przystąpią do programowania, artyści zajmą się artystyczną stroną gry
itd. Niezależnie od tego, który z tych przypadków ma miejsce, etapy implementacyjne
pochłaniają najwięcej pracy i wymagają odpowiedniej koordynacji. I właśnie to kryje
się pod pojęciem „zarządzanie projektem”.
32 Rozdział 1  Dziesięcioetapowy tok pracy

Oczywiście można pracować bez żadnego spójnego systemu zarządzania projektem,


ale najczęściej kończy się to tylko zmarnowaniem czasu i pieniędzy. Gdy praca nie jest
właściwie zorganizowana, wówczas często zdarza się, że niektórzy siedzą bezczynnie
i czekają, aż inni skończą swoje zadania. Na pewno nie jest to optymalne wykorzystanie
posiadanych środków.
Jak więc należy prawidłowo zarządzać projektem? Niestety, odpowiedź na to pytanie
wypełniłaby całą książkę. Zamiast tego podam kilka praktycznych wskazówek, które
pomogą Ci szybko usprawnić funkcjonowanie zespołu. Powiem też, że nie od rzeczy bę-
dzie, jeśli spróbujesz dowiedzieć się więcej na temat zarządzania. Kilka interesujących
publikacji z tej dziedziny proponuję w dodatku A.

Zinwentaryzuj środki
Zacznij od ustalenia wszystkich zasobów, którymi masz zarządzać w ramach danego
projektu. A zatem dowiedz się:
■ Kto należy do zespołu i jaką pełni funkcję.
■ Gdzie każda z tych osób będzie wykonywać swoją pracę (czy wszystkie w tym samym
pomieszczeniu, czy może każda w innej części świata).
■ Jakie są różnice czasowe między miejscami przebywania pracowników.
■ Jakim sprzętem i oprogramowaniem dysponuje zespół oraz kto i jak będzie tych
narzędzi używał (w książce będę omawiał programy takie jak Unity, Blender,
GIMP, Inkscape i Audacity).
■ Jak dużo czasu zostało do ostatecznego terminu ukończenia prac.
■ Jaką sumą pieniędzy dysponujesz (całkowity budżet).
Upewnij się, że znasz te wszystkie rzeczy, bo od tego będzie zależało, czy opracowany
przez Ciebie harmonogram będzie realny.

Zmniejsz odległości
Odległość to czas. Jeśli dwaj członkowie Twojego zespołu znajdują się po przeciwnych
stronach Ziemi, będzie miało miejsce znaczące opóźnienie w komunikacji między ni-
mi ze względu na różne strefy czasowe (gdy jeden będzie się budził, drugi będzie się
kładł do łóżka). Niemożność komunikowania się w czasie rzeczywistym zdecydowanie
utrudni skonsolidowanie zespołu.
Zrób jednak wszystko, aby zminimalizować znaczenie tych przesunięć czasowych. Jeśli
Ci się to uda, pozornie zbliżysz tych ludzi do siebie. Jednym ze sposobów na osiągnięcie
czegoś takiego może być utworzenie wirtualnego biura — miejsca w przestrzeni inter-
netowej, gdzie wszyscy członkowie zespołu mogą się logować, aby zostawić wiadomość,
pobrać nowe zadania, sprawdzić terminy, zweryfikować aktualny stan zaawansowania
Etap 5. Tworzenie elementów gry 33

prac i dzięki temu poczuć przynależność do zespołu. Ze zdobyciem oprogramowania dla


takiego biura nie ma większego problemu — można skorzystać z gotowych rozwią-
zań, takich jak BaseCamp (www.basecamp.com), ActiveCollab (www.activecollab.com),
Unfuddle (www.unfuddle.com) itp.

Zaplanuj pracę
Nie ma czegoś takiego jak złożony problem. Złożoność to tylko nagromadzenie
mniejszych elementów składowych. A zatem problem złożony to nic innego jak zbiór
drobnych problemów.
Czasami wyodrębnienie składników większej całości bywa trudne, ale w zarządzaniu
projektem jest konieczne. W tym celu musisz rozbić proces tworzenia gry na małe,
łatwe do ogarnięcia segmenty, takie jak „konstrukcja postaci wilkołaka”, „programo-
wanie inteligencji wroga” czy „komponowanie ścieżki dźwiękowej dla poziomu nr 1”.
W większości programów wspomagających zarządzanie projektami segmenty te są
nazywane zgłoszeniami (tickets). Każde zgłoszenie reprezentuje określone zadanie.
Cały proces tworzenia gry można rozbić na setki lub tysiące takich zgłoszeń. Wyod-
rębnij je wszystkie, a następnie nałóż na kalendarz projektu i wyznacz dla każdej po-
zycji nieprzekraczalny termin realizacji, uwzględniając potrzebę zachowania płynności
procesu. Na koniec przydziel każde zgłoszenie właściwemu członkowi zespołu. Jeśli bę-
dziesz stosował taki system przez cały czas realizacji projektu, przekonasz się, że wszystko
przebiega całkiem sprawnie.
Wspomniałem o zarządzaniu projektem w tym miejscu, bo jest to zagadnienie o szcze-
gólnym znaczeniu dla pozostałych etapów pracy, które obejmują zadania o bardzo
zróżnicowanym charakterze — od modelowania przestrzennego i animacji po pro-
jektowanie poziomów i programowanie. Tym wszystkim trzeba przecież jakoś zarządzać.
A teraz wróćmy do pozostałych etapów i zobaczmy, co się w nich kryje.

Etap 5. Tworzenie elementów gry


Etap piąty to tworzenie elementów gry, czyli wszystkich grafik i animacji. Są to elementy
interfejsu (okna, kursory itp.), grafiki dwuwymiarowe (ekrany powitalne, tła), dźwięki
i grafiki trójwymiarowe (siatki). Wszystko, co widać i słychać podczas grania, jest ele-
mentem gry.
Wytworzenie tych elementów jest zwykle najdłuższą i najdroższą częścią procesu pro-
dukcyjnego (chyba że większość elementów gry jest już gotowa i nadaje się do użycia).
Jeśli efekt końcowy ma być dobrej jakości, na tym etapie nie możesz oszczędzać. Artyści
muszą poświęcić dużo czasu i wykazać się zaangażowaniem. To właśnie na tym etapie
znajdą zastosowanie programy takie jak GIMP, Blender i Inkscape. Zapoznasz się z nimi
już w następnym rozdziale. Teraz chciałbym jedynie, abyś zachował w pamięci kilka rad.
34 Rozdział 1  Dziesięcioetapowy tok pracy

■ Wykorzystuj te same elementy wielokrotnie. Jeśli akcja gry toczy się w wielu po-
dobnych miejscach (np. w biurach), w każdym z nich będą potrzebne takie same
albo podobne obiekty, np. krzesła. W takiej sytuacji możesz wymodelować tylko
jedno lub dwa krzesła, a potem w miarę potrzeb będziesz je tylko kopiował. Nie
musisz każdego jednego egzemplarza modelować od podstaw. Nie przejmuj się za
bardzo powtarzalnością, bo ten sam obiekt może wyglądać zupełnie inaczej w otocze-
niu innych przedmiotów i w innych warunkach oświetleniowych. Jeżeli powtarzalność
będzie się rzucać w oczy, zmodyfikujesz zastosowane kopie, w ostateczności utwo-
rzysz zupełnie nowy obiekt. Nie zakładaj jednak już na wstępie, że problem taki na
pewno wystąpi. Spróbuj zaoszczędzić trochę czasu i pracy.
■ Używaj zdjęć jako materiałów referencyjnych. W większości prac plastycznych
widać dążenie do jak najwierniejszego odtworzenia elementów świata rzeczywistego.
Nawet mityczne stwory, jak smoki, skrzaty czy elfy, zawierają jakąś cząstkę realizmu,
choćby przez to, że są podobne do stworzeń, które naprawdę istnieją. Tak naprawdę
wszystko, co zostało stworzone na potrzeby gier, w mniejszym lub większym stopniu
nawiązuje do świata rzeczywistego i było wzorowane na materiałach fotograficznych.
Po prostu graficy, tworząc swoje dzieła, korzystają ze zdjęć jako materiałów refe-
rencyjnych. Materiały te są niezwykle istotne. Nie sądź, że wszystko uda się wymyślić
i że wystarczy do tego sama wyobraźnia. Jeśli chcesz, żeby gra zrobiła dobre wra-
żenie wizualne, musisz zgromadzić odpowiednie materiały referencyjne. Poświęć
na to tyle czasu, ile trzeba. Rób zdjęcia i zbieraj je, gdzie tylko się da. Każda chwila,
jaką na to przeznaczysz, nie będzie zmarnowana, wcześniej czy później przyniesie Ci
wymierne korzyści. Pierwszą korzyścią będzie szybsze tworzenie wizualnych ele-
mentów gry.
■ Stosuj outsourcing. Outsourcing to po prostu wystąpienie do kogoś z zewnątrz
z propozycją wykonania elementów Twojej gry. Zabieg taki jest dość często stosowany,
a najczęściej wtedy, gdy studio ma poważne opóźnienia i potrzebuje pomocy, by
nadrobić stracony czas, ale nie chce na stałe zatrudniać dodatkowych pracowników.
Jednakże wiążą się z tym dodatkowe koszty — a nie każdy zespół znajdzie odpo-
wiednie rezerwy w swoim budżecie. Zanim podejmiesz decyzję o outsourcingu,
przeanalizuj dokładnie wszystkie za i przeciw.

Etap 6. Importowanie elementów gry do silnika


Po utworzeniu wszystkich elementów trzeba je zaimportować do silnika gry. W tej książ-
ce opiszę tworzenie elementów za pomocą Blendera, GIMP-a i Inkscape’a, a silnikiem
będzie pakiet o nazwie Unity.
Mogłoby się wydawać, że przenoszenie elementów z jednego pakietu do drugiego to nic
wielkiego i nie warto tworzyć z tego odrębnego etapu. Jednakże przenoszenie czegoś,
co zostało wytworzone w jednym programie, i umieszczanie tego w silniku gry często
Etap 6. Importowanie elementów gry do silnika 35

wymaga żmudnego dostrajania wielu parametrów i wprowadzania poprawek. Niekie-


dy może to zająć trochę czasu i spowodować opóźnienia w realizacji całości. Dlatego
przeznaczyłem na te czynności oddzielny etap. Do ich omawiania wrócę jeszcze w na-
stępnym rozdziale, a na razie podam tylko ogólne informacje na temat importowania
elementów gry.
■ Formaty plików i kompatybilność. Sprawdź, jakie formaty plików są możliwe do
zaimportowania przez wybrany silnik gry. Każdy silnik obsługuje określony zestaw
formatów dla siatek, animacji, filmów i obrazów. Dowiedz się, jakie one są, i upewnij
się, że programy użyte do tworzenia elementów gry mogą generować pliki w takich
formatach albo że są dostępne odpowiednie konwertery. Opisywane przeze mnie
programy (Unity, Blender, GIMP i Audacity) są pod tym względem w pełni kompa-
tybilne. Oznacza to, że możesz tworzyć elementy gry w Blenderze, GIMP-ie i Audacity,
a potem bez większych problemów zaimportujesz je do Unity.
Formaty obsługiwane przez Unity
Formaty obrazów Formaty siatek
PSD MA
TIFF MB
JPEG MAX
PNG JAS
GIF C4D
BMP BLEND
TGA LXO
IFF FBX
PICT 3DS
OBJ
Formaty dźwięku Formaty filmów
MP3 AVI
OGG MOV
AIFF ASF
WAV MPG
MOD MPEG
IT MP4VIDEO
S3M Ogg Theora
XM
Więcej informacji na temat obsługiwanych formatów i procesu importowania plików w Unity znajdziesz na stronach:
• http://unity3d.com/unity/workflow/asset-workflow/,
• http://docs.unity3d.com/Documentation/Manual/AssetWorkflow.html.
36 Rozdział 1  Dziesięcioetapowy tok pracy

■ Wymagania dotyczące elementów gry. Fakt, że Unity obsługuje format, w jakim


zapisane są elementy gry, nie gwarantuje wcale prawidłowego ich wyglądu po za-
importowaniu i uruchomieniu silnika. Zanim przystąpisz do tworzenia pierwszego
elementu, zapoznaj się dokładnie z wymaganiami i ograniczeniami stawianymi
przez silnik. Zwróć szczególną uwagę na parametry związane z liczbą wielokątów,
strukturą siatki, liczbą materiałów, mapowaniem UV itp. Najprawdopodobniej spo-
tkasz się z surowymi wymaganiami dotyczącymi struktury i konfiguracji elementów,
a zwłaszcza siatek. Szczegółami tego zagadnienia w odniesieniu do silnika Unity
zajmiemy się w rozdziałach 2. i 3. Na razie możesz zaczerpnąć trochę informacji
z instrukcji dostępnej pod adresem: http://docs.unity3d.com/Documentation/Manual/
ImportingAssets.html.

Etap 7. Projektowanie poziomów


Po udanym zaimportowaniu elementów gry do jej silnika możesz rozpocząć konstru-
owanie poziomów i środowisk. Proces budowania poziomów zmienia się w zależności
od konkretnej gry. Może wymagać łączenia siatek, jak cegieł, w celu uformowania
kompletnego środowiska gry trójwymiarowej, albo malowania bitmapowych teł dla gry
dwuwymiarowej.
Ostatecznym celem projektowania poziomów jest zbudowanie świata, w który gracz ma
się zagłębić. Aby to osiągnąć, musisz stworzyć świat interesujący i interaktywny. Z tego
powodu projektowanie poziomów często odbywa się równolegle z pisaniem kodu i skryp-
tów, czyli z czynnościami zaliczanymi do następnego etapu.
Jeśli chodzi o projektowanie poziomów, to mam trzy bardzo ważne wskazówki, chociaż
tak naprawdę należałoby wymienić znacznie więcej.
■ Stosuj metodę modułową. Kuszące jest patrzenie na poziomy i środowiska z per-
spektywy gracza. Wtedy wydaje się, że są kompletnymi i zespolonymi całościami.
Nie poddawaj się takiej pokusie. Gdy szukasz wyjścia z labiryntu korytarzy i lochów
lub przemierzasz bezkresne obszary pustynne bądź dżunglowe, wszystko sprawia
wrażenie, jakby zostało w całości wygenerowane przez artystę in situ. Ty jednak
powinieneś myśleć o poziomach raczej w kategoriach klocków Lego lub bloków
budowlanych. Zazwyczaj poziomy układa się właśnie z takich małych zazębiających
się kawałków. Są kawałki narożne, proste, krzyżowe, końcowe i wszelkich innych
rodzajów. Każdy można połączyć z dowolnym innym, co w rezultacie daje właściwie
nieskończoną liczbę konfiguracji, w jakich można je ułożyć. Naprawdę uwielbiam
tę metodę. Projektowanie poziomów może dać dużo satysfakcji i radości!

Uwa ga
W rozdziale 3. opisuję techniki projektowania poziomów z użyciem Blendera. Zobaczysz tam, jaki można
zrobić użytek z modułowych klocków, które idealnie do siebie pasują.
Etap 8. Kodowanie 37

■ Projektuj poziomy zgodnie z planami. Podczas tworzenia elementów środowiska


w sposób modułowy łatwo dać się ponieść fantazji. Na przykład w edytorze pakietu
Unity można bez trudu wrzucać kolejne elementy środowiska i łącząc je w najroz-
maitsze sposoby, tworzyć fantazyjne i zupełnie zwariowane światy. Zabawa jest
znakomita, ale może się źle skończyć. Swoboda tworzenia może doprowadzić do
tego, że wygenerowane poziomy i środowiska będą dalekie od pierwotnych planów.
Jeśli się w porę nie opamiętasz, może się okazać, że Twoje dzieło w ogóle nie będzie
się nadawało do użytku i tylko stracisz czas. Pamiętaj o tym i w trakcie projektowa-
nia poziomów często zaglądaj do swoich projektów, map i szkiców. Improwizacja
nie jest rzeczą złą, ale powinna być podejmowana świadomie i nie może burzyć
pierwotnego zamysłu.
■ Sprawdzaj, co inni sądzą. A więc masz już zachwycające poziomy do swojej gry.
Ale czy rzeczywiście są tak zachwycające, jak Ci się wydaje? Według mnie kwestia
estetyki poziomów gry nie istnieje. Uważam, że nie ma poziomów „dobrych” lub
„złych”, tak samo jak nie ma „dobrych” lub „złych” gier — przynajmniej w sensie
obiektywnym. Możesz się z tym zgadzać albo nie. Tak czy inaczej, jeśli planujesz
sprzedawać swoją grę, to musisz brać pod uwagę, co inni ludzie o niej myślą. Dlatego
powinieneś przy najbliższej sposobności dać ją do przetestowania przynajmniej
trzem osobom. Pozwól im pograć na wszystkich poziomach i w tym czasie obserwuj
ich reakcje. Wsłuchuj się w ich komentarze i wyciągaj wnioski. Czy będą to uwagi
pozytywne, czy negatywne, traktuj je wszystkie jak instrukcje mówiące, co masz po-
prawić. Tych negatywnych nie odnoś do siebie i nie obrażaj się ani nie wpadaj w de-
presję. Nie pozwól, aby emocje wzięły górę nad zdrowym rozsądkiem.

Etap 8. Kodowanie
Kodowanie zazwyczaj odbywa się równolegle z projektowaniem poziomów. Świat gry
powinien nie tylko ładnie wyglądać, ale również muszą się w nim dziać pewne rzeczy.
Mogą tam być np. windy przenoszące bohatera na różne kondygnacje budowli albo po-
twory rozwalające ściany i atakujące intruzów, którzy podeszli zbyt blisko. To wszyst-
ko trzeba zaprogramować (zakodować) w Unity za pomocą języka skryptowego. Unity
oferuje trzy takie języki: C#, JavaScript i Boo. Każdy z nich ma olbrzymie możliwości,
więc przy wyborze możesz się kierować jedynie swoimi upodobaniami.

Uwa ga
Wszystkie prezentowane w tej książce skrypty napisałem w języku C#. Nie oznacza to wcale, że inne
uważam za gorsze. Po prostu ten język znam najlepiej i lubię się nim posługiwać.

Programowanie może trwać długo i wymagać dużego nakładu pracy. Aby ten proces
przebiegał efektywnie, pamiętaj o następujących zasadach:
38 Rozdział 1  Dziesięcioetapowy tok pracy

■ Pracuj zgodnie z planem. Nigdy nie programuj na ślepo. Zanim napiszesz pierw-
szy wiersz kodu, przemyśl dokładnie, co chcesz uzyskać. Przecież żeby rozwiązać
jakikolwiek problem, najpierw trzeba dobrze zrozumieć, na czym on polega. Skoro
już o rozwiązywaniu problemów mowa: nie staraj się szukać rozwiązania dobrego
wyłącznie dla bieżącego przypadku, ale takiego, które będzie miało zastosowanie
również w sytuacjach podobnych. Załóżmy np., że masz zaprogramować stwora,
który po odniesieniu ran w walce będzie szukał fantów przywracających zdrowie
i siły. Możesz się skupić na tym jednym konkretnym stworze, ale przecież takich
stworów może być w tej samej grze więcej, a skoro tak, to dlaczego nie miałbyś napisać
ogólnej procedury, którą dałoby się wykorzystać wielokrotnie. Właśnie taki styl pro-
gramowania będziesz miał okazję zobaczyć w drugiej połowie książki.
■ Bądź konsekwentny. Unity pozwala na luksus programowania w kilku językach —
możesz używać C#, JavaScript lub Boo. Możesz nawet stosować kombinacje tych
trzech języków. Jednakże odradzam takie postępowanie. Wybierz jeden język i konse-
kwentnie stosuj go w całym projekcie. Unikniesz dzięki temu ciągłego przestawiania
się na inny sposób myślenia, a w zamian zyskasz większy komfort pracy i możli-
wość pogłębienia znajomości konkretnego języka. Jeśli przyjdzie Ci włączyć do swoje-
go kodu jakąś procedurę napisaną w innym języku, „przetłumacz” ją na wybrany
przez siebie język, chyba że zaistnieją naprawdę ważne przeszkody, takie jak brak
czasu lub szczupłość budżetu.
■ Komentuj swój kod. Komentarze zamieszczane w kodzie są czytelnymi dla czło-
wieka objaśnieniami, mającymi ułatwić zrozumienie, jakie zadanie wykonuje dany
fragment kodu. Nie zaniedbuj tej czynności nawet wtedy, gdy jesteś jedynym pro-
gramistą i nikt inny nie będzie Twojego kodu czytał. Naturalnie gdy go piszesz,
wszystko w nim jest klarowne i zrozumiałe, ale już po paru tygodniach lub miesią-
cach sytuacja może wyglądać zupełnie inaczej. Komentarze przydadzą się zarówno
innym programistom, jak i Tobie. Ty sobie szybciej przypomnisz, o co w tym ko-
dzie chodzi, a inni będą mieli ułatwione zadanie, jeśli będą musieli go zaadaptować
do swoich potrzeb. Kod należy pisać tak, aby mógł być wielokrotnie wykorzystywany,
i komentarze właśnie temu celowi służą.

W s k a z ów ka
Zachęcam do przeczytania artykułu Roedy’ego Greena zatytułowanego How to Write Unmaintainable Code
(http://thc.org/root/phun/unmaintain.html). Jest to utrzymany w ironicznym tonie poradnik na temat,
jak pisać kody „jednorazowego użytku”, ale jednocześnie instruujacy, jak tego nie robić. Autor, pisząc
ten artykuł, miał na uwadze język Java, ale zaprezentowane argumenty są uniwersalne i można je od-
nieść do każdego innego języka.
Etap 9. Testowanie 39

Etap 9. Testowanie
Etap testowania składa się z kilku faz zależnych od rodzaju gry i stopnia jej ukończenia.
Samo testowanie polega w głównej mierze na próbnej grze. Pierwszym testerem będziesz
zapewne Ty sam, ale powinny to zrobić też inne osoby. Celem jest sprawdzenie, czy
wszystko w grze działa zgodnie z projektem i czy przy prawidłowym użytkowaniu nie
pojawiają się błędy.
Podczas takich testów należy sprawdzać wszystkie możliwe warianty, nawet te mało
prawdopodobne. Jeśli gracz ma do wyboru dwoje drzwi: X i Y i z przebiegu gry jasno
wynika, że należy wybrać drzwi X, to tester powinien sprawdzić również, co kryje się za
drzwiami Y. Na tym etapie trzeba grę sprawdzać tak długo i wszechstronnie, jak tylko
pozwalają na to warunki czasowe.
Oto kilka wskazówek, o których warto pamiętać podczas przeprowadzania testów:
■ Testuj jak najwcześniej. Nie myśl o testowaniu jak o czymś, co ma nastąpić dopiero
wtedy, gdy gra będzie gotowa. Testowanie powinno być procesem ciągłym. Testuj
poszczególne funkcje i wprowadzane zmiany, gdy tylko je zaprogramujesz. Zaplanuj
też regularne bardziej ogólne testy w całym procesie produkcyjnym, aby kontrolować
prawidłowość zestrojenia gotowych już elementów. Podczas takich testów bądź
bezwzględny i nie pozwalaj sobie na żadne pobłażanie. Nie bój się, że coś może nie
zadziałać i trzeba będzie poświęcić dużo czasu na naprawę błędu. Jeśli przyczyna
usterki nie jest oczywista, użyj narzędzi debugujących, jakie są w pakiecie Unity.
Działaj systematycznie. Sprawdzaj podejrzane funkcje pojedynczo i w maksymalnej
izolacji od pozostałych. Szukaj błędu metodą eliminacji.
■ Nie bądź jedynym testerem. Tak jak autor nigdy nie będzie dobrym recenzentem
swojej książki, tak i programista nie będzie najlepszym testerem swojego programu.
Owszem, błędy składniowe wychwyci kompilator, a Ty zauważysz oczywiste i grube
błędy logiczne. Natomiast cała masa błędów drobnych i pozornie nic nieznaczących
najprawdopodobniej ujdzie Twojej uwadze. Tak mają wszyscy programiści, nie
tylko twórcy gier. Dlatego proś i zachęcaj innych, aby testowali Twoją grę na róż-
nych etapach jej rozwoju. Będziesz zaskoczony liczbą wykrytych w ten sposób błę-
dów. Każdy błąd wykryty traktuj jak okazję do świętowania, a nie powód do roz-
paczy. Każdy twórca oprogramowania chciałby, aby jego aplikacje były bezbłędne,
ale żeby wyeliminować wszystkie błędy, trzeba je najpierw wykryć.
■ Numeruj kolejne wersje. Potraktuj poważnie numerowanie kolejnych wersji gry,
zachowując ścisłe reguły nadawania numerów głównych i pobocznych, aby dla użyt-
kownika było jasne, z czym ma do czynienia. Po wykryciu i naprawieniu błędów
nie zapomnij o właściwym skorygowaniu również numeru wersji. Dzięki temu użyt-
kownik — i Ty też — będzie wiedział, czy korzysta z wersji najnowszej, czy nie.
Poza tym jeśli w grze pojawi się jakiś nowy błąd, łatwiej Ci będzie ustalić, w któ-
rym momencie (w której wersji) mógł być wprowadzony i jaka zmiana kodu może
być za to odpowiedzialna.
40 Rozdział 1  Dziesięcioetapowy tok pracy

■ Rejestruj błędy. Notuj wszystkie błędy wraz z okolicznościami ich wykrycia i przy-
czynami. Nie zważaj na to, czy dany błąd został naprawiony, czy jeszcze nie. Nie
usuwaj też żadnej pozycji z rejestru. Prześledzenie takiej listy może Cię naprowadzić
na trop podobnych usterek, które jeszcze nie zostały wykryte. Tropienie błędów
w kodzie jakiejkolwiek aplikacji przypomina trochę odkrywanie tajemnic, więc bądź
tak dobrym detektywem, jak tylko możesz.

Etap 10. Budowanie


Ostatni etap to budowanie pełnej wersji gry. Dotarcie do tego etapu może zająć miesią-
ce, a nawet lata. Gra jest już stworzona i przetestowana, ale trzeba jeszcze uczynić z niej
pełnoprawną aplikację, która będzie mogła funkcjonować na innych komputerach.
Jeśli Twoja gra ma być dostępna poprzez sklepy takie jak App Store, Google Play czy
Windows Store, musisz ją zbudować. Proces budowania musisz przeprowadzić także
po to, aby gra dała się uruchomić na platformie Windows, Linux, Mac lub na jakiejś
konsoli do gier.
Wiele aspektów tego procesu można wykonać po prostu w Unity, ale mimo wszystko
wymaga to uwagi i starannego przygotowania. Będziemy do tego wracać wielokrotnie
w pozostałych rozdziałach. Tutaj wymienię tylko kilka najważniejszych kwestii.
■ Dostosuj proces budowy do platformy. Jedną z zalet pakietu Unity jest to, że
umożliwia zbudowanie gry i dostosowanie jej do wielu systemów, takich jak Windows,
Linux, Mac, Android, iOS, Windows Phone, BlackBerry, Web i konsole. Dobrze
oddaje to często powtarzany slogan: „Buduj raz, instaluj wszędzie”. Koncepcja wy-
daje się bardzo prosta — tworzymy grę, a na koniec wciskamy guzik, który sprawia,
że jest ona gotowa do użytku na każdej z wymienionych platform. I rzeczywiście,
proces budowania może tak wyglądać, jeśli tylko właściwie skonfigurujemy narzędzia
pakietu Unity, ale to jeszcze nie musi oznaczać, że gra zadziała prawidłowo w każdym
docelowym systemie. Aby tak się stało, trzeba całemu procesowi poświęcić trochę
uwagi i przeprowadzić tzw. optymalizację budowy gry pod kątem danej platformy.
Oczywiście Unity ma odpowiednie do tego narzędzia, a o technikach ich stosowania
będziemy mówić w kolejnych rozdziałach.
■ Poznaj docelową platformę. Prawie każda gra przeznaczona na określoną plat-
formę ma jakieś minimalne wymagania. Po prostu gracz musi dysponować okre-
ślonym sprzętem, żeby móc zagrać. Czasami twórcy gry określają także zalecane
parametry systemu, czyli taką konfigurację sprzętowo-programową, przy której
gra będzie mogła działać bez żadnych ograniczeń. Są to Twoje dwie „konfiguracje
docelowe” — dwie konfiguracje sprzętowe, na których gra powinna zadziałać. Na
czas testowania i budowania gry powinieneś mieć dostęp do obu tych konfiguracji.
Ale to nie wszystko. O tym, jak mają wyglądać docelowe konfiguracje, powinieneś
zdecydować przed rozpoczęciem tworzenia gry, a nie po jej ukończeniu. Przepro-
Zalecenia praktyczne 41

wadzanie testów w takich warunkach pozwoli Ci właściwie ocenić szybkość dzia-


łania gry i jeśli zajdzie potrzeba, zdecydować o konieczności podjęcia prac nad po-
prawą jej wydajności.
■ Poznaj wymagania sklepu z aplikacjami. Jeśli chcesz, aby Twoja gra znalazła się
w sklepie z aplikacjami, takim jak App Store czy Google Play, musisz poznać wa-
runki, na jakich możesz tam swoją aplikację umieścić. Każdy taki sklep stawia okre-
ślone wymagania co do zawartości gry, rozmiaru pliku i parametrów strukturalnych,
takich jak wymiary ikon czy liczba i rozmiary plików z danymi. Poświęć trochę
czasu na przestudiowanie tych wymagań i uwzględnij je podczas budowania gry.
W razie wątpliwości staraj się uzyskać odpowiedź, korzystając z różnych kanałów
pomocy technicznej konkretnego sklepu.

Zalecenia praktyczne
Zaprezentowany wyżej dziesięcioetapowy tok pracy jest tylko ogólnym schematem
tworzenia gier, od casualowych układanek po drogie MMORPG-i. Jeśli nawet nie spasuje
Ci w całej rozciągłości, to i tak jego znajomość może Ci wiele rzeczy ułatwić. Pamiętaj,
aby maksymalnie wykorzystać to wszystko, co będzie pasowało do Twoich potrzeb.
Jeśli przystępujesz do tworzenia gry po raz pierwszy, mam dla Ciebie kilka dodatko-
wych wskazówek.
■ Mierz siły na zamiary. Postaw sobie cel możliwy do osiągnięcia i zmierzaj do niego
z całych sił. Niemal każdy czuje podniecenie i zapał, gdy myśli o grze, którą zamierza
utworzyć. W takim stanie bardzo łatwo dodaje się kolejne elementy i funkcje, aby
gra była jeszcze lepsza i fantastyczniejsza. Ale też łatwo można sobie nałożyć na
barki więcej niż się potrafi udźwignąć. Jeśli masz mały zespół i niewielki budżet,
wyznacz sobie realistyczne granice, aby uniknąć potem rozczarowania. Jeśli nie
potrafisz realistycznie oszacować całkowitych kosztów przedsięwzięcia ani terminu
jego zakończenia, potraktuj to na równi z zagrożeniem wykonalności projektu
i wprowadź stosowne ograniczenia. Postępuj tak dotąd, aż będziesz w stanie określić
koszty i czas trwania jego realizacji.
■ Nie rozdrabniaj się. Jeśli jesteś przemęczony, zestresowany i masz wszystkiego
dość, to znaczy, że starasz się robić zbyt wiele rzeczy naraz. Raczej skup się na jednym
zadaniu i poświęć mu całą swoją energię. Następny krok rób dopiero po zakończeniu
etapu poprzedniego. Gry są przedsięwzięciami z pogranicza wielu dyscyplin i wyma-
gają od twórców szerokiego wachlarza umiejętności. Nie oznacza to jednak, że
musisz pracować na wszystkich polach jednocześnie, przeskakując z programowania
do grafiki, a stamtąd do muzyki i jeszcze do projektowania poziomów bez wyraźnie
wytyczonego kierunku i podziału pracy. Bądź zorganizowany i koncentruj się na
tym, co aktualnie robisz. Wykonuj zadania po jednym.
42 Rozdział 1  Dziesięcioetapowy tok pracy

■ Mniej graj, więcej pracuj. Pewnego razu grupa młodych ludzi studiujących two-
rzenie gier spytała mnie, jak mogliby poprawić swoją produktywność. Mieli orygi-
nalny pomysł na grę i spore umiejętności, ale frustrowało ich zbyt wolne tempo prac
nad jej realizacją. Gdy odwiedziłem ich studio w Chicago, aby zobaczyć, jak mógł-
bym im pomóc, szybko zorientowałem się, że sporą część czasu spędzają na graniu
w rozmaite gry. Jak się później okazało, granie zajmowało im aż 65% czasu, który
powinni przeznaczyć na tworzenie własnej gry. To prawda, że inne gry mogą być
źródłem cennej inspiracji, ale takie myślenie może być istotnym zagrożeniem dla
postępu prac nad własnym projektem. Bądź uczciwy wobec siebie, jeśli chodzi o po-
dział czasu na pracę i rozrywkę.
■ Nie uskarżaj się na narzędzia. Podczas tworzenia gry napotkasz wiele przeszkód
i problemów. I nie ma tu znaczenia, jakiego narzędzia będziesz akurat używał: Unity,
Blendera, GIMP-a czy jeszcze innego. W takich sytuacjach łatwo zrzucić całą winę
na niedoskonałość narzędzia, ale taka postawa wyjdzie tylko na złe zarówno Two-
jej pracy, jak i Twojej grze. Zamiast narzekać, postaraj się spojrzeć na problem
z innej perspektywy i poszukać innego sposobu użycia narzędzia. Zrób sobie krótką
przerwę i wróć do pracy z innym nastawieniem. W razie potrzeby poszukaj doradz-
twa w internecie. Zazwyczaj ten sam cel można osiągnąć na wiele sposobów i służące
do tego narzędzia też pozwalają na znaczną elastyczność. Gdy tylko przestaniesz
narzekać na narzędzia i zaczniesz odkrywać ich wszechstronność, zdołasz zrobić z ich
pomocą więcej niż Ci się wydaje. Nie pytaj: „Kto zawinił?”, tylko mów do siebie:
„Wiem, że za pomocą tego programu można to zrobić. Ale jak?”.

Podsumowanie
Ten rozdział wyznacza punkt początkowy na naszej drodze do praktycznego wykorzy-
stania połączonych możliwości Unity i Blendera oraz kilku innych programów wspo-
magających tworzenie gier. Celem ostatecznym jest ukształtowanie właściwego sposobu
myślenia o grach komputerowych i ich tworzeniu.
W dziesięcioetapowym toku pracy cały cykl produkcji gry dzielimy na dziesięć odrębnych
faz. Kolejność i metody ich realizacji zależą od konkretnej gry, zespołu wykonawczego
i dostępnych środków. Zawsze jednak wyznaczają one istotne punkty cyklu produk-
cyjnego, przez co zarządzanie nim staje się łatwiejsze. W pozostałych rozdziałach skoncen-
trujemy się na sześciu ostatnich etapach, czyli na tworzeniu elementów gry, programowa-
niu i ostatecznym budowaniu gry. Pominiemy zagadnienia związane z projektowaniem
gry i tworzeniem dokumentu projektowego. Zrobimy tak, bo najczęściej po programy
typu Unity i Blender sięga się dopiero wtedy, gdy projekt gry jest już gotowy. One
mają służyć do tworzenia elementów gry i jej poziomów, a właśnie to ma być głównym
tematem książki. Nie będę jednak opisywał tych zagadnień w układzie zgodnym z za-
prezentowanym wyżej tokiem pracy, lecz w układzie tematycznym i z uwzględnieniem
wzajemnych powiązań między poszczególnymi programami oraz ich współpracy z silni-
kiem Unity.
Podsumowanie 43

W tym pierwszym rozdziale podałem wiele wskazówek i rad dla tych, którzy po raz
pierwszy próbują stworzyć grę, ale nie oznacza to, że inni z niego nie skorzystają.
Wszystkie zawarte w nim rady można by podsumować następująco: mierz siły na za-
miary, nie rób zbyt wielu rzeczy jednocześnie, twórz gry zamiast w nie grać i nie ob-
winiaj narzędzi za swoje niepowodzenia. Jeśli podczas lektury pozostałych rozdziałów
będziesz postępował zgodnie z tymi czterema zasadami, to myślę, że tworzenie gier
stanie się dla Ciebie wspaniałym zajęciem. Oczywiście mam na myśli tworzenie gier za
pomocą Unity i Blendera.
44 Rozdział 1  Dziesięcioetapowy tok pracy
R OZ DZ I AŁ 2

O D B LENDERA DO U NITY

Prostota jest szczytem wyrafinowania.


— Leonardo da Vinci

Po przeczytaniu tego rozdziału powinieneś:


■ umieć przygotować Blendera do współpracy z Unity;
■ rozumieć zagadnienia związane z przechodzeniem od Blendera do Unity;
■ zdawać sobie sprawę z trudności w importowaniu i eksportowaniu siatek;
■ umieć obchodzić się z ostrymi krawędziami i modyfikatorem Edge Split (rozcinanie
krawędzi);
■ umieć eksportować modele w formacie FBX.
Niemal w każdej grze wideo mamy do czynienia z wyświetlaniem modeli złożonych
z wielokątów i dlatego zwanych siatkami. Ich geometryczna forma jest definiowana za
pomocą wierzchołków, krawędzi i ścianek. W ten właśnie sposób przedstawiane są
w zasadzie wszystkie przedmioty widoczne w grze — od elementów uzbrojenia po ludzi
i wszelkie potwory. Artyści tworzący na potrzeby gier mają do dyspozycji wiele rozma-
itych programów ułatwiających generowanie takich siatek, ale my będziemy używać wy-
łącznie Blendera. Jest to darmowy i działający na wielu platformach program do mode-
lowania obiektów trójwymiarowych; można go pobrać ze strony: www.blender.org/.

Uwa ga
Jeśli chciałbyś zobaczyć konkretne przykłady tego, co potrafi Blender, obejrzyj krótki film pt. Sintel za-
mieszczony na stronie: www.youtube.com/watch?v=eRsGyueVLvQ.

45
46 Rozdział 2  Od Blendera do Unity

Nie będę opisywał Blendera od podstaw. Jest mnóstwo darmowych i komercyjnych po-
radników oraz kursów obsługi tego programu kierowanych również do początkującego
użytkownika. Można tam nie tylko dowiedzieć się wszystkiego na temat interfejsu tego
programu i stosowanych w nim skrótów klawiszowych, ale również poznać podstawy
modelowania, teksturowania itp.

W s k a z ów ka
Jeśli jeszcze nigdy nie używałeś Blendera albo potrzebujesz odświeżyć swoją wiedzę o nim, zanim przy-
stąpisz do dalszej lektury tego rozdziału, to zajrzyj do dodatku A. W części zatytułowanej „Książki” znaj-
dziesz kilka pozycji, które z pewnością ułatwią Ci wstępne poznanie tego programu.

Głównym tematem tego rozdziału jest współpraca Blendera z Unity, ale będzie też oka-
zja, żeby wspomnieć o modelowaniu i teksturowaniu. Jednak zgodnie z tym, co przed
chwilą powiedziałem, skoncentruję się przede wszystkim na praktycznym aspekcie
współdziałania tych dwóch programów. W szczególności pokażę, jak można skonfigu-
rować interfejs Blendera, aby dało się w nim pracować szybciej i wydajniej. Następnie
zobaczysz, na czym polega optymalny sposób eksportowania wymodelowanych siatek
do programu Unity z zachowaniem odpowiedniego cieniowania, rozmiarów i struktury.
Jeśli w tym momencie nie wiesz za bardzo, o czym mówię, nie przejmuj się. Wkrótce
wszystko się wyjaśni.

Konfigurowanie interfejsu Blendera


Gdy uruchomisz Blendera po raz pierwszy i nie zmienisz ustawień domyślnych, jego
interfejs będzie wyglądał mniej więcej tak jak na rysunku 2.1. Mówię „mniej więcej”, a nie
„dokładnie”, bo Blender jest dość często aktualizowany i jest niemal pewne, że wersja
używana przez Ciebie będzie nowsza od mojej, a zatem możesz mieć przed sobą nieco
inny widok.
Wielu ludziom odpowiadają te domyślne ustawienia i używają oni Blendera bez zmie-
niania czegokolwiek. Jednak ja się do nich nie zaliczam. Wprowadzam zmiany, i to
dość znaczące. Opiszę je wszystkie wraz z uzasadnieniem, abyś mógł w pełni ocenić,
czy moje podejście jest godne naśladowania, czy nie. Oto te modyfikacje.

Ciemny motyw
Kolorystyka interfejsu Blendera jest zdefiniowana w postaci zestawów barw zwanych
motywami. Motyw domyślny zawiera średnie odcienie szarości pokazane na rysunku 2.1.
Stwierdziłem, że przy dłuższej pracy taki interfejs działa jednak rozpraszająco — oko
ludzkie w naturalny sposób kieruje się w stronę miejsc jaśniejszych. A skoro naszą uwagę
przyciąga interfejs, to trudniej się nam skupić na opracowywanym modelu. Aby temu
zaradzić, przyciemniam interfejs, włączając motyw Elsyiun pokazany na rysunku 2.2.
Konfigurowanie interfejsu Blendera 47

Rysunek 2.1. Blender w konfiguracji domyślnej (wersja 2.68a). Jeśli masz wersję późniejszą,
jej interfejs może wyglądać nieco inaczej
Źródło: Blender.

Rysunek 2.2. Motyw Elsyiun przyciemnia interfejs Blendera


Źródło: Blender.
Aby włączyć ten motyw kolorystyczny, wykonaj następujące czynności:
1. Wybierz File/User Preferences (plik/preferencje użytkownika) lub wciśnij klawisze
Ctrl+Alt+U.
2. W oknie dialogowym Blender User Preferences, które się otworzy, kliknij zakładkę
Themes (motywy).
48 Rozdział 2  Od Blendera do Unity

3. Rozwiń listę Presets (ustawienia predefiniowane) i wybierz pozycję o nazwie Elsy-


iun, tak jak pokazano na rysunku 2.3. Kolory interfejsu natychmiast się zmienią.

Rysunek 2.3. W oknie dialogowym Blender User Preferences wybierz motyw o nazwie Elsyiun
Źródło: Blender.

4. W celu zatwierdzenia wprowadzonej zmiany kliknij przycisk Save User Settings (za-
pisz ustawienia użytkownika) widoczny w dolnej części okna preferencji. Następnie
zamknij to okno, aby wrócić do głównej przestrzeni roboczej.
Jeśli później uznasz, że jednak motyw domyślny był lepszy, możesz go przywrócić przez
kliknięcie przycisku Reset to Default Theme (przywróć motyw domyślny) w oknie Blender
User Preferences.

Etykietki bez pythonowych instrukcji


Blendera używają zarówno artyści tworzący modele, jak i programiści piszący skrypty
rozwijające możliwości programu. Dlatego w ustawieniach domyślnych starano się
uwzględnić potrzeby jednych i drugich. Jednak my, twórcy gier, będziemy działać głów-
nie jako artyści, więc niepotrzebne nam będą elementy przydatne programistom.
Jednym z takich elementów są instrukcje w języku Python (język programowania do-
stępny w Blenderze jako język skryptowy) wyświetlane w etykietkach narzędziowych,
które ukazują się, gdy przytrzymasz wskaźnik myszy na jakimś przycisku lub innym
elemencie interfejsu (rysunek 2.4). Jako artyście informacje takie nie będą Ci potrzebne.
Możesz je śmiało ukryć, aby dodatkowy tekst nie angażował bez potrzeby Twojej uwagi.
Konfigurowanie interfejsu Blendera 49

Rysunek 2.4. Przy domyślnych ustawieniach Blendera w etykietkach narzędziowych wyświetlane


są informacje zarówno dla artystów, jak i programistów
Źródło: Blender.

Aby wyłączyć wyświetlanie informacji pythonowych, wykonaj następujące czynności:


1. Otwórz okno dialogowe Blender User Preferences przez wybranie polecenia File/User
Preferences.
2. Kliknij zakładkę Interface (interfejs).
3. Wyłącz opcję Show Python Tooltips (pokaż etykietki narzędziowe Pythona) — ry-
sunek 2.5.
4. Kliknij przycisk Save User Settings (zapisz ustawienia użytkownika). (Jeśli tego nie
zrobisz, dawne ustawienia powrócą po ponownym uruchomieniu programu).

Kontrolki z programu Maya


Dla mnie największym usprawnieniem w pracy z Blenderem i Unity jest możliwość
wykonywania wielu czynności w Blenderze w sposób podobny jak w programie Maya.
Przy ustawieniach domyślnych Blender oferuje własny zestaw skrótów klawiszowych
i kontrolek do nawigowania w oknach widokowych. Niestety, wszystko odbywa się tu in-
aczej niż w programie Unity, który pod tym względem nie różni się od programu Maya.
50 Rozdział 2  Od Blendera do Unity

Rysunek 2.5. Wyłączanie informacji pythonowych w oknie Blender User Preferences


Źródło: Blender.

Ponieważ często będziemy musieli używać Blendera na przemian z Unity, byłoby do-
brze, gdyby dało się uniknąć częstego przestawiania się z jednego systemu sterowania
na inny. Z doświadczenia wiem, że bez ujednolicenia tych systemów łatwo o pomyłkę,
a zastosowanie skrótu blenderowego w Unity (lub na odwrót) nie wróży nic dobrego.
Rozwiązanie tego problemu tkwi w predefiniowanym ustawieniu o nazwie Maya, za
pomocą którego można sprawić, że Blender będzie działał tak jak Unity. Po uaktyw-
nieniu tego ustawienia otrzymujemy jeden spójny system sterowania obowiązujący
w obu aplikacjach.

Uwa ga
Ktoś może zapytać, dlaczego upodobniłem Blendera do Unity, a nie na odwrót. Powód jest wręcz banal-
ny: po prostu Blender jest pod względem konfigurowalności bardziej elastyczny i nawet ma już wbudo-
wane gotowe ustawienia, więc po co się męczyć, skoro można to zrobić szybko i skutecznie.

Zmianę systemu sterowania Blenderem można przeprowadzić na dwa sposoby. Pierw-


szy polega na wybraniu odpowiedniej opcji na ekranie powitalnym, a drugi wymaga po-
służenia się oknem dialogowym Blender User Preferences. W pierwszym przypadku
należy:
1. Uruchomić Blendera.
2. Na ekranie powitalnym rozwinąć listę Interactions (interakcje) i wybrać z niej
opcję Maya — tak jak na rysunku 2.6.
„Błąd” zamykania bez zapisu 51

Rysunek 2.6. Wybieranie systemu sterowania Blenderem na ekranie powitalnym


Źródło: Blender.

W s k a z ów ka
Ekran powitalny można wyświetlić również w trakcie pracy z Blenderem. W tym celu należy kliknąć
ikonkę Blendera widoczną w nagłówku okna informacyjnego, który domyślnie znajduje się przy górnej
krawędzi interfejsu (na rysunku 2.6 ikonka ta jest zaznaczona kółkiem).

Drugi sposób wymaga następujących czynności:


1. Wybierz polecenie File/User Preferences.
2. W oknie dialogowym Blender User Preferences, które się otworzy, kliknij zakładkę
Input (wejście).
3. Rozwiń listę Presets i wybierz pozycję o nazwie Maya (rysunek 2.7)1.
4. W celu zatwierdzenia wprowadzonej zmiany kliknij przycisk Save User Settings.

„Błąd” zamykania bez zapisu


Zanim przejdziemy do bardziej zasadniczych spraw, chciałbym omówić kwestię po-
zornego błędu, który stał się już sławny w społeczności blenderowej. Otóż istnieje nie-
pisane prawo, które mówi, że każda aplikacja użytkowa powinna reagować na polece-
nie zamknięcia odpowiednim komunikatem, jeśli użytkownik nie zapisał aktualnego

1
Listy są dwie (na rysunku rozwinięta jest tylko jedna): jedna odnosi się do operacji wykonywanych
za pomocą myszy, a druga do skrótów klawiszowych. Ekran powitalny ustawia obie listy w należyty
sposób — przyp. tłum.
52 Rozdział 2  Od Blendera do Unity

Rysunek 2.7. Ustawianie systemu sterowania Blenderem w oknie dialogowym Blender User
Preferences
Źródło: Blender.

stanu swojej pracy. Niemal wszystkie programy, od pakietów Microsoft Office i Li-
breOffice aż po zaawansowane programy graficzne, takie jak Unity czy GIMP, w pełni
respektują to prawo, a Blender nie! Gdy go zamykasz, po prostu znika z ekranu i robi
tak niezależnie od tego, czy zapisałeś rezultat swojej pracy, czy nie. A gdy go urucha-
miasz ponownie, jakby nigdy nic wyświetla nową, świeżą scenę i nadal nie daje żadnego
znaku, że tamta niezapisana scena nadal istnieje i możesz do niej wrócić. Już niejeden
użytkownik uznał, że wiele godzin pracy zostało bezpowrotnie stracone. W takich
chwilach rzeczywiście można wpaść w furię, zwłaszcza jeśli sobie uświadomimy, że
przecież można było wszystkiego uniknąć, gdyby tylko Blender „zachował się” w spo-
sób konwencjonalny i wyświetlił stosowne ostrzeżenie.

Uwa ga
Niektórzy próbowali uzasadniać „brak tej funkcji”, twierdząc, że użytkownik Blendera powinien być
profesjonalistą i dbać o rezultaty swojej pracy. Uważam jednak takie podejście za co najmniej niewła-
ściwe, ponieważ ignoruje ono fakt, że każdemu (również profesjonaliście) może się zdarzyć przypadko-
we zamknięcie aplikacji bez zapisania opracowywanego pliku. Na szczęście problem jest tylko pozorny!
Czytaj dalej…

Przekonanie, że Blender pozwala na utratę niezapisanych zmian, jest błędne. Jego twórcy
przewidzieli takie sytuacje i zaimplementowali metodę odzyskiwania rezultatów po-
przedniej sesji. Wystarczy po prostu wybrać polecenie File/Recover Last Session
Przenoszenie modeli z Blendera do Unity 53

(plik/odtwórz ostatnią sesję) — rysunek 2.8. Polecenie działa, ponieważ Blender tuż
przed zamknięciem zapisuje bieżącą scenę w pliku quit.blend i wystarczy ten plik otwo-
rzyć. Wydaje się to całkiem proste (i tak jest — wszystko sprowadza się przecież tylko do
kliknięcia odpowiedniego polecenia w menu), ale przeświadczenie o niedopracowaniu
Blendera powoduje, że możliwość przywrócenia poprzedniej sesji często uchodzi uwadze
użytkownika.

Rysunek 2.8. Przywracanie poprzedniej sesji w celu odzyskania niezapisanych danych


Źródło: Blender.

Być może to, co napisałem, nie do końca Cię przekonuje i nadal uważasz, że wzorem
innych aplikacji Blender powinien wyświetlać ostrzeżenie o niezapisanych zmianach.
Proponuję jednak odłożyć te dywagacje na bok. Nie piszę książki o tym, jakie funkcje
dany program powinien zawierać, a jakich nie. Piszę o tym, jaki program jest i co
można za jego pomocą zrobić. Sądzę, że tylko przy takim nastawieniu da się w pełni
wykorzystać te możliwości programu, które w nim tkwią.

Przenoszenie modeli z Blendera do Unity


Jednym z zagadnień, które są najczęściej dyskutowane w rozmowach na temat toku
pracy z użyciem Blendera i Unity, jest przenoszenie modeli wygenerowanych w Blenderze
do silnika Unity. Popularną metodą jest zapisanie blenderowej sceny w pliku .blend
54 Rozdział 2  Od Blendera do Unity

(natywny format Blendera) za pomocą polecenia File/Save (plik/zapisz), a następnie


otwarcie tego pliku w Unity. Resztą zajmuje się już Unity — przynajmniej w teorii!
Czasami — zależnie od okoliczności — otrzymasz dokładnie to, o co Ci chodziło, i nie
musisz niczego poprawiać, ale najczęściej rezultaty będą trudne do zaakceptowania.
Może się również zdarzyć, że ta prosta metoda w ogóle nie zadziała. Wyjaśnię teraz,
dlaczego tak się dzieje, a potem na konkretnym przykładzie przedstawię właściwe
rozwiązanie.

Uwa ga
Na razie zajmujemy się eksportowaniem blenderowych modeli do Unity w sensie ogólnym. Pomijamy
szczegóły dotyczące modeli animowanych, takich jak rigowane siatki postaci człekokształtnych lub innych
stworów. Wrócimy do nich w dalszej części książki.

Pliki .blend
Blender domyślnie tworzy pliki w formacie .blend. Dlatego gdy wydasz mu polecenie
File/Save (plik/zapisz), zapisze bieżącą scenę w pliku z rozszerzeniem .blend. Na szczę-
ście Unity potrafi odczytywać takie pliki, więc możesz ich używać do przenoszenia
danych z jednego programu do drugiego. Po prostu przeciągnij plik z Eksploratora
lub Findera i upuść w obrębie interfejsu Unity.
Metoda wydaje się interesująca, ale jest kilka powodów, dla których zdecydowanie od-
radzam jej stosowanie.
■ Unity do zaimportowania pliku .blend potrzebuje Blendera. Unity odczytuje
pliki .blend, ale nie bezpośrednio. Tak naprawdę akceptuje tylko formaty: FBX,
DAE, 3DS, DXF i OBJ. Gdy ma zaimportować dane z innego pliku, uruchamia
w tle program macierzysty (Blendera dla pliku .blend) i za jego pomocą konwertuje
ten plik na format FBX. A zatem każdy, kto chce importować pliki .blend do Unity,
musi mieć zainstalowanego Blendera, nawet gdy nie ma zamiaru go używać. Unity
potrzebuje go do przeprowadzenia konwersji. Wprawdzie Blender jest darmowy,
ale już sama konieczność jego instalacji tylko po to, by otworzyć jakiś plik, może być
irytująca — tym bardziej, że da się tego uniknąć (o tym za chwilę).
■ Pliki .blend ograniczają liczbę opcji eksportu i zwiększają ryzyko niekompaty-
bilności. Gdy Unity przeprowadza konwersję, nie masz na ten proces żadnego wpły-
wu. Stosowane są wtedy ustawienia domyślne, które przecież nie zawsze są optymal-
ne, i w rezultacie otrzymujesz niekoniecznie prawidłową siatkę. Oczywiście może
się zdarzyć, że wszystko pójdzie dobrze, ale nie mając na nic wpływu, możesz li-
czyć tylko na szczęśliwy przypadek. Poza tym dochodzi jeszcze ryzyko wynikające
z częstych modyfikacji samego Blendera. Jeśli do konwersji pliku zostanie użyta inna
wersja niż ta, za pomocą której go wygenerowano, rezultat może być trudny do
przewidzenia.
Przenoszenie modeli z Blendera do Unity 55

■ Pliki .blend są zbyt duże. Nie jest to zarzut pod adresem tego formatu, lecz stwier-
dzenie, że przy ustawieniach domyślnych Unity z pomocą Blendera przeniesie do
formatu FBX całą zawartość sceny, włącznie z obiektami, które nie powinny być
importowane, np.: kamery, lampy, niewidoczne siatki, obiekty pozorne. W Blenderze
są przydatne, ale ich import do Unity na ogół nie ma sensu.
Uwa ga
Więcej informacji na temat formatów 3D i ich technicznych uwarunkowań znajdziesz w instrukcji obsługi
programu Unity dostępnej pod adresem: http://docs.unity3d.com/Documentation/Manual/3D-formats.html.

Ćwiczenie: ręczny eksport do FBX


Po przeczytaniu powyższych uwag raczej nie będziesz przenosił modeli z Blendera do
Unity za pomocą plików .blend. O ile na wczesnym etapie prac, podczas testowania
siatek, możesz się jeszcze nimi posługiwać, o tyle do importowania gotowych zasobów
powinieneś używać wyłącznie plików w formacie FBX — tym bardziej, jeśli będą to
zasoby przekazywane innym członkom zespołu.
Jak już wspominałem, Unity posługuje się wewnętrznie formatem FBX nawet wtedy,
gdy importuje pliki .blend. Ale jeśli sam wyeksportujesz z Blendera plik FBX, będziesz
miał większą kontrolę nad jego zawartością niż podczas automatycznej konwersji pliku
.blend. Ponadto uniezależnisz Unity od innych programów, bo z formatem FBX radzi
sobie bez żadnej pomocy z zewnątrz.
W ćwiczeniu tym pokażę na przykładzie zwykłego stożka, jak takie eksportowanie
należy przeprowadzać. Naturalnie Twoje modele będą bardziej rozbudowane i skom-
plikowane, ale wszystko, co tutaj powiem, ma zastosowanie do wszystkich modeli: pro-
stych i złożonych. Więc zaczynajmy!

Tworzenie modeli
To ćwiczenie zaczniemy od zupełnie nowej sceny w Blenderze (zob. rysunek 2.1 lub
2.2). W codziennej pracy do eksportowania będziesz przystępował ze sceną zawierającą
gotowe modele. Jednak tym razem usuwamy wszystko z wyjątkiem kamery. W pustej
scenie umieść zwykły stożek — wybierz polecenie Add/Mesh/Cone (dodaj/siatkę/stożek).
Będzie to model, który wyeksportujesz z przeznaczeniem umieszczenia go w Unity
(rysunek 2.9).

Radzenie sobie z wadami cieni


Uwa ga
Ten punkt i następny zachowują ważność, pod warunkiem że używasz Blendera w wersji wcześniejszej niż 2.69.
Właśnie w tym wydaniu aplikacji dodano funkcję dzielenia normalnych, która likwiduje omawiane tu usterki.
Więcej informacji na ten temat znajdziesz pod adresem: http://wiki.blender.org/index.php/Dev:Ref/Release_
Notes/2.69. Jeśli używasz wersji 2.69 lub nowszej, możesz od razu przejść do punktu zatytułowanego
„Środek obiektu”.
56 Rozdział 2  Od Blendera do Unity

Rysunek 2.9. W pustej scenie Blendera umieść stożek


Źródło: Blender.

Idźmy dalej. Jeśli od razu przeniesiesz siatkę stożka z Blendera do Unity, czy to w pliku
.blend, czy FBX (o którym więcej już za chwilę), najprawdopodobniej będziesz miał
problem z wyrenderowaniem prawidłowych cieni na jej powierzchni. Zauważysz to,
gdy tylko spojrzysz na siatkę w oknie widokowym Unity lub w polu podglądu na panelu
Inspector (inspektor). Siatka zostanie wygładzona i będzie wyglądała dziwnie. Problem
wynika z odmiennego podejścia obu programów do roli, jaką powinny odgrywać
normalne. Rozbieżności w wyglądzie stożka wyświetlanego w Blenderze i w Unity są
pokazane na rysunku 2.10.

Rysunek 2.10. Problem z cieniowaniem powierzchni siatki. Tutaj rozbieżności w cieniowaniu między
Blenderem i Unity najlepiej widać przy krawędzi łączącej powierzchnię boczną stożka z jego podstawą
Źródło: Blender.
Przenoszenie modeli z Blendera do Unity 57

Uwa ga
Dalszy ciąg tego punktu przedstawia sytuację hipotetyczną, więc nie musisz tego czytać. Chciałem Ci tylko
pokazać, na jaki problem możesz natrafić, jeśli postąpisz zgodnie z podanym opisem. Innym efektem, jaki
napotkasz, będą dużo mniejsze wymiary siatki w Unity aniżeli w Blenderze. Wynika to z domyślnie
przyjmowanej przez Unity skali o wartości 0,01. Możesz się o tym przekonać, sprawdzając tę wartość w pa-
nelu Inspector, gdy siatka jest zaznaczona (rysunek 2.11). Aby to naprawić, po prostu zwiększ parametr
Scale Factor (współczynnik skali) do poziomu 1. (Zagadnienie to będzie jeszcze omawiane).

Rysunek 2.11. Przez ponowne przeliczenie normalnych w Unity można szybko naprawić błędy
cieniowania
Źródło: Blender.

W przypadku modeli tak prostych jak sześciany, stożki czy kule problem cieniowania
można szybko rozwiązać w Unity. Trzeba tylko zaznaczyć właściwą siatkę w panelu
Project (projekt), po czym w panelu Inspector wybrać z listy rozwijanej Normals (nor-
malne) opcję Calculate (oblicz). (Nie zapomnij kliknąć potem przycisku Apply, czyli
„zastosuj”, aby zatwierdzić wprowadzone zmiany). Unity na podstawie kątów między
ściankami ustali, które krawędzie mają być wygładzone, a które powinny pozostać
ostre. W rezultacie otrzymasz stożek wyglądający niemal tak samo jak w Blenderze
(zob. rysunek 2.11). Możesz zatem powiedzieć, że między aplikacjami występuje relacja
podobieństwa 1:1.
Powyższa metoda „naprawiania” błędów cieniowania ma jednak istotne ograniczenia.
Jest to działanie automatyczne i nie masz żadnego wpływu na to, które krawędzie zo-
staną zacieniowane ostro, a które łagodnie. W przypadku stożka jest to wystarczające, ale
przecież nie tylko takie siatki chciałbyś importować. Dlatego musimy wrócić do Blendera
i tam odpowiednio przygotować model do eksportu. A zatem, jeśli wraz ze mną prze-
nosiłeś stożek za pośrednictwem pliku .blend, usuń go teraz z Unity i ponownie otwórz
Blendera.
58 Rozdział 2  Od Blendera do Unity

Ostrość krawędzi i modyfikator Edge Split


W poprzednim punkcie pokazałem jeden sposób na rozwiązanie problemu złego cie-
niowania, a teraz zaprezentuję metodę pewniejszą i najczęściej stosowaną.
Jeśli chcesz, żeby po zaimportowaniu do Unity siatka wyglądała prawidłowo i nie ufasz
zbytnio mechanizmom przeliczania normalnych w tej aplikacji, musisz jeszcze w Blen-
derze wskazać dokładnie, które krawędzie mają pozostać ostre. Ostra krawędź to takie
miejsce na powierzchni siatki, gdzie spotykają się dwie ścianki, a ich cieniowania pozo-
stają całkowicie odrębne — nie są w żaden sposób uśredniane. Zazwyczaj są to kanty
takich brył jak sześcian czy graniastosłup, ale mogą to być także nagłe załamania ścian
pod kątem 90º. Natomiast większość obiektów o kształtach organicznych, np. ludzka
twarz, ma powierzchnie gładkie i nie ma tam miejsca na ostre krawędzie.
W przykładowym stożku powinieneś wskazać jako ostre krawędzie tworzące obwód jego
podstawy, tam bowiem łączą się dwie zupełnie odrębne powierzchnie. Zaznacz więc
cały obwód podstawy, po czym wybierz polecenie Mesh/Edges/Mark Sharp (siatka/
krawędzie/oznacz jako ostre) — tak jak na rysunku 2.12.

Rysunek 2.12. Krawędzie na obwodzie podstawy stożka oznacz jako ostre


Źródło: Blender.

Wskazanie krawędzi, które powinny być ostre, to dopiero pierwszy krok. Teraz trzeba
jeszcze poddać siatkę działaniu modyfikatora o nazwie Edge Split (rozcinanie krawędzi),
który porozcina siatkę wzdłuż ostrych krawędzi i w ten sposób wymusi na Unity odrębne
cieniowanie rozłącznych powierzchni. Nie bój się, że przez taki zabieg zniszczysz siatkę,
bo wszystko dzieje się w sposób odwracalny — modyfikator działa w Blenderze i zawsze
możesz go wyłączyć, a wtedy siatka powróci do stanu pierwotnego (z nierozciętymi
krawędziami).
Przenoszenie modeli z Blendera do Unity 59

Aby zastosować modyfikator Edge Split, wykonaj następujące czynności:


1. Zaznacz siatkę stożka.
2. Otwórz zakładkę Object modifiers (modyfikatory obiektu) panelu Properties (wła-
ściwości) — rysunek 2.13.

Rysunek 2.13. Modyfikator Edge Split znajduje się na zakładce Object modifiers
Źródło: Blender.

3. Na zakładce Object modifiers rozwiń listę Add Modifier (dodaj modyfikator) i wskaż
opcję Edge Split. Modyfikator o takiej właśnie nazwie zostanie przypisany do obiektu
stożka.
4. W właściwościach modyfikatora wyłącz opcję Edge Angle (kąt krawędzi), ale pozo-
staw włączoną funkcję Sharp Edges (ostre krawędzie) — tak jak na rysunku 2.14.
W ten sposób nakażesz Blenderowi rozcięcie siatki tylko wzdłuż tych krawędzi,
które oznaczyłeś jako ostre, a nie na podstawie kąta między przyległymi ściankami.

Ostrzeżeni e
Nie klikaj przycisku Apply (zastosuj) w właściwościach modyfikatora (zob. rysunek 2.14), bo spowodujesz
zatwierdzenie wprowadzonych zmian, a to będzie oznaczało, że staną się nieodwracalne. Po prostu zostaw
modyfikator takim, jakim jest. Wrócisz do niego później, gdy będziesz eksportował stożek do pliku FBX.
60 Rozdział 2  Od Blendera do Unity

Rysunek 2.14. Dodaj do stożka modyfikator Edge Split, aby wyostrzyć oznaczone krawędzie
Źródło: Blender.

Uwa ga
Zatwierdzenie (zastosowanie) modyfikatora przypisanego siatce wprowadza zmiany „nieodwracalne”,
albo inaczej „stałe”, w sensie umownym. Należy to rozumieć jako niemożność odłączenia modyfikatora
od obiektu i w ten sposób anulowania skutków jego działania. Jedynym sposobem na przywrócenie stanu
pierwotnego jest ręczne zmodyfikowanie siatki — przez ponowne ustawienie wierzchołków, krawędzi
i ścianek.

Środek obiektu
Zarówno w Unity, jak i w Blenderze każdy obiekt ma określony punkt, zwany w Unity
środkiem transformacji (pivot), a w Blenderze po prostu środkiem (origin). (Ja będę
używał nazwy blenderowej). Jest to punkt odniesienia dla geometrii siatki. Jeśli ją
przesuniesz do nowego położenia o określonych współrzędnych scenicznych, to właśnie
tam znajdzie się jej środek. Jeśli ją będziesz obracał, to właśnie ten punkt będzie środkiem
obrotu. Krótko mówiąc: jest to początek lokalnego układu współrzędnych siatki. Gdy
ją eksportujesz z Blendera, zapewne chciałbyś, aby położenie tego punktu było takie
jak należy. Właśnie teraz pokażę Ci, jak to osiągnąć. Na rysunku 2.15 zaznaczyłem za-
równo środek stożka, jak i miejsce na zakładce Object (obiekt), gdzie możesz odczytać
jego położenie we współrzędnych globalnych. (Gizmo transformacji jest umieszczone
dokładnie w środku siatki).
Przenoszenie modeli z Blendera do Unity 61

Rysunek 2.15. Globalne (światowe, sceniczne) współrzędne położenia zaznaczonego obiektu można
odczytać na zakładce Object panelu Properties. W oknie widokowym środek obiektu jest wskazywany
przez gizmo transformacji
Źródło: Blender.

Podczas modelowania w Blenderze często środek obiektu ląduje nie tam, gdzie byśmy
chcieli. Czasami trzeba go umieścić w ściśle określonym położeniu względem siatki.
Na przykład gdy obiektem jest postać człekokształtna, wskazane jest umieszczenie środka
jej siatki na dolnej powierzchni stopy, żeby po zaimportowaniu do Unity właśnie tą
częścią stykała się z podłożem.
Na rysunku 2.15 środek stożka domyślnie pokrywa się z jego środkiem masy. (Wska-
zuje na to położenie gizma transformacji). Widać też, że pokrywa się on również z po-
czątkiem globalnego układu współrzędnych. Załóżmy, że chcesz go umieścić na pod-
stawie stożka, aby przy współrzędnych globalnych równych (0,0,0) bryła spoczywała na
podłożu, a nie pod nim. Żeby to uzyskać, wykonaj następujące czynności:
1. W oknie widokowym Blendera zaznacz stożek.
2. Włącz przyciąganie przyrostowe (Incremental Snapping) w sposób pokazany na
rysunku 2.16. Jeśli teraz będziesz przesuwał stożek, będzie się on przemieszczał sko-
kowo zgodnie z odległościami między liniami blenderowej siatki konstrukcyjnej,
a nie płynnie jak przy przesuwaniu swobodnym.
3. Za pomocą gizma transformacji przesuń stożek w górę, aby jego podstawa znalazła
się w siatce konstrukcyjnej. Zauważ, że w Blenderze oś skierowana do góry to oś Z
i w trakcie przesuwania stożka w górę zmienia się wartość tej współrzędnej. Teraz
położenie stożka powinno być określone wartościami (0,0,1). Jednak środek siatki
przesunął się wraz z nią. Spójrz na rysunek 2.17. Stożek spoczywa na podłożu, tak
62 Rozdział 2  Od Blendera do Unity

Rysunek 2.16. Włącz przyciąganie przyrostowe, aby móc przesuwać obiekt skokowo zgodnie
z siatką konstrukcyjną
Źródło: Blender.

jak chcieliśmy, ale jego środek (wskazywany przez gizmo transformacji) nadal po-
krywa się ze środkiem masy, a nie z podłożem. Musimy to tak skorygować, żeby
bez przesuwania siatki jej środek znów znalazł się w punkcie o współrzędnych glo-
balnych (0,0,0).

Rysunek 2.17. Przesunięcie stożka w górę spowodowało, że jego środek nie jest już w początku
globalnego układu współrzędnych
Źródło: Blender.
Przenoszenie modeli z Blendera do Unity 63

4. Aby z powrotem umieścić środek stożka w początku globalnego układu współrzęd-


nych, użyj blenderowego kursora 3D (widoczny w oknie widokowym jako włosowaty
krzyżyk celowniczy). Ustaw ten kursor w początku układu współrzędnych globalnych.
W tym celu wybierz polecenie Object/Snap/Cursor to Center (obiekt/przyciągnij/
kursor do środka) — tak jak na rysunku 2.18.

Rysunek 2.18. W ramach przygotowań do przesunięcia środka stożka ustaw kursor 3D


w początku globalnego układu współrzędnych
Źródło: Blender.

5. Po ustawieniu kursora 3D w początku globalnego układu współrzędnych przycią-


gnij do niego środek stożka. W ten sposób początek lokalnego układu współrzędnych
siatki pokryje się z początkiem układu globalnego. Aby to zrealizować, zaznacz siatkę
stożka (jeśli jeszcze nie jest zaznaczona), a następnie wybierz Object/Transform/
Origin to 3D Cursor (obiekt/przekształć/środek do kursora 3D). Gizmo transfor-
macji przesunie się do środka globalnego układu współrzędnych, a to będzie oznaczało,
że tam też znajduje się środek stożka. Co więcej, współrzędna Z stożka będzie teraz
miała wartość 0, a nie, jak dotychczas, 1. Rezultat jest pokazany na rysunku 2.19.
64 Rozdział 2  Od Blendera do Unity

Rysunek 2.19. Umieść środek siatki w środku sceny, a proces importu w Unity będzie bardziej
przewidywalny
Źródło: Blender.

Obracanie obiektów
Niestety, to nie wszystko. Jest jeszcze kilka rzeczy do zrobienia, jeśli chcesz, aby prze-
noszenie siatki z Blendera do Unity przebiegło bezboleśnie i zakończyło się w sposób
przewidywalny.
Aby zilustrować kolejne zadanie, jakie zostało do wykonania, rozważmy następujący
scenariusz. Jeśli teraz przeniesiesz stożek z Blendera do Unity — czy to za pomocą pliku
.blend, czy FBX — jego wygląd w panelu Project na pierwszy rzut oka będzie prawidłowy.
Lecz jeśli przyjrzysz się uważniej, zauważysz, że coś jest nie tak z orientacją stożka.
Wygląda, jakby był obrócony o 90º lub 270º. I rzeczywiście tak jest (rysunek 2.20).
Zaznaczenie siatki w panelu Project i sprawdzenie jej transformacji w panelu Inspector
w pełni potwierdza taką diagnozę. Podczas importu w Unity siatka została obrócona
o 270º wokół osi X, chociaż w Blenderze jej obroty wokół każdej osi były zerowe
(u Ciebie oś obrotu może być inna). Istnieje tutaj wyraźna rozbieżność. Mamy więc do
czynienia z niedopasowaniem domyślnych orientacji obiektu w Blenderze i Unity.

Uwa ga
Jeśli w tym stanie przeciągniesz siatkę z panelu Project i umieścisz ją w scenie Unity, najprawdopodob-
niej jej orientacja zostanie skorygowana automatycznie, a nawet jeśli tak się nie stanie, możesz to zrobić
ręcznie za pomocą stosownego manipulatora. Niektórych takie rozwiązanie zadowala, ale mnie nie. Ja
zawsze dążę do tego, by importowane siatki miały ustawienia standardowe — położenie (0,0,0), obrót
(0,0,0) i skalę (1,1,1). Dzięki temu unikam kłopotów związanych z niewłaściwymi wartościami począt-
kowymi tych trzech transformacji.
Przenoszenie modeli z Blendera do Unity 65

Rysunek 2.20. Podczas przenoszenia z Blendera do Unity siatka jest obracana wokół jednej z osi
o 90º lub 270º
Źródło: Unity Technologies.

Problem z obrotem wynika z fundamentalnej rozbieżności między układami współ-


rzędnych w Blenderze i w Unity. W Unity osią skierowaną do góry jest Y, a w Blenderze
taką osią jest Z. Dlatego przy przejściu do przestrzeni o innej orientacji obiekt jest obra-
cany o 90º lub 270º. Rozwiązanie polega na wykonaniu obrotu kompensacyjnego w pro-
gramie macierzystym (Blenderze). Zabieg jest dwuetapowy. Pierwszy krok wykonamy
teraz, a drugi dopiero po zapoznaniu się z blenderowym eksporterem FBX.
A zatem, jeśli razem ze mną wykonywałeś poprzednie czynności, usuń siatkę stożka
w Unity i wróć do Blendera. W oknie widokowym zaznacz stożek i za pomocą odpo-
wiedniej kontrolki w panelu Properties obróć go o -90º wokół osi X. Niektóre siatki bę-
dziesz musiał także obrócić o 180º wokół osi Y, aby po zaimportowaniu do Unity były
zwrócone do ekranu przodem, a nie tyłem. Spójrz na rysunek 2.21.
Po wykonaniu kompensacyjnego obrotu musisz to przekształcenie zatwierdzić. Cho-
dzi o takie „wypalenie” lub „zakodowanie” tego przekształcenia, żeby z blenderowego
punktu widzenia nadal wszystkie obroty miały wartość zerową. Żeby coś takiego osią-
gnąć, upewnij się, że siatka jest zaznaczona, po czym wybierz polecenie Object/Apply/
Rotation & Scale (obiekt/zastosuj/obrót i skalowanie) — rysunek 2.22. I to na razie
wszystko! Wrócimy do tej kwestii, gdy będziemy eksportować model do pliku FBX.
66 Rozdział 2  Od Blendera do Unity

Rysunek 2.21. Przed wyeksportowaniem do formatu FBX nadaj siatce odpowiednią orientację
Źródło: Blender.

Rysunek 2.22. Zatwierdź transformację obiektu


Źródło: Blender.
Przenoszenie modeli z Blendera do Unity 67

Nazywanie obiektów
Ten etap procesu eksportowania jest opcjonalny. Przecież możesz z powodzeniem
przenieść model do Unity bez nadawania mu specjalnej nazwy, a dla gracza nie będzie
to miało żadnego znaczenia. Lecz jeśli gra ma zawierać dużo rozmaitych modeli, to
warto poświęcić trochę czasu i ponadawać im jakieś sensowne nazwy, aby później
można było łatwiej znaleźć to, czego się szuka. Nie lekceważ tej sprawy, bo bez dobre-
go systemu nazewnictwa szybko wkrada się bałagan i organizacja pracy zaczyna kuleć.
Dlatego nadawaj nazwy modelom już w Blenderze.
Blender automatycznie przypisuje stożkowi nazwę Cone (stożek). Jednak na ogół bę-
dziesz chciał zmienić taką domyślną nazwę na bardziej unikatową. Spróbujmy zatem
nadać stożkowi nazwę MyCone (mój stożek). W tym celu zaznacz bryłę w oknie wido-
kowym, dwukrotnie kliknij jej dotychczasową nazwę w panelu Outliner (organizator)
i zastąp ją nową (rysunek 2.23). I to wszystko! Teraz możemy rozpocząć eksportowanie
siatki do pliku FBX.

Rysunek 2.23. Nadaj obiektowi sensowną nazwę, aby później móc sprawniej pracować
Źródło: Blender.

Eksportowanie do pliku FBX


Wszystko, co robiliśmy do tej pory, było przygotowaniem do tego kroku. Teraz użyjemy
blenderowego narzędzia eksportującego i za jego pomocą zapiszemy stożek w pliku
FBX, aby stamtąd już bez żadnych niespodzianek mógł być zaimportowany w Unity.
Wcześniej uzasadniałem, dlaczego lepiej jest importować siatki w Unity z plików FBX,
a nie z plików .blend, a teraz, podtrzymując wszystkie tamte stwierdzenia, chcę powie-
dzieć, że pliki .blend również powinny odgrywać ważną rolę w Twojej pracy. Nigdy nie
68 Rozdział 2  Od Blendera do Unity

zapominaj o zapisywaniu swoich scen właśnie w tych plikach, bo tylko dzięki temu
będziesz miał do nich pełny dostęp i w razie potrzeby będziesz mógł wprowadzać nie-
zbędne zmiany. Jeśli zdecydujesz się na modyfikowanie siatki, nie wczytuj jej do Blendera
z pliku FBX, lecz załaduj ją z pliku .blend. Plik FBX traktuj wyłącznie jako medium
pośredniczące w przenoszeniu modeli z Blendera do Unity. Dlatego zanim wyeks-
portujesz siatkę do pliku FBX, zapisz ją w pliku .blend, wydając Blenderowi standardowe
polecenie File/Save (plik/zapisz).
Aby zaznaczoną siatkę wyeksportować do pliku FBX, wykonaj następujące czynności:
1. Zaznacz przeznaczoną do eksportu siatkę i wybierz File/Export/Autodesk FBX
(.fbx) (plik/eksportuj/Autodesk FBX) — rysunek 2.24. Otworzy się okno narzędzia
eksportującego z wieloma opcjami i parametrami eksportu. Dla siatek nieanimowa-
nych, czyli takich jak stożek, najlepsze będą ustawienia pokazane na rysunku 2.25.

Rysunek 2.24. Przed rozpoczęciem eksportu zaznacz właściwą siatkę


Źródło: Blender.

2. Nadaj plikowi sensowną nazwę. Ja wpisałem Cone.fbx, co widać na rysunku 2.25.


Każda eksportowana siatka powinna mieć własną, unikatową i opisową nazwę.
3. Na rolecie Export FBX (eksport FBX) zaznacz opcję Selected Objects (zaznaczone
obiekty). Spowoduje to, że wyeksportowane zostaną tylko obiekty zaznaczone, a nie
cała scena. Jeśli nie włączysz tej opcji, wszystkie siatki zostaną skomasowane w jedną
grupę i wyeksportowane.
Przenoszenie modeli z Blendera do Unity 69

Rysunek 2.25. Ustawienia eksportu dla siatek statycznych


Źródło: Blender.

Uwa ga
Parametr Scale (skala) ma domyślną wartość 1.00 i w większości przypadków byłaby ona odpowiednia.
Jednakże, jak się wkrótce przekonasz, Unity zupełnie pomija ten parametr bez względu na jego wartość.
W zamian stosuje własną skalę o wartości 0.01, czy tego chcesz, czy nie. Później pokażę, jak sobie z tym
problemem radzić.

4. Określ kierunki Forward (w przód) i Up (w górę). Jest to drugi etap procesu roz-
poczętego w punkcie „Obracanie obiektów”. Ustawienia te w połączeniu z odpo-
wiednią orientacją obiektu w scenie gwarantują mu właściwą orientację również
po zaimportowaniu w Unity. Zazwyczaj kierunki te należy ustawiać zgodnie z kie-
runkami osi w Blenderze, czyli w polu Forward należy ustawić Y Forward, a w polu
Up — Z Up. Czasami będziesz musiał trochę pokombinować z tymi ustawieniami,
zanim siatka zostanie zaimportowana ze standardowymi wartościami transformacji,
czyli z położeniem (0,0,0), obrotem (0,0,0) i skalą (1,1,1), a mimo to będzie miała
właściwą orientację.
70 Rozdział 2  Od Blendera do Unity

5. Upewnij się, że zaznaczona jest opcja Apply Modifiers (zastosuj modyfikatory). Jest
to konieczne, aby wszystkie modyfikatory przypisane siatce, włącznie z Edge Split
(opisanym w punkcie „Ostrość krawędzi i modyfikator Edge Split”), zostały zako-
dowane w eksportowanej siatce. (Opcja ta nie spowoduje zatwierdzenia żadnego
modyfikatora w pierwotnej blenderowej scenie; ma wpływ jedynie na siatkę, która
jest generowana podczas eksportu i zapisywana w pliku FBX).
6. Dla siatek nieanimowanych (statycznych) wyłącz opcje Include Animation (dołącz
animację) i Optimize Keyframes (optymalizuj klatki kluczowe). O eksportowaniu
siatek animowanych będzie mowa w dalszej części książki.

Uwa ga
Zamiast FBX możesz użyć formatu Collada (.dae). Użyj wtedy polecenia File/Export/Collada (plik/eksportuj/
Collada). Format ten obsługuje siatki zarówno statyczne, jak i animowane. Więcej informacji na jego temat
znajdziesz pod adresem: https://collada.org/.

Zawartość pliku FBX


Podczas eksportowania Blender tworzy plik FBX możliwy do odczytania w Unity.
Przyjrzyjmy mu się nieco dokładniej. Warto to zrobić, bo plik zawiera czytelne dla
człowieka (tekst ASCII) i edytowalne zapisy właściwości eksportowanej siatki. W razie
potrzeby można tu jeszcze coś poprawić. Do przeglądania i edycji zawartości takiego
pliku można użyć dowolnego edytora tekstowego, takiego jak Notepad, Notepad++
czy nawet MonoDevelop (rysunek 2.26).

Rysunek 2.26. Pliki FBX zawierają czytelny dla człowieka tekst ASCII, który można modyfikować
w dowolnym edytorze tekstowym lub zintegrowanym środowisku programistycznym (IDE)
Źródło: MonoDevelop.
Ćwiczenie: importowanie plików FBX w Unity 71

Uwa ga
Teoretycznie ręczne manipulowanie w prawidłowo wyeksportowanych plikach FBX nie powinno być
potrzebne. Ale mimo wszystko warto wiedzieć, że taka możliwość istnieje. Warto też wiedzieć, że pliki
te można analizować i przetwarzać również w trybie wsadowym.

Ćwiczenie: importowanie plików FBX w Unity


Po wyeksportowaniu siatki FBX z Blendera zapewne będziesz chciał ją zaimportować
w Unity, aby tam dołączyć ją do gry. W tym celu po prostu przeciągnij odpowiedni
plik z Eksploratora (Windows) lub Findera (Mac OS) na panel Project w Unity (rysunek
2.27). Ale to jeszcze nie wszystko. Najprawdopodobniej pewne ustawienia będą wyma-
gały dostrojenia. W tym ćwiczeniu zajmiemy się również takimi sprawami.

Rysunek 2.27. Importowanie plików FBX do panelu Projekt w Unity


Źródło: Unity Technologies.

Współrzędne UV mapy światła


Gdy będziesz importował statyczną siatkę terenu, budowli lub innego elementu środowi-
ska gry, zapewne będziesz chciał ją oświetlić metodą mapowania światła. Do realizacji te-
go rodzaju oświetlenia możesz użyć narzędzia Beast Lightmapper dostępnego w Unity
po wybraniu polecenia Window/Lightmapping (okno/mapowanie światła). Mapowanie
światła polega na określaniu, jak dana siatka reaguje na panujące w jej otoczeniu warunki
oświetleniowe — jakie rzuca cienie, jakie tworzy odblaski — i zapisywaniu takich in-
formacji w formie specjalnej tekstury. Tekstura taka, zwana mapą światła, jest potem
nakładana na powierzchnię siatki, co sprawia, że ta ostatnia wygląda, jakby rzeczywi-
ście była oświetlona.
72 Rozdział 2  Od Blendera do Unity

Dzięki takim zabiegom ani procesor graficzny, ani główny nie muszą na bieżąco obli-
czać efektów oświetleniowych. Jednak żeby coś takiego się udało, zaimportowane siatki
muszą mieć przypisane współrzędne mapy światła. Współrzędne te to specjalne dane
matematyczne określające, w jaki sposób tekstura z mapą światła ma być odwzorowana
na powierzchni siatki. Bez nich mapowanie światła może dać wynik daleki od oczekiwa-
nego. Wartości tych współrzędnych możesz wyznaczyć ręcznie w Blenderze, ale możesz
też zlecić to zadanie odpowiednim funkcjom Unity.
Jeśli zdecydujesz się na ten drugi sposób, zacznij od zaznaczenia siatki w panelu Project,
aby wyświetlić jej właściwości w panelu Inspector. Potem po prostu włącz opcję Gene-
rate Lightmap UVs (generuj współrzędne mapy światła) i kliknij przycisk Apply (za-
stosuj) — tak jak na rysunku 2.28. W większości przypadków otrzymasz rezultat pra-
widłowy, kłopot mogą sprawić jedynie siatki o kształtach okrągłych lub organicznych
i wtedy będziesz musiał sam wyznaczyć te współrzędne za pomocą odpowiednich na-
rzędzi Blendera. Więcej informacji na ten temat znajdziesz w następnym rozdziale.

Rysunek 2.28. Automatyczne generowanie współrzędnych mapy światła dla zaimportowanej siatki
Źródło: Unity Technologies.
Ćwiczenie: importowanie plików FBX w Unity 73

Współczynnik skali
Dla każdej importowanej siatki FBX Unity automatycznie ustala współczynnik skali
o wartości 0,01 i nie ma tu znaczenia, jaka wartość jest zapisana w importowanym pliku.
W rezultacie siatka przyjmuje rozmiary dużo mniejsze niż te, które powinna mieć zgod-
nie z projektem. Czasami będziesz musiał wykonać mocne zbliżenie, żeby ją w ogóle
zobaczyć. Problem można rozwiązać przez zwiększenie wartości parametru Scale Factor
(współczynnik skali) do poziomu 1 (rysunek 2.29). Jednakże przy większej liczbie im-
portowanych siatek lub wielokrotnym importowaniu tej samej siatki (ze względu na
częste modyfikacje) ciągłe powtarzanie tej samej czynności szybko staje się męczące.

Rysunek 2.29. Zmiana współczynnika skali na 1 (zamiast 0,01)


Źródło: Unity Technologies.

Metoda alternatywna polega na napisaniu skryptu, który zmusi Unity do określonego


zachowania podczas importowania siatek — w tym przypadku do ustawiania za każdym
razem współczynnika skali o wartości 1. Skrypt będzie działał automatycznie i już
nigdy nie będziesz musiał ręcznie poprawiać tego parametru. Aby to uzyskać, utwórz
w panelu Project nowy skrypt w języku C# i nazwij go FBXFix.cs (poprawianie FBX).
Następnie umieść w tym skrypcie następujący kod:
74 Rozdział 2  Od Blendera do Unity

using UnityEditor;
public class FBXFix : AssetPostprocessor
{
public void OnPreprocessModel()
{
ModelImporter modelImporter = (ModelImporter) assetImporter;
modelImporter.globalScale = 1;
}
}

Gotowy skrypt umieść w folderze Editor (edytor). (Jeśli taki folder nie istnieje w bieżącym
projekcie, utwórz go). Żeby skrypt działał, musi się znajdować właśnie w takim folderze
(rysunek 2.30). Aby go przetestować, zaimportuj nowy plik FBX. Współczynnik skali
powinien mieć teraz wartość 1!

Rysunek 2.30. Odpowiedni skrypt w folderze Editor ustawi współczynnik skali importowanej
siatki na 1
Źródło: Unity Technologies.

A zatem umiesz już eksportować modele z Blendera i importować je do Unity z zacho-


waniem niemal pełnej wierności.

Podsumowanie
Rozdział ten poświęciłem opisowi czynności związanych z przenoszeniem modeli
między Blenderem a Unity. Mówiąc krótko: gdy dwa różne programy wymieniają
między sobą dane, bardzo często część tych danych jest tracona lub zmieniana. W przy-
padku Blendera i Unity do przenoszenia danych można użyć plików .blend lub FBX.
W tym rozdziale starałem się wykazać, że pliki FBX nadają się do tego celu znacznie
lepiej. Ale jak miałeś okazję się przekonać, temat jest znacznie szerszy niż tylko wybór
Podsumowanie 75

formatu plików. Żeby siatka przeniesiona z Blendera do Unity wyglądała jak najlepiej,
trzeba wykonać jeszcze kilka dodatkowych czynności. Niezbędne jest oznakowanie
ostrych krawędzi siatki, nadanie jej odpowiedniej orientacji, właściwe umiejscowienie
środka transformacji itp. Wszystko, co tutaj napisałem, odnosi się do każdej siatki,
niezależnie od jej rodzaju. Siatki animowane mają dodatkowe wymagania, ale tym za-
gadnieniem zajmiemy się dokładniej w jednym z dalszych rozdziałów. Natomiast te-
matem następnego rozdziału będzie specyficzny rodzaj siatek statycznych, mianowicie
modułowe siatki środowiskowe.
76 Rozdział 2  Od Blendera do Unity
R OZ DZ I AŁ 3

M ODUŁOWE ŚRODOWISKA
I SIATKI STATYCZNE

Kreatywność to tylko umiejętność łączenia różnych rzeczy.


— Steve Jobs

Po przeczytaniu tego rozdziału powinieneś:


■ rozumieć, czym są siatki statyczne i modułowe środowiska;
■ umieć stosować modułowe metody budowania środowisk;
■ znać zagadnienia związane z modelowaniem i mapowaniem UV;
■ dobrze rozumieć pojęcia takie jak mirroring, duplikaty, n-kąty itp.;
■ umieć budować w Unity sceny z modułów i prefabrykatów.
W wielu grach typu RPG czy FPS widzimy wspaniale rozbudowane środowiska w po-
staci lasów, jaskiń, stacji kosmicznych, biurowców, szpitali, tajnych laboratoriów itp.
Jak każda „namacalna” rzecz w grze 3D środowiska są wykonane z siatek — mister-
nych kompozycji wielokątów, krawędzi i wierzchołków połączonych w jedną całość za
pomocą programu do modelowania w trzech wymiarach. Dla twórcy gier budowanie
takich złożonych środowisk jest interesującym wyzwaniem technicznym.
Z punktu widzenia gracza wygląda to jak kompleksowy, spójny i w pełni zintegrowany
świat. Wnętrza pomieszczeń płynnie przechodzą w sąsiadujące z nimi korytarze, a krajo-
braz górzysty niepostrzeżenie zamienia się w teren zurbanizowany lub pustynny. Można
odnieść wrażenie, że całe środowisko jest jedną wielką siatką i że w takiej postaci zostało
zaimportowane do silnika gry. Jednak na ogół jest to tylko złudzenie. Zazwyczaj środo-
wisko składa się z wielu małych kawałków, zwanych modułami, które połączone razem
jak klocki Lego tworzą większą całość. Technika takiego składania środowisk z małych

77
78 Rozdział 3  Modułowe środowiska i siatki statyczne

kawałków nazywana jest metodą budowania modułowego lub po prostu metodą mo-
dułową. W zasadzie jest to trójwymiarowy odpowiednik metody kafelkowej stosowanej
przy tworzeniu plansz dla gier 2D.
Na rysunku 3.1 pokazany jest zestaw modułów dla środowiska fantastycznonaukowego.
Sam w sobie może nie zachwyca, ale przez wielokrotne użycie poszczególnych modułów
można zbudować całkiem spójne środowisko, chociażby takie jak na rysunku 3.2.

Rysunek 3.1. Kompletny zestaw modułów środowiska fantastycznonaukowego.


Przez łączenie tych elementów jak klocków możesz ułożyć kompletne środowisko
Źródło: Blender.

Rysunek 3.2. Przykład środowiska zbudowanego z modułów


Źródło: Unity Technologies.
Zalety metody modułowej 79

Zalety metody modułowej


Metoda modułowa ma kilka niewątpliwych zalet. Oto one:
■ Wielokrotność użycia. Przez rozbicie środowiska na elementarne kawałki, a nie
konstruowanie go w całości, ujawnia się olbrzymi potencjał wynikający z możliwo-
ści wielokrotnego wykorzystywania poszczególnych elementów. Te same moduły
połączone w różnych kombinacjach pozwalają uzyskać różne środowiska — przy
założeniu, że moduły zostały należycie zaplanowane i przygotowane! (W dalszej
części rozdziału zobaczysz, jak należy to robić). Możliwość wielokrotnego stosowania
modułów zwalnia nas z konieczności modelowania wielu podobnie wyglądających
środowisk, bo przecież można je poskładać z tych samych klocków.
■ Wydajność. Wielokrotność użycia niemal zawsze idzie w parze ze wzrostem wy-
dajności i efektywności, zwłaszcza w renderowaniu. Jeśli Unity potrafi należycie zin-
terpretować środowisko złożone z modułów, to możesz znacząco poprawić efektyw-
ność gry. Korzyści wynikają szczególnie z wyświetlania wyłącznie zawartości bryły
widzenia i tylko tego, co nie jest zasłonięte, a także z lepszego zarządzania pamięcią.

Uwa ga
Więcej informacji na temat bryły widzenia (frustum) i pomijania tego, co jest zasłonięte, znajdziesz na
stronach: http://docs.unity3d.com/Documentation/Manual/UnderstandingFrustum.html oraz http://docs.
unity3d.com/Documentation/Manual/OcclusionCulling.html.

■ Optymalizacja tekstur. Środowiska modułowe są optymalne pod względem tekstu-


rowania, ponieważ teksturowanie małych modułów jest dużo łatwiejsze niż nakłada-
nie złożonego obrazu na jedną, rozbudowaną siatkę. Do tego dochodzi jeszcze
możliwość wielokrotnego stosowania tej samej tekstury, jako że każdy moduł cią-
gle korzysta z tych samych współrzędnych teksturowych i z tej samej przestrzeni tek-
sturowej. A zatem do poteksturowania całego środowiska modułowego, choćby
nie wiadomo jak dużego, nie potrzeba więcej tekseli (pikseli teksturowych) niż do
poteksturowania samych modułów.

Rozpoczynanie prac nad środowiskiem modułowym


Po podjęciu decyzji co do wyglądu środowiska gry i jego rozplanowaniu trzeba wy-
modelować poszczególne moduły w programie do grafiki 3D, np. w Blenderze. Od po-
czątku zwracaj baczną uwagę na rozmiary i proporcje modułów, żeby później nie było
problemów z ich wzajemnym dopasowywaniem.
Podczas modelowania musisz pamiętać, że nie tworzysz całego środowiska, a jedynie
segmenty, z których później (po zaimportowaniu do Unity) takie czy inne środowisko
będzie można złożyć. W tworzeniu takich pasujących do siebie modułów często pomaga
wyobrażenie sobie gotowego środowiska pociętego na jednakowej wielkości kostki.
80 Rozdział 3  Modułowe środowiska i siatki statyczne

Potem trzeba jeszcze zbudować taką geometrię wewnątrz tych wyimaginowanych ko-
stek, aby dało się je sensownie połączyć również w innej aranżacji. Nie oznacza to, że
każdy moduł musi się łączyć z każdym innym; chodzi po prostu o to, aby dało się z nich
ułożyć jak najwięcej środowisk o zbliżonym charakterze.
Ja przeważnie zaczynam od ustalenia wymiarów kostki, czyli objętości podstawowego
klocka (rysunek 3.3). Domyślny sześcian utworzony w Blenderze ma swój środek
w początku globalnego układu współrzędnych (0,0,0), co na ogół jest niekorzystne. Za-
zwyczaj najwłaściwsze jest takie położenie, przy którym w punkcie (0,0,0) znajduje się
środek dolnej ścianki bryły. Aby to osiągnąć, włącz funkcję przyciągania przyrostowego
i przesuń sześcian w górę (wzdłuż osi Z) na tyle, żeby jego dolna ścianka znalazła się
dokładnie na siatce konstrukcyjnej (rysunek 3.4).

Rysunek 3.3. Sześcian jako elementarny składnik środowiska modułowego


Źródło: Blender.

Jednak samo przesunięcie bryły wraz z jej środkiem nie wystarczy. Przy przenoszeniu
siatki z jednego programu do drugiego najlepiej sprawdza się usytuowanie jej środka
w początku globalnego układu współrzędnych, przez który przechodzi siatka kon-
strukcyjna. Przy domyślnych ustawieniach Blendera w tym właśnie punkcie znajduje
się kursor 3D i jeśli do niego przyciągniesz środek kostki, uzyskasz to, o co chodzi.
Aby to zadanie wykonać, po prostu wybierz polecenie Object/Transform/Origin to 3D
Cursor (obiekt/przekształć/środek do kursora 3D) — tak jak na rysunku 3.5. Jeśli kursor
3D znajduje się poza środkiem globalnego układu współrzędnych, umieść go tam, wy-
bierając polecenie Object/Snap/Cursor to Center (obiekt/przyciągnij/kursor do środka).
Rozpoczynanie prac nad środowiskiem modułowym 81

Rysunek 3.4. Aby ułatwić sobie ustawienie sześcianu na siatce konstrukcyjnej, włącz przyciąganie
przyrostowe
Źródło: Blender.

Rysunek 3.5. Umieszczanie środka sześcianu w początku globalnego układu współrzędnych


za pośrednictwem kursora 3D
Źródło: Blender.
82 Rozdział 3  Modułowe środowiska i siatki statyczne

Tak przygotowana kostka stanowi najmniejszy blok, czyli moduł środowiska, i dlatego
będę ją często nazywał klockiem podstawowym. Nie da się jednoznacznie powiedzieć,
jakie powinny być jego wymiary, bo to w dużym stopniu zależy od konkretnej gry i przy-
jętego toku pracy. Ja zazwyczaj kieruję się tutaj wymiarami głównego bohatera, jakie
posiada on w Unity. Dlatego w przypadku gier pierwszoosobowych i RPG zazwyczaj
dotąd przenoszę kostkę między Blenderem i Unity, aż uzyskam podstawowy klocek
obejmujący postać gracza z pewnym naddatkiem. Do zmieniania wymiarów kostki
można użyć blenderowego narzędzia Scale (skala) — skrót klawiszowy R — ale ja wolę
operować tutaj liczbami całkowitymi. Dlatego zawsze używam kontrolek Dimensions
(wymiary) z panelu N1 i jako wartości X, Y oraz Z wpisuję okrągłe, pozbawione części
ułamkowej liczby — tak jak na rysunku 3.6. Jak widać, tym razem nadałem kostce wy-
miary (w jednostkach globalnych) 2×2×3, przy czym wymiar największy odnosi się do
wysokości. Przypominam: w Blenderze kierunek pionowy wyznacza oś Z.

Rysunek 3.6. Ustalanie wymiarów klocka podstawowego za pomocą panelu N


Źródło: Blender.

Uwa ga
Pamiętaj o ustawieniu relacji 1:1 między jednostkami Blendera i Unity (była o tym mowa w rozdziale 2.).

1
Autor tak nazywa panel Properties (właściwości) wysuwany z prawej krawędzi okna widokowego
po wciśnięciu klawisza N — przyp. tłum.
Używanie klocka podstawowego 83

Używanie klocka podstawowego


Zdefiniowanie klocka podstawowego to chyba najważniejszy moment w całym proce-
sie budowy środowiska modułowego. Element ten wytycza swego rodzaju jednostkę,
według której będą ustalane wymiary wszystkich modułów. Oto kilka ogólnych wska-
zówek dotyczących postępowania z klockiem podstawowym, gdy już zostaną ustalone
jego wymiary i położenie w blenderowej scenie.
■ Zachowaj kopię bezpieczeństwa. Nigdy nie modeluj, nie edytuj i nie usuwaj pier-
wotnego klocka podstawowego. Zawsze miej jego kopię w scenie jako wzorzec do
ustalania wymiarów innych modułów środowiska. Po zdefiniowaniu wszystkich
parametrów klocka powiel go i używaj kopii, a oryginał umieść na odrębnej, nieza-
leżnej warstwie.
■ Używaj go wyłącznie jako wzorca. Nie modeluj klocka podstawowego. Nie popra-
wiaj ani nie zmieniaj jego wierzchołków. On jest swego rodzaju szablonem, na pod-
stawie którego tworzysz inne moduły środowiska. Wyznacza objętość i graniczne
wymiary najmniejszego z tworzonych modułów. Traktuj go jak element pomocniczy
przy modelowaniu modułów.
■ Używaj go do ustalania wymiarów większych elementów. Z faktu ustanowienia
klocka podstawowego wzorcem dla modułów środowiska nie wynika wcale, że
wszystkie moduły muszą mieć takie same jak on wymiary. Klocek podstawowy może
reprezentować np. tylko część drzwiową jakiegoś pomieszczenia, włącznie z frag-
mentami ścian, sufitu i podłogi. Jeśli chcesz utworzyć większe moduły, jak chociażby
korytarze, możesz to śmiało zrobić. Zadbaj tylko, żeby ich wymiary były całkowi-
tymi wielokrotnościami wymiarów klocka podstawowego (2×, 3×, 4× itd.). Nie
używaj wartości ułamkowych ani takich, które nie są podzielne przez żaden wymiar
klocka podstawowego. Tylko wtedy wszystkie moduły (włącznie z klockiem pod-
stawowym) będą do siebie pasowały i będziesz mógł z nich ułożyć większą całość.
Jeśli nadasz im wymiary zbyt zróżnicowane, żadna układanka się nie uda i nie bę-
dziesz mógł wykorzystać zalet modułowości (rysunek 3.7).

Opracowywanie modułów w Blenderze


Wypracowanie sobie nawyku modelowania w kategoriach segmentów, kostek i klocków
podstawowych to jeszcze nie wszystko, jeśli chodzi o tworzenie środowisk w Blenderze.
Powinieneś też wiedzieć, jak ustawić pewne parametry aplikacji, aby praca przebiegała
sprawniej. Oto kilka wskazówek na ten temat.
84 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.7. Wymiary większych elementów powinny być całkowitymi wielokrotnościami


wymiarów klocka podstawowego. Tutaj segment korytarzowy jest dwa razy dłuższy od segmentu
narożnego
Źródło: Blender.

Odwracanie normalnych
Środowiska zamknięte, takie jak pokoje, jaskinie czy dziuple, są przez gracza oglądane
raczej od wewnątrz niż z zewnątrz. A zatem gdy umieścisz w scenie nowy sześcian lub
inną bryłę z zamiarem wymodelowania jakiegoś wnętrza, najprawdopodobniej będziesz
chciał widzieć wszystko od środka. To z kolei oznacza, że wszystkie wielokąty składające
się na podłogę, sufit i ściany powinny być zwrócone do wewnątrz bryły, a nie na zewnątrz.
W tej sytuacji konieczne będzie odwrócenie normalnych przypisanych tym wielokątom.
Zabieg ten możesz wykonać następująco:
1. Włącz tryb edycji ścianek.
2. Wciśnij klawisze Ctrl+A lub wybierz polecenie Select/Select All (zaznacz/zaznacz
wszystko), aby zaznaczyć wszystkie ścianki obiektu.
3. Wybierz polecenie Mesh/Normals/Flip Normals (siatka/normalne/odwróć normalne).
Blender odwróci normalne, co da efekt wizualny taki jak na rysunku 3.8.

Uwa ga
Jeśli używasz domyślnych ustawień Blendera i masz włączony tryb wyświetlania Solid (bryłowy), to od-
wrócenie normalnych może nie dać żadnego efektu wizualnego. W takim przypadku koniecznie prze-
czytaj następny punkt!
Opracowywanie modułów w Blenderze 85

Rysunek 3.8. Sześcian przed odwróceniem normalnych i po takim zabiegu. Odwracanie


normalnych powoduje coś w rodzaju wywracania siatki na lewą stronę
Źródło: Blender.

Ukrywanie ścianek odwróconych tyłem


Domyślnie Blender wyświetla wszystkie wielokąty jako dwustronne, mimo że w grach
wideo stosuje się wielokąty jednostronne. W Unity, podobnie jak w grach wideo,
oglądać można tylko jedną stronę wielokąta. Jeśli spojrzysz na wielokąt z drugiej strony,
będzie on po prostu niewidoczny. Natomiast w Blenderze rysowane są obie strony, co
oznacza, że nawet po odwróceniu normalnych wszystkie ścianki są nadal widoczne.
Takie zachowanie aplikacji może utrudniać modelowanie modułów środowiska, bo
przecież często będziesz chciał obejrzeć wnętrze obiektu, np. pokoju, a wtedy ścianki
odwrócone tyłem będą tylko przeszkadzać.
Na szczęście Blender oferuje funkcję o nazwie Backface Culling (odrzucanie ścianek
odwróconych tyłem). Znajdziesz ją w sekcji Shading (cieniowanie) rolety Display (wy-
świetlanie) będącej częścią panelu N. Aby wymusić renderowanie tylko jednej strony
wielokątów, po prostu włącz tę funkcję (rysunek 3.9).

Funkcja przyciągania
Jeśli zamierzasz tworzyć dające się łatwo łączyć moduły środowiskowe, trudno Ci bę-
dzie obejść się bez korzystania z funkcji przyciągania. Na dobrą sprawę powinna ona
stać się Twoją drugą naturą na czas pracy w Blenderze. Dzięki niej precyzyjne wyrów-
nywanie wierzchołków czy całych modeli staje się niezwykle proste.
Funkcja przyciągania ma kilka form, ale teraz interesować nas będą tylko przyciąganie
do wierzchołków i przyciąganie przyrostowe, które umożliwia ustawianie obiektów
zgodnie z siatką konstrukcyjną. Wszystko to ma niebagatelne znaczenie przy mode-
lowaniu elementów, które później będą się miały ładnie łączyć w jedną całość, gdy po
86 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.9. Aby zmusić Blendera do renderowania tylko jednej strony ścianek, zaznacz opcję
Backface Culling
Źródło: Blender.

przeniesieniu do Unity będziesz z nich układał środowisko gry. Jeśli choćby jeden ele-
ment będzie niedopasowany do reszty, może powstać wyraźne zaburzenie w konstrukcji
środowiska i cała Twoja praca pójdzie na marne. Jeśli ustawisz taki segment obok in-
nego, może powstać między nimi luka, ponieważ ich wierzchołki nie będą się pokry-
wały. Czasami luka może być tak duża, że gracz, trafiwszy na nią, wypadnie poza śro-
dowisko gry!
Oczywiście można łatać takie miejsca przez wstawianie specjalnych, kolidujących pry-
mitywów, które zapobiegną wypadaniu gracza, ale takie rozwiązanie jest po prostu po-
wierzchowne i z daleka pachnie tandetą. Tak naprawdę nie sięga do źródła problemu,
który tkwi w samej strukturze siatki. Dlatego zawsze stosuj funkcję przyciągania i mode-
luj wszystko z należytą precyzją.
Aby zastosować przyciąganie przyrostowe, włącz ogólną funkcję przyciągania (służy
do tego przycisk z ikoną w kształcie magnesu) i ustaw tryb Increment (przyrost) — tak
jak na rysunku 3.4. Gdy ten tryb przyciągania jest aktywny, wszystkie transformacje
mogą być wykonywane jedynie skokowo o ściśle określoną wartość. Jest to szczególnie
przydatne, gdy w grę wchodzą transformacje na poziomie obiektowym (a nie wierz-
chołkowym, krawędziowym czy wielokątowym), bo pozwala na bardzo dokładne roz-
mieszczanie całych obiektów. Poza tym, jak już opisywałem w podrozdziale „Rozpo-
czynanie prac nad środowiskiem modułowym”, przyciąganie przyrostowe może być
pomocne również przy umieszczaniu środka obiektu dokładnie w początku globalnego
układu współrzędnych.
Opracowywanie modułów w Blenderze 87

W przeciwieństwie do przyciągania przyrostowego, które dopuszcza transformacje


skokowe, przyciąganie do wierzchołków powoduje automatyczne wyrównywanie jed-
nego lub kilku wierzchołków siatki z jakimś innym wierzchołkiem. Jeśli chcesz wy-
równać dwa lub więcej wierzchołków względem którejkolwiek (lub wszystkich) osi, to
właśnie przyciąganie do wierzchołków jest tym, czego potrzebujesz! Dla przykładu
rozważmy sytuację z rysunku 3.10. Podczas modelowania ściany w module środowi-
skowym przypadkowo przesunąłem górne wierzchołki w prawo, co spowodowało lekkie
pochylenie pionowych wcześniej krawędzi.

Rysunek 3.10. Brak właściwego wyrównania wierzchołków ściany


Źródło: Blender.

Aby na powrót ustawić te wierzchołki w linii prostej z wierzchołkami leżącymi niżej,


mogłem je po prostu przeciągnąć za pomocą narzędzia Transform (przekształć) do
położenia, przy którym krawędzie ściany byłyby mniej więcej proste. Lecz z pomocą
funkcji przyciągania mogłem sprawić, że na nowo stały się dokładnie proste. Aby to
uzyskać, wykonałem następujące czynności:
1. Zaznaczyłem wszystkie wierzchołki wymagające przesunięcia.
2. Włączyłem funkcję przyciągania do wierzchołków (zob. rysunek 3.4).
3. Ograniczyłem możliwość przesuwania tylko wzdłuż osi X (można to zrobić za po-
mocą gizma translacji lub przez wciśnięcie kolejno klawiszy W i X).
4. Trzymając wciśnięty przycisk myszy, przesunąłem zaznaczone wierzchołki w po-
bliże właściwie ustawionych wierzchołków leżących niżej. Wtedy zadziałała funk-
cja przyciągania i umieściła przeciągane wierzchołki dokładnie tam, gdzie powinny
być. W rezultacie uzyskałem perfekcyjne wyrównanie wierzchołków przesuwanych
z docelowymi (rysunek 3.11).
88 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.11. Funkcja przyciągania do wierzchołków wyrównuje wierzchołki przesuwane


z docelowymi
Źródło: Blender.

Uwa ga
Więcej informacji o wszystkich opcjach funkcji przyciągania znajdziesz w dokumentacji Blendera do-
stępnej pod adresem: http://wiki.blender.org/index.php/Doc:2.6/Manual/3D_interaction/Transform_
Control/Snap_to_Mesh.

N-kąty
Siatki składają się z wielokątów — dlatego często mówi się o nich: siatki wielokątne.
Najprostszym wielokątem jest trójkąt, który ma trzy boki. Potem są czworokąty o czte-
rech bokach. Teoretycznie można wymieniać dalej: pięciokąty, sześciokąty, ośmiokąty,
dziesięciokąty, dziewiętnastokąty itd. do nieskończoności. Każdy z tych kształtów cha-
rakteryzuje się określoną liczbą boków stanowiących jego obwód. Co ciekawe, każdy z tych
wielokątów można zbudować z odpowiedniej liczby właściwie dobranych trójkątów.
Opracowywanie modułów w Blenderze 89

W modelowaniu 3D oraz w grach wideo wszystkie wielokąty mające więcej niż cztery
boki nazywane są n-kątami (n-gons). Powiem krótko: to są Twoi wrogowie. Nigdy nie
powinny się znaleźć w żadnej wymodelowanej przez Ciebie siatce. Dlatego jeszcze na
etapie pracy w Blenderze powinieneś podjąć odpowiednie kroki, aby się ich pozbyć.
To znaczy: jeśli znajdziesz jakiś n-kąt, musisz go koniecznie porozcinać na trójkąty lub
czworokąty. Te drugie nie zawsze dadzą się utworzyć (to już zależy od natury siatki),
ale trójkąty można wyznaczyć zawsze (rysunek 3.12).

Rysunek 3.12. Cylindryczny obiekt z n-kątową podstawą. N-kąt ma tu postać czternastokąta


foremnego. Taki obiekt będzie sprawiał problemy w grze 3D
Źródło: Blender.

Blender oferuje kilka narzędzi do retopologizacji modeli, czyli do takiego przebudowy-


wania ich siatek, aby składały się wyłącznie z trójkątów i czworokątów. Jednym z tych na-
rzędzi jest Triangulate Faces (triangulacja ścianek) dostępne w trybie edycyjnym jako
polecenie Mesh/Faces/Triangulate Faces (siatka/ścianki/triangulacja ścianek) — rysu-
nek 3.13. Działa ono tylko na zaznaczone ścianki, ale błyskawicznie zamienia je na
zbiór trójkątów. Może być szybkim sposobem na pozbycie się n-kątów przed wyeks-
portowaniem siatki do Unity, chociaż jego wadą jest to, że nie pozwala na żadną ingeren-
cję w przeprowadzany podział.
Drugim, znacznie elastyczniejszym narzędziem do retopologizacji modeli przez elimi-
nowanie n-kątów jest Knife (nóż). Podobnie jak poprzednie jest dostępne w trybie edy-
cyjnym i umożliwia interaktywne dzielenie oraz reorganizowanie siatki przez rozcinanie jej
90 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.13. Za pomocą narzędzia Triangulate Faces błyskawicznie podzielisz każdy czworokąt
i każdy n-kąt na trójkąty
Źródło: Blender.

wzdłuż rysowanych w czasie rzeczywistym linii (rysunek 3.14). W gruncie rzeczy jest
to „ręczne” korygowanie siatki, które trwa dłużej niż przy stosowaniu narzędzia Trian-
gulate Faces, ale za to mamy nieograniczoną swobodę w decydowaniu, jak dana ścianka
ma być podzielona.

Rysunek 3.14. Krojenie ścianek modelu na trójkąty i czworokąty za pomocą narzędzia Knife
Źródło: Blender.
Opracowywanie modułów w Blenderze 91

Wyszukiwanie n-kątów
Na pozór wydaje się, że wyszukanie n-kąta nie powinno być trudne. W końcu wystar-
czy policzyć, ile boków ma dana ścianka, aby stwierdzić, czy jest n-kątem, czy nie.
Lecz w praktyce, gdy siatka składa się z setek czy nawet tysięcy ścianek, wskazanie
wszystkich n-kątów (jeśli są jakieś) wcale nie musi być rzeczą łatwą. Na szczęście
Blender znów przychodzi z pomocą i umożliwia zaznaczenie wszystkich n-kątów w siatce
przez kliknięcie jednego przycisku (no, może kilku). Procedura taka wygląda nastę-
pująco:
1. Włącz tryb edycji ścianek.
2. Jeśli istnieje jakieś zaznaczenie, usuń je.
3. Wybierz polecenie Select/Select Faces by Sides (zaznacz/zaznacz ścianki według boków)
— tak jak na rysunku 3.15.

Rysunek 3.15. Narzędzie Select Faces by Sides umożliwia zaznaczenie wszystkich ścianek
o zadanej liczbie boków
Źródło: Blender.

4. Aby wyszukać wszystkie n-kąty w siatce, wpisz w polu Number of Verices (liczba
wierzchołków), które widnieje teraz w przyborniku, cyfrę 4.
92 Rozdział 3  Modułowe środowiska i siatki statyczne

5. Z listy rozwijanej Type (typ) wybierz opcję Greater Than (więcej niż), bo przecież
n-kąty mają więcej niż cztery wierzchołki.
6. Wyłącz opcję Extend (poszerz). Przy takiej kombinacji ustawień zostaną zaznaczone
wszystkie ścianki, które mają więcej niż cztery wierzchołki, czyli wszystkie n-kąty
(jeśli jakieś w ogóle są). Jeśli nie widzisz, czy jakieś ścianki zostały zaznaczone, czy
nie, sprawdź liczbę zaznaczonych ścianek wyświetlaną na nagłówku ekranu infor-
macyjnego w prawym górnym rogu interfejsu (rysunek 3.16).

Rysunek 3.16. Zaznaczanie wszystkich n-kątów w siatce


Źródło: Blender.

Cofanie operacji i usuwanie duplikatów


Gdy pracujesz w Blenderze, z rozwagą używaj polecenia Undo (cofnij). Niektóre pole-
cenia (w niektórych wersjach), np. Extrude (wytłocz), są w rzeczywistości operacjami
wieloetapowymi, mimo że użytkownik uruchamia ich wykonanie jednym kliknięciem.
Dlatego też aby ich skutki zostały cofnięte całkowicie, potrzebne jest wielokrotne uży-
cie polecenia Undo. Nie jest to zbyt intuicyjne i często powoduje (nie licząc innych
przyczyn), że w siatce pojawiają się zdublowane wierzchołki (tzw. duplikaty). Powstają
podczas modelowania i zajmują dokładnie te same miejsca co inne wierzchołki. Za-
tem niektóre wierzchołki siatki stają się podwójne i w oknie widokowym nie da się ich
jednoznacznie zlokalizować, bo z wyglądu nie różnią się od pojedynczych. Najlepszym
sposobem na pozbycie się takich niepożądanych duplikatów jest zaznaczenie wszyst-
kich wierzchołków (wciśnij Ctrl+A) i wybranie polecenia Mesh/Vertices/Remove Doubles
(siatka/wierzchołki/usuń duplikaty) — rysunek 3.17.
Opracowywanie modułów w Blenderze 93

Rysunek 3.17. Aby rozwiązać problem zdublowanych wierzchołków, użyj polecenia Remove Doubles
Źródło: Blender.

Mirroring
Podczas modelowania obiektów symetrycznych, np. korytarzy, tuneli, często wygodnie
jest wymodelować tylko jedną połowę takiego obiektu (rysunek 3.18), a drugą utworzyć
jako lustrzane odbicie tamtej. Zabieg taki nazywany jest mirroringiem.

Rysunek 3.18. W technice mirroringu wystarczy wymodelowanie połowy obiektu


Źródło: Blender.
94 Rozdział 3  Modułowe środowiska i siatki statyczne

Po wymodelowaniu połowy modułu możesz wygenerować jej symetryczny duplikat,


przypisując jej modyfikator Mirror (lustro). Dostęp do tego modyfikatora uzyskasz na
zakładce Modifiers (modyfikatory) panelu Properties (właściwości). Po prostu kliknij listę
rozwijaną Add Modifier (dodaj modyfikator) i wybierz z niej pozycję o nazwie Mirror
(rysunek 3.19). Stosowanie tego modyfikatora może zaoszczędzić dużo czasu, ale nie
należy z tym przesadzać. Gracz szybko zauważy symetryczność, powtarzalność i sche-
matyczność środowiska, w którym się porusza.

Rysunek 3.19. Generowanie drugiej strony korytarza za pomocą modyfikatora Mirror


Źródło: Blender.

Uwa ga
Modyfikator Mirror automatycznie ustawia płaszczyznę (lub oś) symetrii w taki sposób, aby przechodziła
przez środek (środek transformacji) obiektu. Jeśli więc chcesz, żeby zastosowanie modyfikatora przynio-
sło spodziewany rezultat, ustaw wcześniej środek obiektu we właściwym miejscu. Wskazówki, jak to
zrobić, znajdziesz w podrozdziale „Rozpoczynanie prac nad środowiskiem modułowym”.

Pamiętaj, że wygenerowane lustrzane odbicie nie stanowi pełnej jedności z orygina-


łem tak długo, jak długo modyfikator Mirror pozostaje niezatwierdzony. Innymi sło-
wy: oryginał i jego lustrzane odbicie staną się jedną całością dopiero wtedy, gdy klikniesz
przycisk Apply (zastosuj) odpowiadający temu modyfikatorowi.

Grupowanie wierzchołków
Tworzenie siatek w programach do grafiki 3D nieuchronnie wiąże się z manipulowa-
niem dużymi liczbami wierzchołków, krawędzi i ścianek, które w sumie stanowią
podstawowy materiał modelarski. Szczególnie liczne są wierzchołki, a właśnie one są
Opracowywanie modułów w Blenderze 95

najczęściej zaznaczane, gdy trzeba wskazać jakiś obszar siatki w celu przeprowadzenia
operacji modelarskich. Jednak zaznaczanie każdego wierzchołka oddzielnie może być
uciążliwe, a już na pewno byłoby frustrujące, gdyby trzeba było te same wierzchołki
zaznaczać wielokrotnie (może się przecież zdarzyć, że po pewnym czasie od wykonania
jednej operacji na zaznaczonych wierzchołkach będziesz musiał wykonać inną na do-
kładnie tych samych wierzchołkach).
Na szczęście Blender oferuje możliwość zapisania zestawu raz zaznaczonych wierzchoł-
ków i potem przywoływania go, gdy te same wierzchołki mają być użyte. Zestawy te,
zwane w Blenderze grupami, można tworzyć, przywoływać i usuwać za pośrednictwem
zakładki Data (dane) panelu Properties (rysunek 3.20).

Rysunek 3.20. Do zarządzania zestawami zaznaczonych wierzchołków służy sekcja Vertex


Groups (grupy wierzchołków) zakładki Data panelu Properties
Źródło: Blender.

Aby utworzyć nową grupę, kliknij przycisk oznaczony znakiem plus (+) i wpisz stosowną
nazwę (rysunek 3.21). Nazwa powinna być unikatowa i najlepiej, jeśli będzie opisowa.
Po utworzeniu grupy i zaznaczeniu jej nazwy na zakładce Data możesz jej przypisać
zestaw zaznaczonych wierzchołków przez zwykłe kliknięcie przycisku Assign (przy-
pisz) widocznego pod listą dostępnych grup (rysunek 3.22). Aby później ponownie
zaznaczyć te same wierzchołki, musisz tylko wskazać właściwą grupę i kliknąć przycisk
Select (zaznacz), który również widać na rysunku 3.22.
96 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.21. Tworzenie grupy w celu zapisania zestawu zaznaczonych wierzchołków


Źródło: Blender.

Rysunek 3.22. Przypisywanie wierzchołków do grupy i ponowne ich zaznaczanie


Źródło: Blender.
Opracowywanie modułów w Blenderze 97

Parametry wyświetlania siatki


Możliwe, że to tylko moja ułomność, ale stwierdziłem, że przy domyślnych ustawie-
niach Blendera wierzchołki są słabo widoczne i przez to praca z nimi jest utrudniona.
(Może masz takie same odczucia?) Żeby móc pracować efektywniej, niemal zawsze
zmieniam sposób, w jaki wierzchołki są renderowane, w oknie widokowym. Oto zmiany,
które wprowadzam:
1. Z menu File (plik) wybieram polecenie User Preferences (preferencje użytkownika),
tak jak na rysunku 3.23, aby otworzyć okno dialogowe Blender User Preferences.

Rysunek 3.23. Przywoływanie okna dialogowego Blender User Preferences


Źródło: Blender.

2. W oknie Blender User Preferences klikam zakładkę Themes (motywy).


3. Z listy po lewej stronie wybieram pozycję 3D View (widok 3D), aby wyświetlić
opcje interfejsu dla okna widokowego.
4. Dla opcji Vertex (wierzchołek) i Vertex Select (zaznaczenie wierzchołka) wybieram
jaśniejsze kolory, co spowoduje, że wierzchołki zarówno niezaznaczone, jak i za-
znaczone będą jaśniejsze.
5. Zwiększam wartość parametru Vertex Size (rozmiar wierzchołka) do 8 lub nawet 9,
przez co wszystkie wierzchołki siatki stają się większe i lepiej widoczne. Dla mnie
takie zmiany są wystarczające i dzięki nim nie tylko lepiej widzę wierzchołki, ale
i łatwiej jest mi je zaznaczać podczas modelowania (rysunek 3.24).
98 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.24. Ustawianie kolorów i rozmiarów wierzchołków w oknie Blender User Preferences
Źródło: Blender.

Mapowanie UV i tworzenie tekstur


Modelowanie w kategoriach wierzchołków, krawędzi i ścianek to dopiero pierwszy
krok w kierunku utworzenia kompletnego zestawu środowiskowego. Następny to ma-
powanie UV i pokrywanie modeli teksturami. Nadal pracujemy w Blenderze, ale do
pomocy przy malowaniu i edycji tekstur angażujemy dodatkowo programy takie jak
GIMP lub Photoshop. Do głosu dojdzie również Unity ze swymi wymaganiami i do-
brze zrobisz, jeśli będziesz miał te wymagania przez cały czas na myśli. Właśnie takimi
sprawami będziemy się zajmować w tym podrozdziale.

Wyznaczanie szwów, mapowanie UV i modelowanie


Mapowanie UV to nic innego jak rozwijanie trójwymiarowej geometrii modelu na
płaskiej powierzchni. Celem takiego zabiegu jest uzyskanie dwukierunkowej relacji
między trójwymiarowym modelem a płaskim obrazem. Jeśli taką relację uda się utwo-
rzyć, piksele dwuwymiarowej tekstury będą mogły być rzutowane na powierzchnię
modelu i nadawać mu określony wygląd. Dwukierunkowość relacji oznacza, że szcze-
góły namalowane bezpośrednio na powierzchni modelu w trzech wymiarach mogą być
zrzutowane na płaską teksturę!
Jednak żeby dokonać takiego rozwinięcia modelu, trzeba wcześniej wyznaczyć w jego
siatce tzw. szwy (seams), czyli linie, wzdłuż których będzie można model rozciąć, aby
w ogóle dało się go otworzyć i rozpłaszczyć. Proces ten należy przeprowadzać z wielkim
namysłem, ponieważ Unity wymaga, aby, ze względu na szybkość działania, szwów
było jak najmniej. Tak czy inaczej jakieś szwy są potrzebne, bo bez nich w ogóle nie da
Mapowanie UV i tworzenie tekstur 99

się modelu rozwinąć. Dla każdego wierzchołka na szwie Unity wstawi duplikat, a to
oznacza, że szwy pośrednio przyczyniają się do wzrostu liczby wierzchołków modelu.
Aby wyznaczyć szew w siatce modelu, zaznacz krawędzie, wzdłuż których ten szew
powinien przebiegać, po czym kliknij w przyborniku przycisk Mark Seam (oznacz szew)
lub z menu Mesh (siatka) wybierz polecenie Edges/Mark Seam (krawędzie/oznacz szew)
— tak jak na rysunku 3.25.

Rysunek 3.25. Przed rozwinięciem siatki należy wyznaczyć szwy. Można to zrobić za pomocą
przycisku Mark Seam w przyborniku lub polecenia Edges/Mark Seam
Źródło: Blender.

Krawędź oznaczoną jako szew Blender wyświetla w kolorze czerwonym (pod warun-
kiem, że nie zmieniłeś ustawienia domyślnego). Gdyby się okazało, że szwy w ogóle
nie są wyróżniane, sprawdź, czy przypadkiem nie wyłączyłeś funkcji odpowiedzialnej
za wyświetlanie szwów. Aby ją włączyć, otwórz panel N i w sekcji Mesh Display (wy-
świetlanie siatki) zaznacz opcję Seams (szwy) — tak jak na rysunku 3.26.
Po wyznaczeniu szwów możesz nakazać Blenderowi rozwinięcie siatki. Odpowiednim do
tego poleceniem jest Unwrap (rozwiń). Dokładny opis procedury rozwijania siatek znaj-
dziesz w dokumentacji Blendera (http://wiki.blender.org/index.php/Doc:2.6/Manual/
Textures/Mapping/UV/Unwrapping).
100 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.26. Żeby szwy były widoczne, trzeba włączyć ich wyświetlanie
Źródło: Blender.

Wyznaczanie szwów często jest traktowane jako odrębny etap następujący po fazie
modelowania, ale moim zdaniem jest to prosta droga do marnowania czasu. Uważam,
że najlepszym rozwiązaniem jest wyznaczanie szwów podczas modelowania. Dlaczego?
Ponieważ w trakcie modelowania często stosujemy powielanie dużych fragmentów
siatki (np. przy stosowaniu mirroringu) i jeśli zawczasu wyznaczymy szwy, zostaną
one skopiowane wraz z innymi elementami siatki — w ten sposób odpadnie nam po-
łowa pracy.

Atlas tekstur i pokrywanie się współrzędnych UV


Obecność materiału w scenie wiąże się z dodatkowym obciążeniem dla procesora i przy-
czynia się do obniżenia wydajności gry. Każdy materiał zwiększa liczbę wywołań ry-
sujących. Im więcej materiałów, tym więcej takich wywołań. Jeśli zależy Ci na wydaj-
ności, musisz redukować ich liczbę do niezbędnego minimum. A zatem musisz po prostu
ograniczyć liczbę użytych materiałów.

Uwa ga
W Unity wywołanie rysujące to wewnętrzny proces, który aplikacja wykonuje automatycznie, aby
wyświetlić trójwymiarową grafikę na ekranie monitora. W każdej klatce (a w ciągu sekundy może być
wyświetlanych nawet 100 klatek) Unity wykonuje na ogół co najmniej jedno wywołanie rysujące, a każ-
de z nich angażuje CPU i GPU. Im mniej takich wywołań musi wykonać Unity, aby wyrenderować scenę,
tym większa będzie wydajność gry. Czynniki takie jak liczba materiałów w scenie mają bezpośredni
wpływ na liczbę wywołań rysujących. Każdy unikatowy materiał wymaga przynajmniej jednego takiego
wywołania.
Mapowanie UV i tworzenie tekstur 101

Jednym ze sposobów realizacji tego zalecenia jest używanie jak najmniejszej liczby
tekstur rozpraszających światło. Od samego początku procesu mapowania UV siatek
środowiskowych dąż do tego, by wszystkim modułom przypisać jedną dużą teksturę.
Ten rodzaj tekstur, na które mapowanych jest wiele siatek, określa się mianem atlasu
tekstur.
Żeby zmapować wszystkie siatki środowiskowe na jedną teksturę, trzeba je rozwinąć
w tej samej przestrzeni UV. W Blenderze należy w tym celu złączyć wszystkie siatki
w jedną całość i dopiero wtedy można przeprowadzić mapowanie. Gdy mapowanie zo-
stanie zakończone, należy siatki z powrotem rozdzielić, jeśli mają być eksportowane
do Unity.
Do łączenia siatek służy polecenie Join (złącz). Po prostu zaznacz wszystkie siatki, które
mają być złączone, i wybierz Object/Join (obiekt/złącz), kliknij przycisk Join w przyborni-
ku lub wciśnij klawisze Ctrl+J (rysunek 3.27).

Rysunek 3.27. Aby rozwinąć wszystkie siatki we wspólnej przestrzeni UV, należy je najpierw połączyć
Źródło: Blender.

Gdy siatki utworzą jedną całość, można je rozwinąć jak zwykłą, pojedynczą siatkę.
Warto przy tym pamiętać o możliwości pokrywania się współrzędnych UV. Jeśli siat-
ka zawiera kilka obszarów o podobnej topologii, które powinny wyglądać tak samo —
np. dwa fragmenty ściany lub dwoje podobnych drzwi — można im przypisać te same
współrzędne UV i w ten sposób wielokrotnie wykorzystać ten sam fragment tekstury.
To tak, jakby ich współrzędne UV ułożyć warstwowo jedne na drugich. Każdy z tych
102 Rozdział 3  Modułowe środowiska i siatki statyczne

obszarów siatki będzie więc miał przypisaną tę samą część tekstury. Jeśli zastosujesz tę
technikę w każdym możliwym przypadku, oszczędności liczone w kategoriach roz-
miarów tekstury mogą być znaczące. Są nawet przykłady pokazujące, jak przez umie-
jętne korzystanie z tych możliwości zdołano całe środowisko zmapować na jedną tek-
sturę liczącą zaledwie 1024×1024 pikseli. Na rysunku 3.28 widać rozwinięcie UV
przykładowego zestawu modułów środowiska, który można pobrać ze strony inter-
netowej: ftp://ftp.helion.pl/przyklady/unible.zip zawierającej materiały uzupełniające
do książki (Rozdział03/MateriałyDoPobrania). Podany folder zawiera zestaw siatek
rozmaitych elementów środowiska (takich jak narożniki ścian, proste fragmenty koryta-
rza, skrzyżowania typu T itp.), które można łączyć ze sobą jak bloki budowlane i tworzyć
kompletne środowiska. Jest tam również tekstura. Zostawiłem w niej trochę wolnego
miejsca dla innych elementów gry, które być może spróbujesz dodać.

Uwa ga
Jeśli chcesz zobaczyć, co można osiągnąć przy użyciu małych tekstur w połączeniu z techniką pokrywa-
nia się współrzędnych UV, obejrzyj filmik zrealizowany przy użyciu UDK i zamieszczony pod adresem:
http://vimeo.com/35470093.

Rysunek 3.28. Aby wielokrotnie wykorzystać przestrzeń tekstury, zastosuj pokrywanie się
współrzędnych UV
Źródło: Blender.

Ustalanie gęstości tekselowej


Tekstury jako prostokątne obrazy mają szerokość i wysokość wyrażane w pikselach.
Gdy rozwinięcie UV jest nakładane na teksturę, każda wyspa UV obejmuje pewien
obszar tekstury i odwzorowuje go na siatkę. Liczba pikseli tekstury przypisana do wyspy
UV jest nazywana gęstością tekselową.
Mapowanie UV i tworzenie tekstur 103

W ocenie gęstości tekselowej pomaga zastosowanie w edytorze UV specjalnej mapy


szachownicowej (UV Grid). Podstawą tej oceny są wtedy kształty i rozmiary poszcze-
gólnych pól szachownicy. W szczególności chodzi o to, by:
■ wszystkie pola szachownicy po zrzutowaniu na siatkę były kwadratowe (miały sze-
rokość równą wysokości);
■ wszystkie pola na wszystkich siatkach środowiska były tej samej wielkości.
Spełnienie tych warunków gwarantuje właściwą jakość teksturowania, ponieważ każda
siatka otrzyma piksele w ilości proporcjonalnej do jej fizycznych wymiarów.
Przyjrzyjmy się temu dokładniej. Aby wygenerować w Blenderze mapę tekstury sza-
chownicowej, wykonaj następujące czynności:
1. W oknie UV/Image Editor (edytor współrzędnych UV i obrazów) wybierz polecenie
Image/New Image (obraz/nowy obraz).
2. Parametry nowego obrazu ustaw zgodnie z tym, co widać na rysunku 3.29. Upewnij
się też, że wygenerowana tekstura zostanie nałożona na siatki i będzie widoczna
w oknie widokowym. Możliwość obejrzenia jej na modelach ma zasadnicze znaczenie.

Rysunek 3.29. Aby wykryć ewentualne problemy mapowania, nałóż na modele specjalną
teksturę w formie regularnej kratki UV
Źródło: Blender.

Kratka UV nałożona na modele pozwala dość dobrze ocenić, jak piksele tekstury
układają się na poszczególnych siatkach. Istotne są dwa szczegóły:
■ Jeśli pola szachownicy nie są kwadratami, lecz przyjmują kształt wydłużonych pro-
stokątów lub przekrzywionych równoległoboków, to mapowanie wymaga korekty.
104 Rozdział 3  Modułowe środowiska i siatki statyczne

Wszystkie pola powinny mieć kształt kwadratu. W przeciwnym razie tekstura zo-
stanie zdeformowana.
■ Upewnij się, że pola szachownicy na wszystkich modelach mają takie same wymia-
ry. Jeśli tak nie jest, to znaczy, że rozkład pikseli teksturowych między poszczegól-
ne modele będzie nieproporcjonalny. A zatem może się okazać, że mały obiekt po-
chłania znaczną część tekstury, a duży — o wiele mniejszą. W takiej sytuacji mały
obiekt będzie nadmiernie szczegółowy, a duży będzie rozmazany i mało wyraźny.
Zachowanie stałych wymiarów pól szachownicy spowoduje, że rozkład gęstości tek-
selowej będzie równomierny (rysunek 3.30).

Rysunek 3.30. Skoryguj mapowanie UV, aby rozkład gęstości tekselowej był w miarę równomierny
Źródło: Blender.

Importowanie i konfigurowanie środowisk w Unity


Zestaw środowiska modułowego to zebrane razem wszystkie jego elementy, czyli mo-
duły. Przez układanie, powielanie i łączenie tych elementów w Unity tworzysz rozma-
ite warianty środowiska dla swojej gry. Zazwyczaj każdy moduł jest eksportowany
z Blendera jako odrębny i niezależny plik FBX. Proces eksportowania takich plików
opisałem szczegółowo w rozdziale 2. Na rysunku 3.31 pokazałem przykładowy zestaw
środowiskowy zaimportowany do projektu w Unity.
Po zaimportowaniu zestawu musisz poświęcić trochę czasu na staranne jego skonfigu-
rowanie. Szczególnie powinieneś się skoncentrować na mapowaniu światła i wykry-
waniu kolizji. Jeśli siatki będą miały tylko jeden kanał (zestaw) UV, to Unity automa-
tycznie użyje go do przypisania zarówno standardowych tekstur, jak i map światła.
Importowanie i konfigurowanie środowisk w Unity 105

Rysunek 3.31. Każdy moduł środowiska jest importowany do Unity jako odrębny plik FBX
Źródło: Unity Technologies.

Pozostawienie takiego stanu rzeczy bez zmian najprawdopodobniej spowoduje nie-


prawidłowy wygląd modeli z powodu złego mapowania światła. Pewną poprawę mo-
żesz uzyskać przez włączenie opcji Generate Lightmap UVs (generuj współrzędne UV
mapy światła) we właściwościach siatki (rysunek 3.32). Musisz się jednak liczyć z tym,
że niektóre problemy oświetleniowe zostaną nadal nierozwiązane, zwłaszcza te na
powierzchniach kulistych i organicznych. Wtedy będziesz musiał wrócić do Blendera
i wygenerować odrębny kanał UV dla mapy światła.
W Unity możesz łatwo wygenerować dane kolizyjne dla zaimportowanej siatki, bo
wystarczy, że w panelu Inspector (inspektor) zaznaczysz wśród właściwości siatki
opcję Generate Colliders (generuj zderzacze) — zob. rysunek 3.32. Spowoduje to, że
każda siatka w scenie zostanie wyposażona w zderzacz siatkowy, który nie dopuści, by
inny obiekt, np. gracz, przez nią przeniknął.
Jednak włączenie tej opcji — i w ogóle zderzacze siatkowe — powoduje zwiększone
zapotrzebowanie na moc obliczeniową, a zatem przy dużej liczbie siatek i zderzaczy
wydajność gry może spaść poniżej dopuszczalnego poziomu, a na urządzeniach mo-
bilnych gra może wcale nie zadziałać. Dlatego zderzaczy siatkowych należy używać
tylko wtedy, gdy jest to konieczne ze względu na precyzję wykrywania kolizji. W większo-
ści przypadków wystarczają do tego metody przybliżone. Pozostaw więc opcję Generate
Colliders wyłączoną i ręcznie dopasuj zwykłe zderzacze prostopadłościenne i kuliste do
przybliżonych obrysów elementów środowiska. Zderzacze prostopadłościenne i kuliste
nie wymagają takich mocy obliczeniowych jak siatkowe (rysunek 3.33).
106 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.32. Generowanie współrzędnych UV mapy światła dla siatki


Źródło: Unity Technologies.

Rysunek 3.33. Składniki kolizyjne można dodawać do siatek ręcznie i mogą to być zderzacze
w formie zwykłych prymitywów
Źródło: Unity Technologies.
Stosowanie prefabrykatów 107

Stosowanie prefabrykatów
Moduły wchodzące w skład zestawu środowiskowego są elementami podstawowymi
wielokrotnego użytku. Są podstawowe w tym sensie, że dopiero w wyniku ich łączenia
powstają rzeczy skomplikowane, a wielokrotność użytku oznacza, że każdy moduł
może być użyty wiele razy i w różnych miejscach. W związku z tym często okazuje się
(przekonasz się, gdy zaczniesz tworzyć sceny w Unity), że poziom zawiera wiele po-
wtarzających się kombinacji tych samych modułów. Mogą to być np.: całe korytarze,
narożne fragmenty pomieszczeń, hole, tunele czy pokoje, które pomimo że same skła-
dają się z kilku połączonych modułów, powtarzają się w określonych konfiguracjach
w wielu miejscach tego samego poziomu. Niektóre środowiska mają przykładowo wiele
jednakowych pokoi lub tak samo przebiegających korytarzy. Jest to wyższy poziom mo-
dułowości. Można oczywiście za każdym razem od nowa składać każdą taką kombinację
z elementów podstawowych, ale dużo łatwiejsze jest stosowanie tzw. prefabrykatów,
czyli pogrupowanych już modułów. Prefabrykaty, podobnie jak moduły, nadają się do
wielokrotnego użytku, zupełnie jakby były pojedynczymi siatkami (rysunek 3.34).

Rysunek 3.34. Kolekcja prefabrykatów, które można zastosować w wielu aranżacjach


Źródło: Unity Technologies.

Aby w Unity utworzyć prefabrykat, po prostu kliknij prawym przyciskiem myszy pu-
ste miejsce w panelu Project i z podręcznego menu wybierz polecenie Create/Prefab
(utwórz/prefabrykat) — rysunek 3.35. Następnie nadaj prefabrykatowi sensowną nazwę,
która będzie opisywała jego zawartość.
108 Rozdział 3  Modułowe środowiska i siatki statyczne

Rysunek 3.35. Tworzenie prefabrykatu


Źródło: Unity Technologies.

Po utworzeniu prefabrykatu wskaż wszystkie siatki, które powinny się w nim znaleźć.
Najpierw wskaż tę, która będzie nadrzędna, a potem, korzystając z panelu Hierarchy
(hierarchia), ustal, które mają być podrzędne. Gdy już relacja nadrzędności zostanie
ustalona, zaznacz obiekt nadrzędny i przeciągnij go do prefabrykatu w panelu Project.
Wraz z obiektem nadrzędnym znajdą się tam również obiekty podrzędne (rysunek 3.36).

Rysunek 3.36. Tworzenie prefabrykatów z ustalonej konfiguracji siatek


Źródło: Unity Technologies.
Wsad statyczny 109

Wsad statyczny
Większość elementów środowiska, takich jak ściany, podłogi czy sufity, prawdopo-
dobnie w ogóle nie będzie się przemieszczać ani zmieniać w trakcie gry. Po prostu takie
obiekty zawsze będą tkwić na swoich miejscach jako elementy scenografii. A skoro
są niezmienne, nazwiemy je obiektami statycznymi. W przeciwieństwie do nich obiekty
takie jak postać gracza, wrogowie i wszelkie modyfikowalne rekwizyty będziemy nazywać
dynamicznymi.
Jeśli środowisko zawiera elementy statyczne, powinieneś je oznaczyć w edytorze Unity,
aby mogły być renderowane w trybie wsadowym, co może znacznie poprawić wydajność
gry na wszystkich platformach, zarówno stacjonarnych, jak i przenośnych. W tym
celu zaznacz wszystkie statyczne elementy środowiska, a następnie włącz opcję Static
(statyczne) w panelu Inspector — tak jak na rysunku 3.37.

Rysunek 3.37. Wszystkie nieruchome obiekty oznacz jako wsad statyczny


Źródło: Unity Technologies.

Podsumowanie
W tym rozdziale skupiliśmy się na modelowaniu środowiska z uwzględnieniem jego
modułowości. Opisany tok pracy wymagał użycia dwóch aplikacji: Blendera i Unity.
W pierwszej chwili tworzenie środowiska modułowego wydaje się łatwe, bo przypo-
mina zabawę klockami. Ogólnie rzecz biorąc, to prawda, ale po głębszej analizie całego
procesu widać, że jest to zajęcie dość pracochłonne i wymagające znajomości wielu tajni-
ków. Ważne jest zachowanie odpowiednich proporcji i rozmiarów poszczególnych
modułów, aby później dały się łatwo łączyć w jedną większą całość. Dużo uwagi trzeba
też poświęcić kwestiom mapowania UV i tworzenia prefabrykatów. Krótko mówiąc:
tworzenie środowiska techniką modułową wymaga trochę czasu i nie łudź się, że uda
110 Rozdział 3  Modułowe środowiska i siatki statyczne

Ci się to zrobić w pośpiechu. Dokładnie zaplanuj wszystkie moduły, ustal ich wymiary
i dobrze opracuj mapowanie UV, a w ogólnym rozrachunku zaoszczędzisz niemało
czasu.
Podczas lektury tego rozdziału możesz używać plików ćwiczeniowych zawierających
kompletny zestaw środowiska modułowego. Pliki te możesz pobrać ze strony: ftp://ftp.
helion.pl/przyklady/unible.zip. Jeśli zaciekawiła Cię problematyka modelowania środo-
wisk i chciałbyś się dowiedzieć czegoś więcej, zapraszam do obejrzenia mojego poradnika
filmowego pt. Modular Asset Building dostępnego pod adresem: www.3dmotive.com.
R OZ DZ I AŁ 4

T EREN

Sztuka prostoty jest tajemnicą złożoności.


— Douglas Horton

Po przeczytaniu tego rozdziału powinieneś:


■ znać zalety i wady systemu generowania terenów w Unity;
■ znać alternatywne metody tworzenia terenów dostępne w Blenderze;
■ umieć rzeźbić tereny i malować je teksturami;
■ umieć posługiwać się blenderowymi narzędziami rzeźbiarskimi;
■ umieć tworzyć geometrie dróg pasujące do terenu.
Niemal każda gra, której akcja toczy się w środowisku plenerowym, a więc w lesie, na
pustyni, na nizinie, w górach czy na ulicy, wymaga odpowiednio wymodelowanego tere-
nu — terenu w znaczeniu technicznym, a nie potocznym. Dla nas pojęcie teren będzie
oznaczało dużą i zazwyczaj gęstą siatkę, reprezentującą podłoże albo inaczej stały grunt
danego poziomu.
Siatki tego typu można tworzyć na wiele sposobów. Unity oferuje łatwy, ale wydajny
system generowania terenów, który pokrótce omówię w następnym podrozdziale. Ma
on jednak kilka istotnych ograniczeń i twórcy gier często zmuszeni są do szukania innych
rozwiązań. Jednym z nich jest ręczne modelowanie terenu w odpowiedniej do tego
aplikacji, np. w Blenderze. I właśnie tym zajmiemy się w pozostałej części rozdziału.

Tworzenie terenu w Unity


Unity zawiera mnóstwo narzędzi przeznaczonych do rzeźbienia i malowania rozległych
siatek mogących stanowić podłoże dla sceny. W tym podrozdziale omówię je pokrótce
i wskażę ich wady oraz zalety. Pełną dokumentację systemu tworzenia terenu w Unity

111
112 Rozdział 4  Teren

znajdziesz w oficjalnej witrynie tej aplikacji (http://docs.unity3d.com/Documentation/


Manual/Terrains.html). Na rysunku 4.1 jest pokazana scena z gry Boot Camp, do której
teren został wykonany za pomocą narzędzi dostępnych w Unity.

Rysunek 4.1. Teren wygenerowany w systemie Unity dla gry Boot Camp. Jeśli chcesz,
możesz pobrać ten teren za darmo z Unity Asset Store
Źródło: Unity Technologies.

Prześledźmy typowy tok pracy konieczny do wygenerowania prostego terenu za po-


mocą narzędzi dostępnych w Unity. Zaprezentowany tu opis odnosi się do Unity 4.3.
Wersje wcześniejsze wymagały trochę innego podejścia. Aby rozpocząć tworzenie terenu,
po prostu wybierz polecenie GameObject/Create Other/Terrain (obiekt gry/utwórz inny/
teren), tak jak na rysunku 4.2. Na środku sceny pojawi się domyślna siatka terenu.

Rysunek 4.2. Generowanie terenu w Unity


Źródło: Unity Technologies.
Tworzenie terenu w Unity 113

Uwa ga
Jeśli interesuje Cię tworzenie terenów w starszych wersjach Unity, obejrzyj nagrany przeze mnie kurs
wideo pt. Unity Assets & Terrain dostępny pod adresem: www.3dmotive.com.

Parametry terenu
Przed przystąpieniem do rzeźbienia gór, przepaści, brzegów rzeki i innych szczegółów
krajobrazowych musisz skonfigurować ustawienia siatki terenu. Są one dostępne w pa-
nelu Inspector (inspektor), gdy siatka terenu jest zaznaczona. Za ich pośrednictwem mo-
żesz ustalić wymiary terenu, jego powierzchnię i ogólną topologię.
Wygenerowana przez Unity siatka terenu ma wymiary 2000×2000 jednostek globalnych,
co w praktyce oznacza powierzchnię 4 000 000 m2! Nie zawsze tak duży obszar jest
potrzebny, więc jeśli wystarczy Ci teren o mniejszej powierzchni, zmniejsz te wymiary.
Dla potrzeb prezentowanego przykładu ustawiłem 512×512 jednostek globalnych, a po-
zostałe parametry pozostawiłem bez zmian (rysunek 4.3).

Rysunek 4.3. Aby przygotować teren do rzeźbienia, skonfiguruj jego ogólną topologię
Źródło: Unity Technologies.

Uwa ga
Przy tworzeniu terenów lubię umieszczać w scenie źródło światła kierunkowego (zob. rysunek 4.3),
które ułatwia mi obserwowanie form i kształtów powstających w trakcie rzeźbienia. Nie jest to bez-
względnie konieczne, ale w oczywisty sposób się przydaje.
114 Rozdział 4  Teren

Ważnym parametrem terenu jest Heightmap Resolution (rozdzielczość mapy wysoko-


ści). Ustawienie to określa pikselowe wymiary kwadratowej tekstury, której Unity
używa do deformowania powierzchni terenu. Jej piksele są rzutowane na siatkę terenu
i w zależności od jasności powodują przesuwanie wierzchołków w górę (piksele jasne)
lub w dół (piksele ciemne). Im większa będzie rozdzielczość tej tekstury, tym więcej
szczegółów krajobrazowych będzie można w niej zawrzeć, ale z drugiej strony wzro-
śnie zapotrzebowanie na pamięć i obniży się wydajność gry. Trzeba więc zachować
umiar i postępować zgodnie z zasadą: zastosuj wartość najniższą spośród odpowiednich
dla danego projektu.

Rzeźbienie terenu
Za pomocą narzędzi służących do modelowania terenu możesz rzeźbić siatkę w oknie
widokowym w sposób interaktywny, czyli z możliwością obserwowania na bieżąco
skutków każdego posunięcia. W istocie rzeczy wszystko sprowadza się do modyfikowa-
nia wewnętrznej tekstury wysokościowej, o której wspomniałem w poprzednim punkcie.
Przeciąganie narzędziem po siatce terenu powoduje malowanie pikseli tekstury, a te
z kolei deformują siatkę.
Gdy w scenie zaznaczona jest siatka terenu, w panelu Inspector dostępne są rozmaite
pędzle (Brushes), co widać na rysunku 4.4. Po uaktywnieniu takiego pędzla po prostu
kliknij teren, aby uzyskać wzniesienie, lub kliknij przy wciśniętym klawiszu Shift, aby
uzyskać obniżenie istniejącego wzniesienia. Za pomocą parametrów Brush Size (roz-
miar pędzla) i Opacity (krycie) możesz regulować zakres i siłę działania używanego
narzędzia. Górzysty krajobraz pokazany na rysunku 4.4 wymodelowałem za pomocą
podstawowego pędzla w kształcie koła. Do łagodzenia ostrych nierówności możesz uży-
wać pędzli wygładzających.

Rysunek 4.4. Teren możesz rzeźbić metodą malowania


Źródło: Unity Technologies.
Tworzenie terenu w Unity 115

Uwa ga
Więcej informacji na temat rzeźbienia terenu znajdziesz w moim kanale YouTube: www.youtube.com/
watch?v=IhhGWK5VYUs.

Malowanie terenu teksturami


Po nadaniu siatce terenu właściwej formy czas na pomalowanie jej teksturami tereno-
wymi. Dopiero wtedy zacznie wyglądać, jakby była wykonana z rzeczywistych mate-
riałów, takich jak ziemia, trawa, skały, woda itp. Malowanie teksturami przypomina
rzeźbienie, bo też wykonuje się je za pomocą pędzli.
Tekstury do pokrywania siatek terenu będziesz tworzył najczęściej sam, ale do prze-
prowadzania rozmaitych testów doskonale nadają się te, które oferuje Unity. Aby sko-
rzystać z tych tekstur, musisz je zaimportować do projektu jako pakiet elementów terenu
— po prostu wybierz polecenie Assets/Import Package/Terrain Assets (elementy/importuj
pakiet/ elementy terenu), tak jak na rysunku 4.5.

Rysunek 4.5. Jeśli chcesz szybko poćwiczyć malowanie terenu teksturami, zaimportuj pakiet
gotowych tekstur
Źródło: Unity Technologies.
116 Rozdział 4  Teren

Jednak żeby zacząć malowanie, musisz najpierw zbudować paletę tekstur. W tym celu
wykonaj następujące czynności:
1. Zaznacz w scenie teren.
2. W panelu Inspector kliknij zakładkę Paint Texture (malowanie teksturą) — rysu-
nek 4.6.

Rysunek 4.6. Dodawanie tekstury do palety


Źródło: Unity Technologies.

3. Kliknij przycisk Edit Textures (edytuj tekstury) i z menu, które się otworzy, wybierz
Add Texture (dodaj teksturę).
4. Gdy otworzy się okno dialogowe Add Terrain Texture (dodaj teksturę terenu), wy-
bierz teksturę (i mapę normalnych, jeśli to konieczne), która ma być dodana do
palety, ustaw jej wymiary i kliknij przycisk Add (dodaj). Jeśli dodana tekstura była
pierwszą na Twojej palecie, to zostanie automatycznie nałożona na całą siatkę te-
renu jako tekstura bazowa lub domyślna. W prezentowanym przykładzie wybrałem
teksturę trawiastą i ustawiłem jej wymiary X oraz Y na 100 jednostek (rysunek 4.7).
Rozmiary ustalane na palecie tekstur są wymiarami scenicznymi i decydują o krotno-
ści powtórzeń tekstury na powierzchni terenu. Przy większych wartościach liczba
powtórzeń tekstury będzie mniejsza i na odwrót.
5. Teren zostanie pokryty w całości dodaną właśnie teksturą. Jeśli uznasz, że rozłoże-
nie jej kafelków jest niewłaściwe i trzeba zmienić jej wymiary, jeszcze raz kliknij
przycisk Edit Textures i wybierz tym razem polecenie Edit Texture (edytuj teksturę)
— rysunek 4.8.
Tworzenie terenu w Unity 117

Rysunek 4.7. Dodawanie tekstury do palety


Źródło: Unity Technologies.

Rysunek 4.8. Aby zmienić parametry tekstury, wybierz Edit Textures/Edit Texture
Źródło: Unity Technologies.

6. Po dodaniu tekstury bazowej możesz dodawać kolejne, klikając za każdym razem


przycisk Edit Textures i wybierając polecenie Add Texture. Jednak te tekstury, w prze-
ciwieństwie do bazowej, nie będą już automatycznie nakładane i będziesz to musiał
robić ręcznie, używając odpowiednich pędzli. Tam, gdzie namalujesz nową teksturę,
tekstura bazowa zostanie zakryta.
7. Aby namalować nową teksturę, zaznacz ją na palecie w panelu Inspector i wybierz
pędzel. Następnie za pomocą myszy „zamaluj” odpowiedni fragment terenu. Jak wi-
dać na rysunku 4.9, technika ta pozwala tworzyć złożone i bogate w szczegóły tereny.
118 Rozdział 4  Teren

Rysunek 4.9. Malowanie terenu teksturami dodanymi do palety


Źródło: Unity Technologies.

Ocena terenów generowanych przez Unity


Unity oferuje kilka naprawdę znakomitych narzędzi do modelowania terenów. W po-
przednim podrozdziale poznałeś przykład tego, jak za pomocą zaledwie paru kliknięć
i niewielkiej modyfikacji kilku parametrów można wygenerować teren kompletnie
poteksturowany i w pełni dostosowany do naszych potrzeb. Jednak system ten ma kilka
wad, i to tak poważnych, że wielu twórców gier postanowiło szukać innych rozwiązań.
Wady te dotyczą następujących zagadnień:
■ Wydajność. Tradycyjnie już twórcy gier unikają stosowania terenów wygenero-
wanych w Unity, jeśli gra ma działać na urządzeniach przenośnych z systemami
takimi jak Android czy iOS. Wynika to głównie z kafelkowania, dużej liczby ścianek
i ogólnie wielkiej zasobożerności takich terenów. Wprawdzie najnowsze modele
urządzeń mobilnych są szybkie i mają spore możliwości, co nawet do pewnego
stopnia wpłynęło na zmianę powyższego nastawienia, ale nadal tereny generowane
przez Unity pozostawiają wiele do życzenia pod względem optymalizacji. Często
zawierają więcej wierzchołków niż to jest konieczne i zajmują zbyt dużo miejsca
w pamięci. Dla komputerów stacjonarnych, konsoli czy najbardziej zaawansowanych
urządzeń mobilnych może nie jest to wielki problem, ale dla przeciętnego sprzętu
może stanowić barierę nie do pokonania, zwłaszcza przy braku optymalizacji również
innych aspektów gry. Krótko mówiąc: żeby poprawić wydajność, warto poszukać
innego rozwiązania.
■ Optymalność topologii. Topologia siatki, w tym również siatki terenu, wiąże się
nie tylko z liczbą jej składników w postaci wierzchołków, krawędzi i ścianek, ale
również z ich ułożeniem. Unity generuje tereny w sposób proceduralny, czyli buduje
je według określonego przepisu, wprowadzając jedynie takie modyfikacje, które
wynikają z wartości parametrów ustawionych na zakładce Terrain Settings (ustawienia
Modelowanie terenu w Blenderze 119

terenu) panelu Inspector. Parametry te omawiałem w poprzednim podrozdziale,


w punkcie „Parametry terenu”, a należą do nich m.in.: Width (szerokość), Length
(długość) i Height (wysokość). Poza tymi parametrami nie mamy na nic wpływu.
Nie możemy np. decydować, gdzie siatka powinna być bardziej zagęszczona, a gdzie
teselacja może być mniejsza. W rezultacie otrzymujemy siatkę uśrednioną, w której
rozkład wierzchołków, krawędzi i ścianek jest niemal stały na całej powierzchni. Coś
takiego na ogół nie sprzyja optymalizacji, bo przecież najczęściej spora część tere-
nu nigdy nie będzie oglądana z bliska i w związku z tym nie musi być tak szczegó-
łowo wymodelowana jak rejony, w których gra rzeczywiście się toczy. Aby zoptyma-
lizować siatkę terenu pod tym kątem, trzeba znaleźć taki sposób generowania, który
umożliwi nam większy wpływ na rozkład wierzchołków i ścianek.
■ Ograniczenia mapy wysokości. Wzniesienia i obniżenia terenu generowanego przez
Unity są określone przez płaską, pikselową mapę wysokości, co ma dość poważne
konsekwencje. Teoretycznie mapa ta znajduje się nad siatką terenu i jest rzutowana
w dół, powodując wznoszenie siatki tam, gdzie piksele są jasne, i obniżanie jej w miej-
scach, gdzie piksele są ciemne. Można w ten sposób wyrzeźbić nawet bardzo skom-
plikowane krajobrazy, ale pewnych formacji nie da się uzyskać. Nie da się tą me-
todą wymodelować np. nor, jaskiń, dziupli i innych tego typu miejsc, w których
między warstwami terenu występuje pusta przestrzeń. Jest to poważne ograniczenie
metody generowania terenów na podstawie mapy wysokości. Do pewnego stopnia
można to ograniczenie obejść, stosując dodatkowe obiekty siatkowe lub dodatko-
we tereny, ale żeby problem w pełni rozwiązać, trzeba siatkę terenu wymodelować
ręcznie w edytorze grafiki 3D.
W sumie te trzy powody stanowią solidną podstawę do tego, by poważnie myśleć o szu-
kaniu innych sposobów modelowania terenów. Chociaż narzędzia oferowane przez
Unity są niezwykle użyteczne, na pewno nie raz będziesz zmuszony do ręcznego wy-
modelowania terenu, aby mieć nad tym procesem większą kontrolę i przeprowadzić go
zgodnie z regułami optymalizacji. W następnych podrozdziałach sprawdzimy, czy Blender
może być w tym pomocny.

Modelowanie terenu w Blenderze


W Blenderze modelowanie terenu rozpoczynamy od utworzenia obiektu płaszczyzny
i przeprowadzenia stosownej teselacji. Płaszczyznę można utworzyć za pomocą polecenia
Add/Mesh/Plane (dodaj/siatkę/płaszczyznę) — tak jak na rysunku 4.10. Domyślnie
płaszczyzna taka składa się tylko z jednej ścianki.
W celu przeprowadzenia teselacji, która umożliwi wymodelowanie szczegółów terenu,
użyj narzędzia Subdivide (podziel). Uważaj przy tym, żeby nie tworzyć więcej ścianek
niż to jest konieczne, ale też nie przesadzaj w drugą stronę. Zbędne szczegóły zawsze
można usunąć, bądź to ręcznie, bądź proceduralnie.
120 Rozdział 4  Teren

Rysunek 4.10. Modelowanie terenu w Blenderze rozpocznij od utworzenia płaszczyzny za pomocą


odpowiedniego polecenia z menu Add. Nie zapomnij ustawić w panelu N długości i szerokości
terenu (1 jednostka = 1 metr)
Źródło: Blender.

Narzędzie Subdivide można uaktywnić, gdy obiekt jest zaznaczony i w trybie edycji.
W tym celu wykonaj jedną z poniższych czynności:
■ Wybierz z menu polecenie Mesh/Edges/Subdivide (siatka/krawędzie/podziel).
■ W przyborniku kliknij przycisk Subdivide.
■ Jeśli włączyłeś system sterowania zgodny z programem Maya, kliknij siatkę pra-
wym przyciskiem myszy przy wciśniętym klawiszu Ctrl (Windows) lub Command
(Mac OS) i z menu Specials (specjalne) wybierz polecenie Subdivide — tak jak na
rysunku 4.11.
Prawdopodobnie będziesz musiał powtórzyć tę operację wielokrotnie, żeby uzyskać
właściwą gęstość siatki.

Uwa ga
Alternatywną i odwracalną metodą zagęszczania siatki jest stosowanie modyfikatora Multiresolution
(wielorozdzielczość) z opcją Simple (prosty). Więcej informacji na temat tego modyfikatora znajdziesz
w dokumentacji Blendera (http://wiki.blender.org/index.php/Doc:2.6/Manual/Modifiers/Generate/
Multiresolution).

Gdy mamy już przygotowaną płaszczyznę, możemy przystąpić do wyboru jednej z trzech
metod dalszego postępowania. O żadnej z nich nie da się jednoznacznie powiedzieć,
że jest lepsza lub gorsza od pozostałych. Przy wyborze musisz się kierować swoimi
upodobaniami i rodzajem terenu, który masz wymodelować. Oto te trzy metody:
Modelowanie terenu w Blenderze 121

Rysunek 4.11. Dzielenie siatki na mniejsze ścianki


Źródło: Blender.

■ metoda edycji proporcjonalnej,


■ metoda tekstury przemieszczeń,
■ metoda rzeźbienia.

Metoda edycji proporcjonalnej


Metoda ta wzięła swoją nazwę od funkcji Proportional Editing (edycja proporcjonalna),
która w innych programach bywa też nazywana Soft Selection (miękkie zaznaczanie).
Wszelkie wzniesienia i obniżenia terenu wykonuje się tutaj przez przeciąganie w górę
bądź w dół wierzchołków siatki, a funkcja Proportional Editing przenosi te ruchy na
sąsiednie obszary, powodując, że deformacje siatki stają się mniej lub bardziej łagodne.
Zobaczmy, jak to wygląda w praktyce. Wykonaj następujące czynności:
1. Na pasku narzędziowym okna 3D View (widok 3D) kliknij przycisk Proportional
Editing i wybierz opcję Connected (połączone) — tak jak na rysunku 4.12. W ten spo-
sób włączysz edycję proporcjonalną w trybie Connected, co spowoduje, że transfor-
macje zaznaczonych wierzchołków będą się rozprzestrzeniały na kolejne wierzchołki
z sąsiedztwa, tyle że z coraz mniejszą siłą. W rezultacie nastąpi wygładzenie, albo
inaczej stopniowe zanikanie, wprowadzonej deformacji.
2. Zanim przesuniesz jakikolwiek wierzchołek, wybierz krzywą zanikania. W tym
celu kliknij przycisk Proportional Editing Falloff (zanikanie proporcjonalnej edycji)
i wybierz opcję Smooth (gładkie) — tak jak na rysunku 4.13.
122 Rozdział 4  Teren

Rysunek 4.12. W ramach przygotowań do modelowania terenu


włącz edycję proporcjonalną w trybie Connected
Źródło: Blender.

Rysunek 4.13. Wybierz krzywą zanikania dla edycji proporcjonalnej


Źródło: Blender.

3. Teraz możesz rozpocząć modelowanie. Po prostu zaznacz jeden lub kilka wierzchoł-
ków (niekoniecznie połączonych ze sobą) i za pomocą gizma transformacji prze-
ciągnij je w górę lub w dół. Edycja proporcjonalna automatycznie wygładzi wprowa-
dzoną deformację (rysunek 4.14).

Uwa ga
Podczas przeciągania gizma transformacji kursor będzie otoczony białym okręgiem o promieniu poka-
zującym zasięg działania edycji proporcjonalnej. Jeśli masz włączony system sterowania zgodny z pro-
gramem Maya, możesz ten okrąg zmniejszać i powiększać przez obracanie rolką myszy.

4. Postępuj tak, aż uformujesz wszystkie wzniesienia i zagłębienia terenu. Jeśli chcesz


mocniej zróżnicować jego rzeźbę, stosuj różne wartości promienia wyznaczającego
zasięg edycji proporcjonalnej. Wypróbuj też inne krzywe zaniku, np. Sharp (ostre)
i Random (losowe). Na rysunku 4.15 pokazany jest teren, który wymodelowałem
w taki właśnie sposób.
Modelowanie terenu w Blenderze 123

Rysunek 4.14. Rzeźbienie terenu z użyciem funkcji Proportional Editing. Zobacz, jak podnoszenie
tylko jednej ścianki spowodowało uniesienie również sąsiednich, dając w rezultacie wzniesienie
o łagodnych zboczach
Źródło: Blender.

Rysunek 4.15. Teren wymodelowany metodą edycji proporcjonalnej


Źródło: Blender.
124 Rozdział 4  Teren

Metoda tekstury przemieszczeń


W metodzie tekstury przemieszczeń siatka płaszczyzny jest deformowana automatycz-
nie zgodnie z wartościami pikseli tworzącymi specjalną teksturę (mapę wysokości).
Jest to więc metoda podobna do tej, jaką oferuje Unity.
Mapa wysokości to nic innego jak obraz w skali szarości, w którym obszary jasne
oznaczają wzniesienia, a obszary ciemne — zagłębienia. Zasadnicza różnica między sto-
sowaniem tej metody w Blenderze a stosowaniem jej w Unity polega na tym, że Blender
pozwala na dalsze rzeźbienie siatki już po przemieszczeniu wierzchołków. W zdefor-
mowanej siatce można nadal edytować wierzchołki, krawędzie i ścianki przy użyciu
typowo modelarskich narzędzi. Silnik Unity zainstalowany bez żadnych dodatków nie
oferuje tego typu narzędzi.
Zobaczmy, jak w praktyce spisuje się druga metoda modelowania terenu. Wykonaj
następujące czynności:
1. W panelu Texture (tekstura) wczytaj mapę wysokości bezpośrednio z pliku albo
wygeneruj ją w sposób automatyczny. W tym celu kliknij przycisk New (nowy), tak
jak pokazano na rysunku 4.16.

Rysunek 4.16. Generowanie nowej tekstury


Źródło: Blender.

2. Rozwiń listę Type (typ) i wybierz z niej pozycję Voronoi (komórki Woronoja) lub
Clouds (chmury). Tekstura typu Clouds jest generowanym losowo układem pikseli
w rozmaitych odcieniach szarości, który przypomina wyglądem kłęby chmur. Użycie
tych pikseli do przemieszczenia wierzchołków siatki może dać w rezultacie gładki,
ale naturalnie wyglądający teren. Podgląd tekstury jest wyświetlany w okienku Preview
(podgląd). To właśnie jej użyjesz jako tekstury przemieszczenia (rysunek 4.17).
Modelowanie terenu w Blenderze 125

Rysunek 4.17. Generowanie sztucznego obrazu chmur jako tekstury przemieszczenia


Źródło: Blender.

3. Nie zapomnij o wyposażeniu siatki terenu we współrzędne mapowania UV. Aby to


zrobić, zaznacz wszystkie ścianki siatki i wybierz polecenie Mesh/UV Unwrap/Smart
UV Project (siatka/rozwinięcie UV/inteligentne rzutowanie UV) — tak jak na ry-
sunku 4.18. Zaakceptuj domyślne wartości parametrów. Nie musisz stosować rzu-
towania inteligentnego; możesz użyć jakiejkolwiek innej metody rozwijania siatki,
aby tylko rozłożyć ją na całej przestrzeni współrzędnych UV od 0 do 1.
4. Po przypisaniu siatce terenu współrzędnych UV czas zastosować modyfikator Displa-
ce (przemieszczenie). Ustanowi to połączenie między siatką terenu a mapą wysokości.
Otwórz zakładkę Modifiers (modyfikatory) i przypisz siatce wspomniany modyfikator
(rysunek 4.19).

Uwa ga
Więcej informacji na temat modyfikatora Displace znajdziesz w dokumentacji Blendera (http://wiki.blender.
org/index.php/Doc:2.6/Manual/Modifiers/Deform/Displace).
126 Rozdział 4  Teren

Rysunek 4.18. Rzutowanie terenu na przestrzeń tekstury


Źródło: Blender.

Rysunek 4.19. Modyfikator Displace jest dostępny na zakładce Modifiers


Źródło: Blender.

5. W polu Texture (tekstura) wstaw mapę wysokości (rysunek 4.20). Powinno to auto-
matycznie zdeformować siatkę terenu i będziesz mógł od razu ocenić topologiczne
działanie mapy wysokości. Za pomocą parametru Strength (siła) możesz regulować
Modelowanie terenu w Blenderze 127

Rysunek 4.20. Siatka terenu zdeformowana zgodnie z mapą wysokości


Źródło: Blender.

intensywność jej działania. Wartości ujemne (takie jak –1 czy –2) odwracają działanie
mapy, powodując, że piksele jasne przyjmują rolę pikseli ciemnych i na odwrót.
Pamiętaj, że aby siatka została na trwale zdeformowana, musisz zatwierdzić mo-
dyfikator.

Metoda rzeźbienia
Ostatnią z wymienionych metod modelowania terenu jest rzeźbienie. W metodzie tej,
podobnie jak w Unity, operujemy narzędziami przypominającymi pędzle i za ich po-
mocą kształtujemy siatkę terenu zupełnie tak, jakby była wykonana z gliny. Jednak
system pędzli w Blenderze działa bez żadnej mapy wysokości, a to oznacza, że tu można
rzeźbić szczegóły rzeczywiście w trzech wymiarach.
Teraz tylko pokrótce opiszę, jak wyrzeźbić teren przy użyciu narzędzi blenderowych,
chociaż o nich samych warto by powiedzieć znacznie więcej. Tak naprawdę to należałoby
im poświęcić całą książkę! Jeśli interesuje Cię ten temat i chciałbyś dokładniej poznać
narzędzia rzeźbiarskie Blendera, zachęcam do lektury dokumentacji tego programu,
a szczególnie artykułu zamieszczonego na stronie: http://wiki.blender.org/index.php/
Doc:2.6/Manual/Modeling/Meshes/Editing/Sculpt_Mode.
Aby wyrzeźbić teren płaskiej siatki, wykonaj następujące czynności:
1. Zaznacz płaszczyznę i włącz tryb rzeźbienia (Sculpt Mode) — tak jak na rysunku
4.21. W przyborniku po lewej stronie pojawią się narzędzia rzeźbiarskie i ich usta-
wienia. Pamiętaj, że narzędzia te współpracują z urządzeniami reagującymi na nacisk,
więc możesz nimi sterować za pomocą tabletów graficznych, takich jak Wacom
Bamboo, Intuos czy Huion.
128 Rozdział 4  Teren

Rysunek 4.21. Włączanie trybu rzeźbienia


Źródło: Blender.

2. Wybierz typ pędzla. Do wyboru jest wiele pędzli, ale przy rzeźbieniu terenów najlepiej
sprawdzają się Brush (pędzel) i SculptDraw (rzeźbiące wyciąganie). Aby wybrać
żądany pędzel, kliknij okienko z podglądem aktywnego pędzla i na palecie, która się
otworzy, wskaż właściwą miniaturę (rysunek 4.22).

Rysunek 4.22. Wybieranie typu pędzla


Źródło: Blender.
Modelowanie terenu w Blenderze 129

3. Za pomocą suwaka Radius (promień) ustal zasięg oddziaływania pędzla, a suwakiem


Strength (siła) ustaw intensywność tego oddziaływania (rysunek 4.23).

Rysunek 4.23. Ustawianie zasięgu i siły oddziaływania pędzla, a także ustalanie,


czy powinien działać w trybie dodawania, czy odejmowania
Źródło: Blender.

4. Jak widać na rysunku 4.23, oba pędzle (Brush i SculptDraw) mają dwa tryby działania:
Add (dodawanie) i Subtract (odejmowanie). Domyślnie włączony jest tryb Add, co
oznacza, że jeśli przy aktywnym pędzlu klikniesz siatkę terenu (myszą lub piórkiem
tabletu), obszar podlegający działaniu pędzla zostanie wyciągnięty w górę. Tryb Sub-
tract, włączany przez wciśnięcie dodatkowo klawisza Ctrl (Windows) lub Command
(Mac OS), odwraca działanie pędzla i powoduje wtłaczanie terenu w dół.
5. Jeśli podczas malowania przytrzymasz wciśnięty klawisz Shift, uaktywnisz tymcza-
sowo pędzel Smooth (wygładzanie). Oczywiście możesz go uaktywnić również za
pośrednictwem wspomnianej wcześniej palety. Pędzel ten rozpoznaje ułożenia ścia-
nek na podstawie ustawienia wektorów normalnych, a następnie wprowadza uśred-
nianie, co w rezultacie daje płynniejsze przejścia między sąsiednimi ściankami. Takie
działanie jest szczególnie przydatne przy opracowywaniu terenów o stosunkowo nie-
wielkiej rozdzielczości. Przykład wyrzeźbionego w ten sposób terenu jest pokazany na
rysunku 4.24.

Uwa ga
Czasami będziesz chciał ograniczyć deformowanie terenu tylko do jednego kierunku, aby móc kontrolo-
wać wysokość, na jaką dany obszar jest podnoszony lub obniżany. Wtedy deformowanie powinno się
odbywać wyłącznie wzdłuż osi Z, a ograniczenie takie uzyskasz, jeśli z listy rozwijanej Sculpt Plane
(płaszczyzna rzeźbienia), zakreślonej na rysunku 4.24, wybierzesz opcję Z Plane (płaszczyzna Z).
130 Rozdział 4  Teren

Rysunek 4.24. Teren wyrzeźbiony i wygładzony


Źródło: Blender.

Rozdzielczość terenu
Niekiedy po wyrzeźbieniu terenu okazuje się, że jest on zbyt szczegółowy jak na po-
trzeby tworzonej gry. Liczba ścianek jest po prostu za duża, aby kolejne sceny mogły
być renderowane w czasie rzeczywistym. Zdarza się, że liczebność ścianek osiąga poziom
setek tysięcy, a nawet milionów, i wtedy konieczne staje się zmniejszenie rozdzielczości
jeśli nie całej siatki, to przynajmniej jej części.
Teoretycznie możesz usuwać ścianki i krawędzie, posługując się takimi narzędziami
jak Cut (wycinanie), Delete (usuwanie) i Merge (łączenie), ale jest to wysoce nieprak-
tyczne, bo wszystko trzeba robić ręcznie. Na szczęście istnieje możliwość zautomatyzo-
wania tego procesu (przynajmniej w pewnym stopniu) przez zastosowanie modyfikatora
Decimate (dziesiątkowanie), który proceduralnie zmniejsza liczbę ścianek w siatce. Jak
wszystkie modyfikatory jest dostępny na zakładce Modifiers pokazanej na rysunku 4.25.

Ostrzeżeni e
Zmniejszenie liczby ścianek w siatce prowadzi do zmiany jej topologii. Im bardziej zmniejszasz tę liczbę,
tym bardziej zmniejsza się szczegółowość siatki i tym mocniej różni się ona od swojej pierwotnej postaci.

Do sterowania modyfikatorem Decimate służy głównie parametr Ratio (stosunek),


którego wartość domyślna wynosi 1 i jeśli nie wprowadzisz innej, siatka pozostanie
bez zmian i zachowa wszystkie ścianki. Przy wartości 0,5 siatka utraci mniej więcej
połowę ze swej szczegółowości i liczba jej ścianek zmniejszy się o ok. 50%. Na rysunku
4.26 pokazany jest rezultat zdziesiątkowania siatki z rysunku 4.25 do ok. 20% jej pier-
wotnej rozdzielczości.
Malowanie terenu teksturą 131

Rysunek 4.25. Modyfikator Decimate zmniejsza liczbę ścianek w siatce


Źródło: Blender.

Rysunek 4.26. Obniżenie rozdzielczości terenu za pomocą modyfikatora Decimate może dać
rezultat w postaci siatki zoptymalizowanej, ale może ją też zniszczyć. Zachowaj ostrożność!
Źródło: Blender.

Malowanie terenu teksturą


Po wymodelowaniu powierzchni terenu przy użyciu opisanych wyżej (lub innych)
technik trzeba go pomalować teksturą, czyli nałożyć na siatkę obraz, który sprawi, że
całość będzie wyglądała jak prawdziwy teren ze skałami, z trawą, śniegiem itp. Można
to zrobić na kilka sposobów, np. utworzyć odpowiednią teksturę w oddzielnym pro-
gramie graficznym, takim jak GIMP czy Photoshop, i potem nałożyć ją na siatkę terenu
zgodnie ze współrzędnymi UV — jest to klasyczna metoda teksturowania obiektów
132 Rozdział 4  Teren

siatkowych. Lecz Blender oferuje narzędzia umożliwiające wykonanie tego zadania


w sposób bardziej intuicyjny i bezpośredni, bo polegający na nanoszeniu tekstury metodą
malowania. W kolejnych punktach pokażę, jak to się robi.

Wyznaczanie współrzędnych UV terenu


Przed rozpoczęciem teksturowania, niezależnie od wybranej metody, trzeba przypisać
siatce właściwe współrzędne UV. Zagadnienie to opisałem dokładnie w rozdziale 3., w czę-
ści zatytułowanej „Mapowanie UV i tworzenie tekstur”. Mówiąc krótko: współrzędne
UV wyznaczają dwustronną relację, albo inaczej odwzorowanie, między dwuwymiarową
teksturą a trójwymiarową siatką. W blenderowym edytorze współrzędnych UV i obrazów
(UV/Image Editor) można z łatwością wygenerować specjalną teksturę obrazującą
rozkład współrzędnych UV w postaci biało-szarej szachownicy. Dzięki tej teksturze
można szybko ocenić jakość mapowania UV.
Gdy mapowanie UV jest prawidłowe, kratki szachownicy widoczne na powierzchni
siatki są kwadratami (mają wysokość równą szerokości) i wszędzie mają takie same
rozmiary. Taki wygląd szachownicy świadczy o tym, że gęstość tekseli jest jednakowa
na całej powierzchni siatki i nie występują zniekształcenia. Oczywiście taki obrazek
rzadko otrzymuje się od razu po wygenerowaniu współrzędnych UV i trzeba poświęcić
trochę czasu, żeby za pomocą narzędzi dostępnych w edytorze uzyskać stan przynajmniej
zbliżony do idealnego. W przypadku skomplikowanych modeli pracochłonność tego
procesu może być bardzo duża. Lecz bez dobrej jakości mapowania UV nawet naj-
lepszej tekstury nie da się prawidłowo nałożyć, a zatem nie warto żałować czasu na ten
przygotowawczy etap. Na rysunku 4.27 pokazany jest wyrzeźbiony teren z nałożoną
szachownicą UV, której wygląd wskazuje, że można przystąpić do teksturowania.

Uwa ga
Gęstość tekselowa ma znaczenie w grach czasu rzeczywistego. Każda tekstura ma określoną liczbę pik-
seli wyrażoną przez szerokość i wysokość obrazu, lecz na ekranie rzadko jest wyświetlana w swojej na-
turalnej wielkości i perspektywie. Zazwyczaj jest ściskana lub rozciągana (przez ponowne próbkowanie)
na powierzchniach trójwymiarowych siatek o rozmaitych rozmiarach, jak papier, w który owijane są po-
darunki. Gdy duża tekstura jest upychana na małej powierzchni, gęstość tekselowa staje się większa.
Gdy mała tekstura rozkłada się na dużej powierzchni, jej gęstość tekselowa maleje.

Generowanie tekstury
Mamy wyrzeźbiony teren z odpowiednim mapowaniem UV, a zatem możemy rozpo-
cząć malowanie tekstury. Na początek otwórz w Blenderze okno UV/Image Editor
(edytor współrzędnych UV i obrazów), aby utworzyć nową, pustą teksturę, która bę-
dzie zawierała wszystkie piksele zdatne do malowania. Na dolnym pasku edytora kliknij
przycisk New (nowy) — tak jak na rysunku 4.28.
Malowanie terenu teksturą 133

Rysunek 4.27. Przed malowaniem terenu teksturą należy sprawdzić prawidłowość mapowania UV
Źródło: Blender.

Rysunek 4.28. Tworzenie nowej tekstury w oknie UV/Image Editor


Źródło: Blender.

Ja nadałem tej teksturze nazwę TerrainTexture (tekstura terenu) i pozostawiłem jej


domyślne wymiary 1024×1024 pikseli. W zależności od potrzeb możesz odpowiednio
zwiększyć te wymiary lub je zmniejszyć. Zazwyczaj zmieniam też kolor tła z czarnego
na średnio szary (0,5, 0,5, 0,5). Na koniec wyłączam opcję Alpha (alfa), bo tekstury tere-
nów na ogół nie mają obszarów przezroczystych. Zauważ, że wszystko to są preferencje,
134 Rozdział 4  Teren

a nie wymagania. Zawsze trzeba wiedzieć, czego się potrzebuje, i w zależności od tego
dobierać stosowne ustawienia. Warto też pamiętać, co na temat tworzenia tekstur napi-
sałem w poprzednim rozdziale. Po ustawieniu parametrów nowej tekstury kliknij OK
(rysunek 4.29).

Rysunek 4.29. Ustawianie parametrów tworzonej tekstury


Źródło: Blender.

Malowanie w oknie UV/Image Editor


Istnieją dwie zasadnicze metody malowania tekstur:
■ w oknie UV/Image Editor;
■ w standardowym oknie widokowym 3D View.
Nie są to metody wykluczające się; można używać obu. Na razie przyjrzymy się pierwszej
z nich.
1. Na pasku narzędziowym okna UV/Image Editor włącz tryb Paint (malowanie) —
tak jak na rysunku 4.30. Spowoduje to zmianę narzędzi i opcji dostępnych w przy-
borniku po lewej stronie edytora (zob. rysunek 4.31). Są tam pędzle i inne narzę-
dzia związane z malowaniem tekstur. Działają one podobnie jak narzędzia służące
do rzeźbienia terenu, z tym że zamiast deformować siatkę, malują piksele tekstury.
2. Wybierz pędzel i ustaw jego kolor, rozmiar oraz intensywność. Zacznij malować!
Podobnie jak w przypadku narzędzi rzeźbiarskich teraz też możesz posłużyć się
tabletem graficznym.
Podczas malowania w oknie UV/Image Editor lubię mieć też otwarte okno 3D View,
bo pozwala mi to na bieżąco obserwować, jak pod wpływem mojego malowania zmie-
nia się wygląd siatki. Oczywiście w oknie 3D View musi być wtedy włączone cieniowanie
typu Texture (teksturowe), a nie Solid (bryłowe) czy Wireframe (szkieletowe), bo tylko
wtedy tekstura będzie renderowana na siatce (rysunek 4.31).
Malowanie terenu teksturą 135

Rysunek 4.30. Włączanie trybu malowania


Źródło: Blender.

Rysunek 4.31. Malowanie tekstury na siatce za pośrednictwem okna UV/Image Editor


Źródło: Blender.

Trzeba też dodać, że wszystkie dostępne tu pędzle są wyposażone w rozmaite tryby mie-
szania. Co więcej, tryby te można zmieniać przed każdym pociągnięciem pędzla, a do
wyboru są:
136 Rozdział 4  Teren

■ Add (dodawanie);
■ Subtract (odejmowanie);
■ Multiply (mnożenie);
■ Lighten (rozjaśnianie);
■ Darken (przyciemnianie);
■ Mix (mieszanie).
Wyboru odpowiedniego trybu dokonujemy w przyborniku, zanim przeciągniemy pędzlem
po teksturze (rysunek 4.32).

Rysunek 4.32. Pędzli do malowania tekstur można używać z różnymi trybami mieszania
Źródło: Blender.

Jak na razie (w chwili, gdy piszę ten tekst) Blender nie oferuje własnego systemu
warstw obrazowych, który można by wykorzystać przy malowaniu tekstur. Wszystkie
pociągnięcia pędzli są więc „wtapiane” w jedną i tę samą warstwę, a to oznacza, że
żadne z tych pociągnięć nie może być odseparowane od innych i niezależnie od nich
modyfikowane. Jest jednak dodatek o nazwie Texture Paint Layer Manager, który
Malowanie terenu teksturą 137

umożliwia korzystanie z warstw również w Blenderze. Można go łatwo zainstalować


za pośrednictwem okna Blender User Preferences (preferencje użytkownika Blendera).
Oto szczegóły postępowania:
1. Wybierz polecenie File/User Preferences (plik/preferencje użytkownika).
2. W oknie dialogowym Blender User Preferences, które się otworzy, kliknij zakładkę
Addons (dodatki).
3. Na liście Categories (kategorie) zaznacz pozycję Paint (malowanie).
4. Kliknij pole wyboru przy pozycji Paint: Texture Paint Layer Manager (malowanie:
menedżer warstw malowania tekstury) — tak jak na rysunku 4.33.

Rysunek 4.33. Instalowanie dodatku Texture Paint Layer Manager pozwalającego na korzystanie
z warstw przy malowaniu tekstur
Źródło: Blender.

Nie będę opisywał szczegółów posługiwania się tym dodatkiem, bo nie jest on integralną
częścią Blendera. Jeśli jesteś zainteresowany jego używaniem, instrukcję obsługi znajdziesz
pod adresem: http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/
Texture_paint_layers.
138 Rozdział 4  Teren

Malowanie w oknie 3D View


Alternatywna metoda malowania tekstury polega na malowaniu jej wprost na siatce
w oknie widokowym, tak jakby malarz malował na prawdziwej rzeźbie lub żywym
modelu. Stosując tę metodę, nakładasz piksele za pomocą myszy lub tabletu wprost na
siatkę. Pociągnięcia pędzlem są rzutowane z okna widokowego na siatkę modelu i wypa-
lane na powiązanej z nią teksturze. Duże znaczenie dla finalnego efektu ma kąt, pod jakim
widzisz siatkę w oknie widokowym; zawsze dbaj o to, aby miejsce malowane było dobrze
widoczne.
1. Żeby włączyć malowanie tekstury w oknie 3D View, na dolnym pasku narzędzio-
wym z listy Mode (tryb) wybierz opcję Texture Paint (malowanie tekstury) — ry-
sunek 4.34.

Rysunek 4.34. Włączanie trybu Texture Paint w oknie 3D View


Źródło: Blender.

2. Po włączeniu trybu Texture Paint w przyborniku po lewej stronie pojawią się zna-
ne już narzędzia malarskie. Ich działanie jest dokładnie takie samo jak w oknie
UV/Image Editor. Wybierz pędzel, ustaw jego kolor, rozmiar oraz intensywność i za-
cznij malować (rysunek 4.35)!
W omawianej metodzie istotne znaczenie ma kwestia rzutowania. Jak należy pomalo-
wać ściankę, która mieści się w zasięgu pędzla, ale jest odwrócona tyłem? Jak należy
pomalować ściankę, która jest w zasięgu pędzla i zwrócona przodem, ale zasłania ją
inna ścianka leżąca bliżej kamery? Na takie właśnie pytania musisz odpowiedzieć
Blenderowi. Jego domyślnym zachowaniem w obu przypadkach jest niemalowanie takich
Malowanie terenu teksturą 139

Rysunek 4.35. Malowanie bezpośrednio w widoku 3D


Źródło: Blender.

ścianek, ale możesz to zmienić przez zmodyfikowanie ustawień Project Paint (rzuto-
wanie malowania) w przyborniku (rysunek 4.36). Wyłączenie opcji Occlude (okluzja)
zezwala na malowanie ścianek zasłoniętych (przez inne ścianki leżące bliżej kamery).
Wyłączenie opcji Cull (wykluczenie) dopuszcza malowanie ścianek odwróconych tyłem
do kamery. A wyłączenie opcji Normal (normalna) powoduje, że wszystkie ścianki —
niezależnie od ustawienia względem kamery i tego, czy są zasłonięte, czy nie — są malo-
wane z jednakową intensywnością pędzla.

Rysunek 4.36. Za pomocą opcji z sekcji Project Paint możesz ustalić traktowanie ścianek
w zależności od ich ustawienia względem pędzla i kamery
Źródło: Blender.
140 Rozdział 4  Teren

Malowanie teksturami
Jak dotąd malowaliśmy, czy to w oknie UV/Image Editor, czy w widoku 3D, wyłącznie
określonymi kolorami wybieranymi z próbnika. W niektórych przypadkach może to
wystarczyć (np. tereny do filmów rysunkowych), lecz zazwyczaj chodzi o nakładanie
pędzlem przygotowanej wcześniej tekstury odzwierciedlającej z fotograficzną dokładno-
ścią elementy prawdziwego krajobrazu, takie jak trawa, skały itp. W Blenderze umożli-
wiają to narzędzia i opcje z sekcji Texture (tekstura) przybornika. Sekcja ta jest dostępna
zarówno w oknie edytora UV/Image Editor, jak i w oknie widoku 3D. Możesz w niej
wybrać w charakterze pędzla dowolną z załadowanych wcześniej tekstur.
1. Aby załadować do Blendera nową teksturę, otwórz panel Properties (właściwości)
i kliknij zakładkę Texture.
2. Kliknij przycisk New (nowy), aby wygenerować nową, właściwą teksturę — rysu-
nek 4.37.

Rysunek 4.37. Generowanie nowej tekstury


Źródło: Blender.
Malowanie terenu teksturą 141

3. Po utworzeniu nowej tekstury musisz ją jeszcze związać z przygotowanym wcze-


śniej i zapisanym na dysku obrazem. Domyślnie nowa tekstura jest typu Clouds
(chmury) lub jakiegoś innego spośród proceduralnych. Żeby to zmienić, rozwiń listę
Type (typ) i wybierz pozycję Image or Movie (obraz lub film). Wtedy będziesz mógł
wskazać, który obraz lub film ma być użyty w roli tekstury — rysunek 4.38.

Rysunek 4.38. Zmiana typu tekstury na obrazową lub filmową


Źródło: Blender.

4. Przewiń panel w dół i w sekcji Image (obraz) kliknij przycisk Open (otwórz) — ry-
sunek 4.39. Następnie wybierz plik z obrazem, który ma być użyty jako tekstura.
5. Teraz możesz przystąpić do malowania załadowaną teksturą. W trybie Texture Paint
wróć do przybornika i w sekcji Texture wybierz załadowaną wcześniej teksturę
(rysunek 4.40). Wskazana tekstura zostanie przypisana do aktywnego pędzla i odtąd
każde jego pociągnięcie będzie pozostawiało ślad w postaci pikseli z tej tekstury.
142 Rozdział 4  Teren

Rysunek 4.39. Wybór pliku z obrazem jako teksturą


Źródło: Blender.

Rysunek 4.40. Malowanie wybraną teksturą


Źródło: Blender.

Uwa ga
Blender miesza (lub łączy) teksturę z aktualnie wybranym kolorem pędzla. Przykładowo: jeśli wybrałeś
dla pędzla kolor czerwony, to nakładana tekstura zostanie zabarwiona na czerwono. To samo dotyczy
wszystkich innych kolorów. Jeśli chcesz, aby tekstura zachowała swoją pierwotną kolorystykę, wybierz
dla pędzla kolor biały (1.0, 1.0, 1.0).
Tworzenie dróg i ścieżek 143

6. Jeśli po skończeniu malowania wybraną teksturą będziesz chciał ją odłączyć od


pędzla, kliknij przycisk Unlink datablock (odłącz blok danych) znajdujący się pod
miniaturą pędzla w przyborniku (rysunek 4.41).

Rysunek 4.41. Odłączanie tekstury od pędzla


Źródło: Blender.

Tworzenie dróg i ścieżek


Jedno z najczęściej zadawanych pytań, jakie słyszę w związku z modelowaniem tere-
nów, dotyczy tworzenia dróg, ścieżek i innych elementów, które powinny być dopa-
sowane do topologii terenu. Droga np. nie spoczywa na podłożu w taki sposób jak
samochód, człowiek, budynek czy inny tego typu przedmiot o dokładnie określonym
położeniu środka ciężkości. Droga rozciąga się na dużych obszarach, wijąc się i kręcąc,
ale zawsze dopasowuje się ściśle do konturów terenu. Nie wystarczy, że ją położysz na
siatce terenu; ona musi się do tej siatki dopasować. Z tego wynika, że budowanie dróg
i ścieżek musi być nierozerwalnie związane z konkretnym terenem. Jedno z rozwiązań
polega na modelowaniu tych elementów wraz z terenem, tak jakby były jego częścią.
Nie jest to jednak takie proste. Jeśli droga ma być długa i kręta, wymodelowanie jej
z wielokątów mogłoby Cię przyprawić o ból głowy. Lepiej jest oddzielić modelowanie
drogi od modelowania terenu i połączyć te części dopiero w fazie końcowej. W tym
podrozdziale omówię narzędzia, jakie mogą się przydać przy realizacji takiego zadania
w Blenderze.
144 Rozdział 4  Teren

Modelowanie dróg
W poprzednich podrozdziałach przedstawiłem trzy metody tworzenia siatek terenów:
edycji proporcjonalnej, tekstury przemieszczeń i rzeźbienia. Wszystkie razem i każda
z osobna pozwalają zbudować złożony teren dla niemal każdego rodzaju gry. Teraz sku-
pimy się na takim modelowaniu dróg i ścieżek, aby zawsze pasowały do zbudowanego
już terenu. Oto kolejność czynności, jakie trzeba w tym celu wykonać:
1. Włącz widok z góry (Top), aby spojrzeć na teren z perspektywy ptasiej (topograficznej).
Spójrz na rysunek 4.42. (Zakładam, że masz już wymodelowany teren!)

Rysunek 4.42. Do planowania i modelowania dróg najlepszy jest widok z góry


Źródło: Blender.

2. Sposobów na utworzenie drogi jest wiele. Jeden polega na zastosowaniu krzywych.


Wystarczy narysować tylko krawędzie drogi biegnącej przez wymodelowany teren.
Na razie nie musisz się przejmować jej przebiegiem pionowym, czyli wznoszeniem się
i opadaniem na wszelkich nierównościach. Po prostu skoncentruj się na jej przebiegu
poziomym, który najlepiej widać z góry. Aby dodać do sceny linię krzywą, wybierz
polecenie Add/Curve/Bezier (dodaj/krzywą/Beziera) — tak jak na rysunku 4.43.
3. Widziana z góry pierwsza linia reprezentuje jedną krawędź drogi, lewą lub prawą
(na ogół nie ma to większego znaczenia). Wkrótce utworzysz drugą krawędź przez
powielenie tamtej. Jednak wcześniej uaktywnij narzędzie Extrude (wytłocz) — np.
przez wciśnięcie klawiszy Alt+X w trybie edycji — i dodaj kolejne segmenty krzy-
wej, układając je jeden za drugim i formując zgodnie z planowanym przebiegiem
drogi. Pamiętaj: przebieg krzywej w kierunku pionowym (wzdłuż osi Z) jest na ra-
zie nieistotny. Dopasowaniem do ukształtowania terenu zajmiemy się później.
Tworzenie dróg i ścieżek 145

Rysunek 4.43. Tworzenie krzywej Beziera


Źródło: Blender.

4. Po dodaniu ostatniego segmentu połącz końce krzywej, aby utworzyć krzywą za-
mkniętą. Coś takiego jest konieczne, jeśli końce nie mogą być przesuwane niezależnie
jeden od drugiego. A zatem zaznacz krzywą w trybie obiektowym, włącz tryb edycji
i z menu okna widokowego wybierz Curve/Toggle Cyclic (krzywa/przełącz cyklicz-
ność). Przydaje się również ustawienie (w trybie obiektowym) środka transformacji
krzywej w centralnym punkcie jej geometrii, co można szybko zrobić za pomocą po-
lecenia Object/Transform/Origin to Geometry (obiekt/przekształć/środek do geometrii)
— rysunek 4.44.
5. Skoro jedna krawędź drogi jest już gotowa, możesz wykonać drugą. W tym celu
utwórz kopię pierwszej krzywej i przeskaluj ją w górę lub w dół. Przykład kom-
pletnej drogi jest pokazany na rysunku 4.45. Jeśli masz już obie krawędzie, złącz je
w jeden obiekt — zaznacz je, a następnie wybierz z menu okna widokowego polecenie
Object/Join (obiekt/złącz).
6. Jako etap ostatni wykonaj osadzenie drogi w siatce terenu, aby uzyskać jej dopasowa-
nie do powierzchni siatki zarówno w poziomie, jak i w pionie. Możesz to zrobić za
pomocą narzędzia Knife Project (rzutowanie tnące), które zrzutuje obrys drogi na
powierzchnię terenu zgodnie z kierunkiem bieżącego widoku. Wzdłuż konturów
rzutu powstaną dodatkowe krawędzie siatki. Krótko mówiąc: narzędzie to auto-
matycznie przeniesie Twoją drogę na powierzchnię terenu. Aby wszystko poszło
jak należy, musisz włączyć widok z góry — kamera powinna być ustawiona centralnie
nad terenem i skierowana pionowo w dół. Następnie ustaw drogę w takim położeniu,
jakie powinna zajmować po zrzutowaniu pionowo w dół (zob. rysunek 4.45). Gdy już
146 Rozdział 4  Teren

Rysunek 4.44. Ustawianie środka transformacji w geometrycznym środku krzywej


Źródło: Blender.

Rysunek 4.45. Kompletna droga utworzona z dwóch złączonych ze sobą krzywych. Żeby poprawić
ich widoczność na zrzucie ekranu, dodałem efekt fazowania (w panelu Properties) — dla procesu
tworzenia drogi nie ma to znaczenia
Źródło: Blender.
Tworzenie dróg i ścieżek 147

to wszystko przygotujesz, sięgnij po narzędzie Knife Project. Aby uzyskać do niego


dostęp, najpierw usuń istniejące zaznaczenie, a potem zaznacz kolejno obiekt rzu-
towany (drogę) i obiekt rozcinany (teren) — w takiej, a nie innej kolejności. Na
koniec włącz tryb edycji (wciśnij klawisz Tab) i w przyborniku po lewej stronie okna
widokowego kliknij przycisk Knife Project (rysunek 4.46).

Rysunek 4.46. Narzędzie Knife Project zrzutowało obrys drogi na siatkę terenu
Źródło: Blender.

Uaktywnienie narzędzia Knife Project spowoduje nacięcie siatki terenu wzdłuż kontu-
rów drogi, a zatem nacięcia te wyznaczą przebieg drogi na powierzchni terenu! Jest to
naprawdę łatwy sposób na dodawanie dróg do siatki terenu (rysunek 4.47). Oczywiście
trochę pracy zostało jeszcze do wykonania. Trzeba by np. tu i ówdzie wyrównać na-
wierzchnię drogi. Ale dzięki zastosowaniu narzędzia Knife Project zasadnicze zadanie
zostało wykonane szybko i skutecznie. Gratuluję! Teraz już możesz sam tworzyć rozmaite
tereny razem z drogami i ścieżkami.
148 Rozdział 4  Teren

Rysunek 4.47. Ręcznie rzeźbiony teren z systemem drogowym wykonanym


przy użyciu narzędzia Knife Project
Źródło: Blender.

Podsumowanie
Tematem tego rozdziału był teren jako element środowiska gry. Najpierw przedstawiłem
system generowania terenów funkcjonujący w Unity. Jest to system, w którym rzeźba
terenu stanowi odwzorowanie specjalnej tekstury zwanej mapą wysokości. Za pośred-
nictwem tej tekstury można wpływać jedynie na pionowe położenia poszczególnych
punktów terenu i właśnie to ograniczenie skłoniło nas do sprawdzenia, co w kwestii two-
rzenia terenów ma do zaoferowania Blender. Wygenerowany za jego pomocą teren
można by przenieść jako siatkę statyczną do Unity i tam osadzić ją w miejscu terenu
natywnego. Blender oferuje trzy metody modelowania terenu, malowanie teksturami,
a także wygodne narzędzia do nanoszenia dróg i ścieżek. W następnym rozdziale prze-
analizujemy animacyjny tok pracy w Blenderze ze szczególnym uwzględnieniem za-
gadnień związanych z eksportowaniem animacji do Unity.
R OZ DZ I AŁ 5

T OK PRACY ANIMACYJNEJ

Animację ograniczają tylko dwie rzeczy. Możliwości wyobraźni i zdolność


do odtworzenia tego, co sobie wyobrażamy.
— Eric Larson

Po przeczytaniu tego rozdziału powinieneś:


■ umieć wykonać animację w Blenderze i przenieść ją do Unity;
■ umieć pracować z klatkami kluczowymi;
■ wiedzieć, na czym polega miksowanie kształtów i co to są klucze kształtu;
■ umieć wykonywać rigowanie w Blenderze z myślą o przeniesieniu szkieletu do Unity
i wykorzystaniu w systemie Mecanim;
■ umieć przenosić animowane modele z Blendera do Unity.
Animacja w grach komputerowych polega zasadniczo na opisywaniu zmian zachodzą-
cych w miarę upływu czasu, przy czym mogą to być zmiany położenia obiektu lub jego
budowy wewnętrznej. W sensie ogólnym animacja oznacza swoistą relację między cza-
sem a wartością, albo inaczej: między czasem, w którym dochodzi do zmiany, a zmianą,
która się pojawia, gdy nadchodzi właściwy dla niej czas. Dlatego ilekroć będziesz chciał
przesunąć w grze jakiś obiekt lub zmienić jego wygląd, będziesz musiał zastosować
animację przez określenie relacji między czasem a modyfikowaną wartością. Realizacja
takiego odwzorowania jest zazwyczaj oparta na koncepcji klatek kluczowych, a więc
zanim przejdziemy do omawiania zagadnień związanych z tworzeniem animacji w Blen-
derze i Unity, przyjrzymy się dokładniej, na czym ta koncepcja polega.

149
150 Rozdział 5  Tok pracy animacyjnej

Klatka kluczowa jako jednostka animacji


Jak już wspomniałem, animacja oznacza zmiany zachodzące w czasie. Definicja ta
opiera się na pojęciach czasu i zmiany. Zarówno Blender, jak i Unity ujmują te pojęcia
w jedną strukturę, zwaną klatką kluczową.
Kompletna sekwencja animacyjna może zawierać jedną lub więcej klatek kluczowych.
Klatka kluczowa (keyframe) określa właściwości obiektu (np. postaci) w konkretnym
punkcie na osi czasu. Właściwościami tymi mogą być: położenie, kąt obrotu, skala i inne
tego typu parametry (zwane tutaj kanałami). Żeby wykonać sensowną animację, po-
trzeba co najmniej dwóch klatek kluczowych, które określą stan obiektu na końcach
pewnego przedziału czasowego. W Blenderze, tak jak i w Unity, płynność odtwarzania
animacji uzyskuje się przez generowanie klatek pośrednich (tweens). Są to klatki animacji
generowane automatycznie i wstawiane między klatki kluczowe w celu uzyskania
płynnych zmian wartości kluczowanych parametrów. Proces obliczania wartości pośred-
nich nosi nazwę interpolacji i jest sterowany przez matematyczną strukturę o nazwie
krzywa funkcyjna (F-curve). Oś pozioma oznacza czas, a pionowa — zmieniający się
parametr (rysunek 5.1).

Rysunek 5.1. Po lewej stronie u dołu widoczny jest edytor krzywych funkcyjnych będący częścią
edytora wykresów
Źródło: Blender.

Szybkość, z jaką animacje są odtwarzane, zazwyczaj określa się przez podanie liczby
klatek wyświetlanych w ciągu jednej sekundy (fps). Lecz jak się wkrótce przekonasz,
Unity oferuje możliwość skalowania czasu trwania animacji w celu jej przyspieszenia
lub spowolnienia w zależności od potrzeb. Można to robić nawet w czasie rzeczywistym.
Jednak warto ustalić właściwą szybkość animacji już w Blenderze, i to we wczesnej
Przygotowanie Blendera do tworzenia animacji 151

fazie jej tworzenia, aby w trakcie opracowywania mieć możliwość sprawdzania, jak
będzie wyglądała w grze. W tym celu należy otworzyć zakładkę Render (renderowanie)
panelu Properties (właściwości) i w polu Frame Rate (szybkość odtwarzania) wpisać
odpowiednią liczbę — tak jak na rysunku 5.2. Najczęściej stosowane są wartości 25 i 30 fps.

Rysunek 5.2. Określanie szybkości odtwarzania animacji w Blenderze


Źródło: Blender.

Przygotowanie Blendera do tworzenia animacji


Ogólnie tok pracy nad animacją w Blenderze i Unity wygląda następująco:
1. Wykonujesz animację w Blenderze.
2. Eksportujesz ją z Blendera.
3. Importujesz do Unity.
4. Testujesz i udoskonalasz, a w razie potrzeby wracasz do Blendera i tam poprawiasz,
a potem ponownie importujesz.
Najpierw trzeba więc zaplanować i wykonać animację w Blenderze. Jednak zanim się
za to zabierzesz, powinieneś trochę pomajstrować przy ustawieniach programu, aby go
do takiej pracy przygotować. W kolejnych punktach podpowiem Ci, jak do tego podejść
od strony praktycznej.
152 Rozdział 5  Tok pracy animacyjnej

Wykorzystaj specjalny, animacyjny układ interfejsu Blendera


Animacja nie jest jakąś tam dodatkową procedurą wykonywaną po fazie modelowania
czy mapowania UV. Jest to całkowicie odrębny proces, który wymaga starannego
przygotowania, sporego nakładu pracy i zazwyczaj niemałych ilości czasu. Dlatego
warto tak skonfigurować interfejs Blendera, aby maksymalnie pomagał w realizacji tego
zadania. W Blenderze możesz tworzyć własne układy interfejsu, ale do prac animacyjnych
lepiej wykorzystać gotowy układ o nazwie Animation (animacja). Aby go uaktywnić,
po prostu wybierz jego nazwę z listy rozwijanej Screen layout (układ ekranu) widocznej
w górnej części interfejsu (rysunek 5.3).

Rysunek 5.3. Włączanie animacyjnego układu interfejsu


Źródło: Blender.

Uważaj na automatyczne kluczowanie


Funkcja Auto-Key (automatyczne kluczowanie) jest domyślnie wyłączona, ale jeśli ją
włączysz — przez kliknięcie przycisku Auto-Key na pasku narzędziowym okna Timeline
(oś czasu), tak jak na rysunku 5.4 — Blender będzie rejestrował wszystkie transformacje
i modyfikacje siatek, jakie wykonasz. Gdy tylko wykryje jakąś zmianę, automatycznie
utworzy stosowne klatki kluczowe i umieści je na osi czasu. W miarę jak będziesz edytował
poszczególne obiekty, Blender będzie na tej podstawie konstruował animację. Wyko-
na za Ciebie całą robotę związaną z tworzeniem klatek kluczowych i będzie się przy
tym starał odgadnąć, które właściwości chciałbyś animować i jak powinny być interpo-
lowane klatki kluczowe.
Automatyczne kluczowanie ma przyczyniać się do oszczędzenia Twojego czasu, jed-
nakże generuje większą liczbę klatek kluczowych niż jest to konieczne, co zazwyczaj
prowadzi do niepotrzebnego skomplikowania danych animacyjnych. Cierpi na tym
wydajność animacji i za bardzo rozrasta się plik, w którym jest zapisywana. Ma to
Przygotowanie Blendera do tworzenia animacji 153

Rysunek 5.4. Funkcję Auto-Key wspomagającą tworzenie animacji można włączać i wyłączać
Źródło: Blender.

również negatywny wpływ na szybkość działania całej gry, gdy taka animacja zostanie
zaimportowana do Unity, ponieważ silnik musi wtedy przetworzyć więcej klatek.
Dlatego proponuję, abyś w większości przypadków pozostawiał tę funkcję wyłączoną.
Jeśli sam wykonasz klatki kluczowe, animacja będzie zawierała tylko te dane, które są
rzeczywiście niezbędne. Oczywiście będą sytuacje, chociażby przy pracy z wieloma
obiektami lub rigowanymi postaciami, kiedy automatyczne kluczowanie okaże się
bardzo przydatne. Wtedy warto włączyć opcję Only Insert Available (wstawiaj tylko
dostępne) znajdującą się na zakładce Editing (edytowanie) okna dialogowego Blender
User Preferences (rysunek 5.5). Opcja ta spowoduje, że Blender będzie tworzył klatki
kluczowe tylko w tych kanałach, w których Ty sam utworzysz pierwsze takie klatki.
W ten sposób uchronisz się przed zalewem klatek kluczowych w kanałach, które w danej
animacji nie są do niczego potrzebne.

Wstawiaj pojedyncze klatki kluczowe


Często ręczne wstawianie klatek kluczowych okazuje się najefektywniejsze. Masz wte-
dy pełną kontrolę nad tym, które klatki zostaną utworzone w danej sekwencji anima-
cyjnej, a przez to możesz łatwiej ograniczyć ich liczbę do niezbędnego minimum. Aby
ręcznie wstawić klatkę kluczową dla parametru, który może być animowany, kliknij
prawym przyciskiem myszy pole z jego wartością i z podręcznego menu wybierz pole-
cenie Insert Single Keyframe (wstaw jedną klatkę kluczową) — rysunek 5.6.
154 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.5. Nakładanie ograniczeń na funkcję Auto-Key


Źródło: Blender.

Rysunek 5.6. Ręczne wstawianie klatek kluczowych do animacji


Źródło: Blender.
Przygotowanie Blendera do tworzenia animacji 155

Długość animacji
Każda animacja ma określoną długość wyrażoną liczbą klatek. Blender domyślnie
ustawia tę liczbę na 250, ale w każdej chwili możesz to łatwo zmienić. Jednak w przy-
padku animacji, która ma być eksportowana do Unity, nie jest obojętne, jak to zrobisz.
Jeśli wybierzesz niewłaściwą metodę, może się okazać, że po zaimportowaniu do
Unity animacja ma inną liczbę klatek niż ta, którą ustawiłeś. To z kolei może spowo-
dować przedwczesne lub zbyt późne zakończenie animacji.
Jeden ze sposobów ustalania długości animacji polega na określeniu w oknie Timeline
numeru ostatniej klatki — tak jak na rysunku 5.7. Jednakże po uaktywnieniu opcji Use
an alternative start/end frame (użyj alternatywnych klatek jako początkowej i końcowej)
animacja widoczna w oknie Timeline może mieć inną długość niż animacja sceniczna,
którą wyeksportujesz do Unity. Okazuje się bowiem, że w oknie Timeline nie musi
być wcale widoczna cała animacja, a jedynie jej fragment. Często jest widoczna w całości,
ale nie zawsze. Ustawiony w tym oknie zakres klatek nie musi się pokrywać z całkowitą
długością animacji. Dlatego żeby tę długość ustawić prawidłowo, należy się posłużyć
metodą, którą właśnie teraz przedstawię.

Rysunek 5.7. Długość animacji ustawiona w oknie Timeline może się różnić od tej, jaką będzie miała
animacja wyeksportowana do Unity
Źródło: Blender.

Druga (zalecana) metoda ustalania długości animacji nie ma już takich wad, jakie
miała poprzednia. Tutaj już nie grozi rozbieżność między ustawioną a rzeczywistą
liczbą klatek. Czynności, jakie trzeba wykonać, są następujące:
1. W panelu Properties kliknij zakładkę Render.
2. W rolecie Dimensions (wymiary) kliknij pole End Frame (klatka końcowa) i wpisz
numer klatki kończącej animację (rysunek 5.8).
156 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.8. Ustalanie długości animacji przez określenie liczby wszystkich klatek
Źródło: Blender.

Eksportowanie animacji do formatu FBX


W rozdziale 2. opisałem szczegółowo, jak należy eksportować siatki z Blendera do
formatu FBX lub Collada, aby potem można je było łatwo zaimportować do Unity.
Jak zapewne pamiętasz, żeby wyeksportować siatkę do FBX, należy użyć narzędzia
eksportującego dostępnego po wybraniu polecenia File/Export/Autodesk FBX (plik/
eksportuj/Autodesk FBX). W tamtym rozdziale rozważaliśmy jedynie eksport siatek
statycznych. Na szczęście w przypadku siatek animowanych obowiązują podobne za-
sady postępowania. Trzeba jedynie pilnować, aby wszystkie opcje związane z anima-
cjami były włączone. Szczególnie ważne są: Include Animation (dołącz animację), All
Actions (wszystkie akcje), Include Default Take (dołącz ujęcie domyślne) i Optimize
Keyframes (optymalizuj klatki kluczowe) — rysunek 5.9.

Uwa ga
Żeby przenieść siatkę i animację z Blendera do Unity, nie musisz używać formatu FBX. Alternatywą dla
niego jest format Collada (DAE), a właściwe dla niego narzędzie eksportujące jest dostępne po wybraniu
polecenia File/Export/Collada (plik/eksportuj/Collada).

Praca z wieloma animacjami


Często będziesz chciał przypisać jednemu obiektowi kilka animacji — np. gdy będziesz
animował postać wykonującą rozmaite ruchy, powiedzmy: chód, bieg i skoki. Są dwie
metody wykonania tego zadania w Blenderze, które dobrze współgrają z Unity. Prze-
analizujmy je na przykładzie eksportu modelu postaci z kilkoma różnymi animacjami.
Przygotowanie Blendera do tworzenia animacji 157

Rysunek 5.9. Ustawienia niezbędne do prawidłowego wyeksportowania siatki w formacie FBX


Źródło: Blender.

Eksportowanie oddzielnie animacji i postaci


Pierwsza metoda polega na wyeksportowaniu samej postaci jako pojedynczej, zrigo-
wanej, ale nieanimowanej siatki FBX, a następnie wyeksportowaniu poszczególnych
animacji do odrębnych plików FBX. Powstaje więc jeden plik z siatką i kilka dodatko-
wych z danymi animacyjnymi. Każdy z tych dodatkowych plików zawiera kompletną
animację chodu, biegu, skoków itp. W tej metodzie siatki i animacje są porozkładane
w odrębnych plikach. Jej podstawową wadą jest to, że wraz ze wzrostem liczby obiektów
i animacji rośnie również liczba plików.

Eksportowanie animacji i siatek do jednego pliku


W metodzie drugiej zarówno siatka, jak i jej animacje (ruchy) są eksportowane do jednego
wspólnego pliku. Zamiast do odrębnych plików animacje trafiają na jedną oś czasu, gdzie są
ustawiane jedna po drugiej. Przedział czasowy jest powiększany wystarczająco, by wszystkie
animacje się w nim zmieściły. Każda z nich zajmuje tylko fragment osi czasu.
Eksportowanie siatki wraz z animacjami jest wygodne, ponieważ w Unity wystarczy
wtedy zaimportować tylko jeden plik. Później zobaczysz, że tak zaimportowane ani-
macje można nadal łączyć z siatkami z innych plików. Niestety, metoda ta również nie
jest wolna od wad: przy dużej liczbie siatek i animacji plik przybiera gigantyczne roz-
miary i staje się nieporęczny.
158 Rozdział 5  Tok pracy animacyjnej

Uwa ga
Podczas pracy z animacjami będziesz musiał sam decydować, która metoda eksportowania jest najlepsza
dla Twojej gry.

Prosta animacja kluczowana — od Blendera do Unity


W tym podrozdziale prześledzimy proces tworzenia prostej animacji z klatkami kluczo-
wymi i przenoszenia jej z Blendera do Unity. Do wykonania opisywanych tu czynności
możesz użyć własnoręcznie wymodelowanej siatki albo skorzystać z gotowego modelu
zapisanego w pliku Rozdział05/KeyFrameStart.Blend dostępnym na stronie z mate-
riałami uzupełniającymi (ftp://ftp.helion.pl/przyklady/unible.zip).
Aby przygotować Blendera do pracy, wykonaj następujące czynności:
1. Włącz interfejs w układzie Animation. Następnie otwórz plik z obiektem. Może to
być dowolny obiekt — zwykły sześcian lub cokolwiek innego. Ponownie zachęcam
do skorzystania z pliku Rozdział05/KeyFrameStart.Blend.
3. Ustaw długość animacji równą 100 klatek.
4. Zgodnie z tym, co napisałem w punkcie „Długość animacji”, ustaw parametr End
Frame w oknie Timeline i w panelu Properties na 99.
5. Parametr Start Frame (klatka początkowa) ustaw w obu miejscach na 0. Domyślnie
Blender ustawia tę wartość na 1, ale Unity przyjmuje zawsze, że klatka początkowa
importowanej animacji ma numer 0, więc lepiej od razu zadbaj, żeby w tej kwestii
nie było rozbieżności między aplikacjami (rysunek 5.10).

Rysunek 5.10. Ustalanie numeracji klatek animacyjnych


Źródło: Blender.
Prosta animacja kluczowana — od Blendera do Unity 159

W naszej prostej animacji, począwszy od klatki 0. aż do 99., obiekt będzie się przesuwał
do przodu, do tyłu i znów do przodu. Aby utworzyć taką animację, wykonaj następujące
czynności:
1. Ustaw suwak czasu w klatce 0. (Jeśli używasz systemu sterowania z programu Maya,
kliknij tę klatkę prawym przyciskiem myszy).
2. Utwórz pierwszą klatkę kluczową z siatką w położeniu początkowym. W tym celu
zaznacz siatkę, a następnie na zakładce Object (obiekt) panelu Properties kliknij
prawym przyciskiem myszy pole Y (lub X w zależności od kierunku, w którym chcesz
przesuwać obiekt) i z podręcznego menu wybierz Insert Single Keyframe. W ten
sposób zapiszesz położenie, jakie obiekt będzie zajmował na początku animacji.
W oknach Graph Editor (edytor wykresów) i Dopesheet (raport operatorski) rozpocz-
nie się tworzenie ścieżki animacji, a w oknie Timeline pojawi się znacznik klatki
kluczowej (rysunek 5.11).

Rysunek 5.11. Ustanawianie pierwszej klatki kluczowej


Źródło: Blender.

3. Wstaw następne klatki kluczowe na osi czasu. W przykładowej animacji przesunąłem


siatkę do położenia –1.96168 na osi Y i wstawiłem klucz w klatce 20. Następnie
cofnąłem ją do położenia Y = 1.24381 i wstawiłem klucz w klatce 55. W klatce 80.
wstawiłem klucz dla położenia Y = –1.29317, a w klatce 99. ustawiłem siatkę z po-
wrotem w położeniu początkowym. Nie zapomnij po każdym przemieszczeniu
obiektu ustanowić klatki kluczowej lub po prostu włącz funkcję Auto-Key — rysu-
nek 5.12. (Jeśli zdecydujesz się na drugie rozwiązanie, zapoznaj się z tym, co napi-
sałem w punkcie „Uważaj na automatyczne kluczowanie”).
160 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.12. Tworzenie sekwencji animacyjnej


Źródło: Blender.

4. Gdy animacja będzie już gotowa, zaznacz siatkę i za pomocą polecenia File/Export/
Autodesk FBX wyeksportuj ją, stosując ustawienia pokazane na rysunku 5.9. Po-
wstanie jeden plik FBX zawierający zarówno siatkę, jak i dane animacyjne (jako re-
zultat zastosowania drugiej metody spośród opisanych w punkcie „Praca z wielo-
ma animacjami”). Na koniec zaimportuj ten plik do Unity (rysunek 5.13).

Rysunek 5.13. Importowanie pliku FBX do Unity


Źródło: Unity Technologies.
Prosta animacja kluczowana — od Blendera do Unity 161

W Unity, gdy zaznaczysz zaimportowaną siatkę w panelu Project (projekt), jej dane
wraz z konfiguracją zostaną wyświetlone na trzech zakładkach panelu Inspector (in-
spektor):
■ Model (model) — na tej zakładce są wyświetlane wszystkie ustawienia związane ze
strukturą siatki, z jej wierzchołkami i współrzędnymi UV.
■ Rig (szkielet) — tutaj jest opisana struktura szkieletu, za pomocą którego realizo-
wana jest animacja siatki.
■ Animations (animacje) — ta zakładka zawiera wszystkie dane animacyjne związane
z zaimportowaną siatką.
Zauważ, że dane dotyczące siatki, szkieletu i animacji są w Unity wzajemnie odseparo-
wane. Podział ten ma niebagatelne znaczenie, ponieważ z jego istnienia wynika, że ani-
macje osadzone w jednym pliku niekoniecznie muszą być stosowane z zapisaną w nim
siatką. Równie dobrze można je zastosować z siatkami pochodzącymi z innych plików.
Mówimy wtedy o retargetowaniu animacji (rysunek 5.14).

Rysunek 5.14. Zaimportowane dane są dzielone na trzy grupy: siatkowe, szkieletowe i animacyjne
Źródło: Unity Technologies.

Teraz przejdziemy do skonfigurowania zaimportowanej siatki, aby nadawała się do


użycia w grze. Będzie to polegało głównie na odpowiednim skonfigurowaniu armatury
odpowiedzialnej za deformowanie siatki i utworzeniu klipu animacyjnego na podstawie
danych zapisanych w zaimportowanej osi czasu.
162 Rozdział 5  Tok pracy animacyjnej

1. Otwórz zakładkę Rig panelu Inspector i upewnij się, że z listy rozwijanej Animation
Type (typ animacji) wybrana jest opcja Generic (ogólny). Oznacza to, że siatka nie
jest humanoidem i jest zgodna z systemem Mecanim.

Uwa ga
System Mecanim został wprowadzony do Unity 4. Jest to zbiór funkcji animacyjnych, które ułatwiają
importowanie, konfigurowanie i obsługę animowanych modeli siatkowych utworzonych za pomocą
programów do modelowania takich jak Blender. Będziemy ich używać dość często, nie tylko w tym roz-
dziale, ale również w pozostałych. Nieco szerszy opis systemu Mecanim zamieściłem w książce Unity 4
Fundamentals (ISBN: 978-0415823838).

Uwa ga
Postać z rysunku 5.13 wygląda wprawdzie jak humanoid, ale dla Unity nim nie jest. Unity uznaje siatkę
za humanoidalną, jeśli ta ma określony rodzaj szkieletu z odpowiednią liczbą kości i odpowiednio ze sobą
powiązanych. Model z rysunku 5.13 nie ma wcale szkieletu i dlatego został zakwalifikowany jako typ ogólny.

2. Otwórz zakładkę Animations. Zauważ, że prezentuje ona klip o nawie Default Take
(ujęcie domyślne), który zawiera całą animację z pliku, począwszy od klatki 0. aż
do 99. Później pokażę, jak można tę animację podzielić na mniejsze części. Na razie
jednak pozostaniemy przy jednym klipie. Zmień tylko jego nazwę na BasicAnimation
(animacja podstawowa) i jeśli to konieczne, ustaw za pomocą pól Start (początek)
oraz End (koniec) właściwe numery klatek dla początku i końca animacji. Cała oś
czasu reprezentuje pełną animację, jaka została wyeksportowana z Blendera.
3. Włącz opcję Loop Time (zapętlenie czasu), aby zmusić Unity do automatycznego
powtarzania animacji.
4. Jeśli chcesz zobaczyć, jak wygląda zaimportowana animacja, kliknij przycisk Play
(odtwarzanie) w oknie podglądu (rysunek 5.15).
5. Po wprowadzeniu modyfikacji w ustawieniach klipu kliknij przycisk Apply (zastosuj),
aby wszystko zatwierdzić. Dane animacyjne zostaną zaktualizowane.
Jeśli siatkę dodasz do sceny jako obiekt gry (GameObject), a potem klikniesz przycisk
Play na górnym pasku aplikacji, żeby uruchomić grę, okaże się, że siatka jest statyczna,
czyli że żadna animacja nie została jej automatycznie przypisana. Żeby animacja siatki
była uruchamiana automatycznie i przebiegała zgodnie z ustawieniami klipu anima-
cyjnego, musisz to zaaranżować za pomocą elementu o nazwie Animator Controller
(sterownik animatora). Niemal wszystkie typy siatek importowane do Unity są umiesz-
czane w scenie z dołączonym składnikiem Animator, którego jednym z elementów jest
Controller, i to do niego uzyskujesz dostęp za pośrednictwem elementu Animator
Controller. To właśnie on decyduje, kiedy i jak animacja siatki ma być uruchomiona.
Domyślnie element ten nie jest przypisany albo ma ustawioną wartość None (nic) i dlatego
siatka nie jest animowana w sposób automatyczny (rysunek 5.16).
Prosta animacja kluczowana — od Blendera do Unity 163

Rysunek 5.15. Konfigurowanie klipu animacyjnego


Źródło: Unity Technologies.

Rysunek 5.16. Siatka umieszczana w scenie otrzymuje składnik o nazwie Animator. Pamiętaj,
że współczynnik skali ma być ustawiony na 1, aby siatka miała właściwe wymiary (zob. punkt
„Współczynnik skali” w rozdziale 2.)
Źródło: Unity Technologies.
164 Rozdział 5  Tok pracy animacyjnej

Aby utworzyć element gry typu sterownik animatora, kliknij prawym przyciskiem
myszy w panelu Project i z podręcznego menu wybierz Create/Animator Controller
(utwórz/sterownik animatora). Parametry sterownika można ustawiać za pośrednictwem
okna Animator (animator) — nie mylić z oknem Animation (animacja). Aby je otworzyć,
wybierz z głównego menu polecenie Window/Animator (okno/animator) — rysunek 5.17.

Rysunek 5.17. Za pomocą sterownika animatora można sterować odtwarzaniem animacji


Źródło: Unity Technologies.

Kontroler animatora to specjalny rodzaj elementu gry, który definiuje skończoną ma-
szynę stanów (finite state machine — FSM) dla danej siatki. Jest w zasadzie wizualną
formą pisania skryptów. Za pomocą kontrolera możesz wprowadzać siatkę w poszcze-
gólne stany animacyjne i określać powiązania między tymi stanami, wskazując, kiedy
dana animacja ma się uaktywnić i kiedy ma się wyłączyć. Możesz nawet mieszać kilka
animacji, np. strzelanie możesz połączyć z marszem. Co więcej, każda z łączonych
animacji może mieć przypisaną określoną wagę.
W naszym przykładzie przypiszemy siatce tylko jeden utworzony wcześniej klip o na-
zwie BasicAnimation. Żeby to zadanie wykonać, po prostu przeciągnij ten klip anima-
cyjny z panelu Project do okna Animator. Spowoduje to automatyczne dodanie klipu
do grafu animatora, gdzie będzie widoczny w postaci pomarańczowego węzła. (Kolor
pomarańczowy oznacza, że jest to węzeł domyślny, czyli taki, który określa początkową
animację siatki). A zatem gdy tylko akcja się rozpocznie, siatka wykona animację zapisaną
w klipie BasicAnimation.
Prosta animacja kluczowana — od Blendera do Unity 165

Jeśli w oknie Animator zaznaczysz węzeł BasicAnimation, to w panelu Inspector będziesz


mógł ustawić szybkość (Speed) odtwarzania klipu. Przy szybkości równej 1 animacja
jest odtwarzana ze swoją nominalną prędkością, czyli z taką, jaka została ustalona
w Blenderze. Gdy zwiększysz tę wartość do 2, szybkość odtwarzania wzrośnie dwukrot-
nie, a jeśli ją zmniejszysz do 0.5, szybkość animacji zmaleje o połowę itd. W naszym
przykładzie pozostaw wartość domyślną, czyli 1 (rysunek 5.18).

Rysunek 5.18. Budowanie grafu animatora


Źródło: Unity Technologies.

Po utworzeniu grafu animatora możesz go przypisać siatce poprzez jej składnik o nazwie
Animator. Oto czynności, jakie należy w tym celu wykonać:
1. Zaznacz siatkę w scenie.
2. Przeciągnij sterownik kontrolera na pole Controller (sterownik) składnika Animator.
3. Kliknij przycisk Play na pasku narzędziowym, aby się przekonać, czy siatka jest
rzeczywiście animowana. To działa, ponieważ wraz z rozpoczęciem akcji siatka
zawsze będzie wchodziła w stan animacyjny określony przez domyślny (pomarań-
czowy) węzeł grafu animatora (rysunek 5.19).

Rysunek 5.19. Obiekt w trakcie odtwarzania animacji


Źródło: Unity Technologies.
166 Rozdział 5  Tok pracy animacyjnej

Animowanie ruchu wzdłuż ścieżki i wypalanie animacji


W grach często zachodzi potrzeba przesuwania obiektów, takich jak ludzie, samochody
czy statki kosmiczne, wzdłuż wyznaczonych wcześniej ścieżek (rysunek 5.20). Jedno
z najbardziej intuicyjnych rozwiązań polega na narysowaniu ścieżki za pomocą blende-
rowych narzędzi do tworzenia krzywych i zmuszeniu obiektu, by w czasie trwania całej
animacji przemierzył wyznaczoną w ten sposób trasę. Podejście takie implikuje jednak
problem wypalania albo, jak chcą niektórzy, konwersji animacji.

Rysunek 5.20. Animacja wzdłuż ścieżki


Źródło: Blender.

Przyjrzyjmy się tej sprawie, tworząc animowany obiekt, który będzie się poruszał po
wyznaczonej ścieżce. Możesz w tym celu stworzyć własną scenę i obiekt, ale możesz też
wykorzystać jako punkt wyjścia plik Follow_Path.blend dostępny w materiałach po-
mocniczych na stronie internetowej powiązanej z książką. Oto szczegóły:
1. W Blenderze możesz rysować ścieżki za pomocą narzędzi służących do tworzenia
krzywych. Po prostu wybierz polecenie Add/Curve/Path (dodaj/krzywą/ścieżkę) —
rysunek 5.21.
2. Aby ukształtować ścieżkę, włącz tryb edycji (wciśnij klawisz Tab). Ja narysowałem
w tym celu zwykły zygzak (rysunek 5.22). Pamiętaj, że w przypadku ścieżek punkty
kontrolne nie leżą bezpośrednio na krzywej, a jedynie wyznaczają kierunki jej wygięć.
Rzeczywisty przebieg ścieżki jest wynikiem interpolacji położeń punktów kontrolnych.
3. Żeby poprawić widoczność ścieżki, otwórz zakładkę Object data (dane obiektu) pa-
nelu Properties i w rolecie Geometry (geometria) zwiększ wartość parametru Depth
(głębokość) należącego do grupy Bevel (fazowanie) — rysunek 5.23.
Animowanie ruchu wzdłuż ścieżki i wypalanie animacji 167

Rysunek 5.21. Tworzenie krzywej stanowiącej ścieżkę animacji


Źródło: Blender.

Rysunek 5.22. Punkty kontrolne wyznaczają krzywiznę ścieżki


Źródło: Blender.

4. Aby zmusić obiekt do poruszania się wzdłuż ścieżki, przypisz mu więzy typu Follow
Path (podążaj wzdłuż ścieżki). W tym celu otwórz zakładkę Constraints (więzy) pa-
nelu Properties i wybierz odpowiednią pozycję z listy możliwych więzów (rysunek 5.24).
168 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.23. Większa głębokość fazowania może poprawić widoczność ścieżki


Źródło: Blender.

Rysunek 5.24. Więzy Follow Path zmuszają obiekt do poruszania się wyłącznie wzdłuż
wskazanej ścieżki
Źródło: Blender.

Uwa ga
Więcej informacji na temat więzów Follow Path znajdziesz w dokumentacji Blendera na stronie:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Constraints/Relationship/Follow_Path.

5. W rolecie z ustawieniami więzów Follow Path kliknij pole Target (cel) i wskaż nary-
sowaną wcześniej krzywą.
Animowanie ruchu wzdłuż ścieżki i wypalanie animacji 169

6. W polu Forward (do przodu) wskaż wektor wyznaczający przód obiektu (twarz po-
staci) jako ten, który ma być ciągle skierowany wzdłuż krzywej. Dzięki temu pod-
czas swej wędrówki po ścieżce obiekt będzie zawsze zwrócony przodem w kierunku
ruchu1 (rysunek 5.25).

Rysunek 5.25. Ustawianie obiektu zgodnie z orientacją ścieżki


Źródło: Blender.

7. Kliknij przycisk Animate Path (animuj ścieżkę). Spowoduje to wygenerowanie da-


nych animacyjnych niezbędnych do przemieszczenia obiektu wzdłuż ścieżki. Aby
przetestować ten ruch, przeciągnij znacznik czasu w oknie Timeline. W oknie wi-
dokowym powinieneś widzieć, jak obiekt przesuwa się wzdłuż krzywej, rozpoczy-
nając swój ruch w klatce pierwszej i kończąc w ostatniej. Zwróć uwagę na ustawie-
nie obiektu (przodem w kierunku ruchu) podczas tej wędrówki (rysunek 5.26).
Jest jednak problem z przeniesieniem takiej animacji do Unity. Zapewne zauważyłeś
(chociażby na rysunku 5.26), że siatka owszem, porusza się, ale w oknach animacyjnych
— takich jak Graph Editor czy Dopesheet — nie widać żadnych klatek kluczowych.
Wynika to z faktu, że więzy (w tym i Follow Path) nie generują takich klatek. Sterują
ruchem obiektów, ale nie używają do tego klatek kluczowych. Unity jednak akceptuje
wyłącznie animacje określone przez klatki kluczowe, kluczowanie kształtu i rigowanie,
a w tym przypadku żaden z tych elementów nie istnieje. Oznacza to, że nasza anima-
cja przeniesiona w tym stanie do Unity przestanie być animacją. Otrzymamy tam je-
dynie statyczną siatkę. Żeby animacja spełniła wymagania Unity, trzeba ją „przełożyć”
na język klatek kluczowych. Niektórzy nazywają to wypalaniem animacji.

1
Żeby to zadziałało, trzeba jeszcze włączyć opcję Follow Curve (podążaj za krzywą) — przyp. tłum.
170 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.26. Animacja polegająca na przemieszczaniu obiektu wzdłuż ścieżki


Źródło: Blender.

Aby przeprowadzić proces wypalania, wykonaj następujące czynności:


1. W oknie 3D View zaznacz siatkę obiektu i z menu wybierz polecenie Object/Animation/
Bake Action (obiekt/animacja/wypal akcję) — rysunek 5.27.

Rysunek 5.27. Przygotowanie do wypalenia animacji z więzami


Źródło: Blender.
Animowanie ruchu wzdłuż ścieżki i wypalanie animacji 171

2. W oknie dialogowym Bake Action ustaw numery klatek dla początku (Start Frame)
i końca animacji (End Frame). (W przypadku animacji z więzami będzie to zazwy-
czaj jej pierwsza i ostatnia klatka). W ten sposób wyznaczysz przedział na osi cza-
su, który zostanie wypalony (przekonwertowany na klatki kluczowe).
3. Parametr Frame Step (odstęp między klatkami) decyduje o dokładności przekładu
animacji. Przy mniejszych wartościach otrzymasz wierniejszą kopię animacji pier-
wotnej. Musisz jednak uważać, bo jeśli ustawisz wartość najmniejszą, czyli 1, Blen-
der utworzy klucze w każdej klatce animacji, od pierwszej do ostatniej. Cała sztuka
polega na tym, by uzyskać dużą dokładność przy możliwie najmniejszej liczbie
klatek kluczowych. (Mniejsza liczba kluczy oznacza mniejszą liczbę danych anima-
cyjnych i szybsze działanie w Unity). Ja ustawiłem ten parametr na 4, a więc klucze
animacyjne zostaną wygenerowane w co czwartej klatce.
4. Włącz opcje Visual Keying (kluczowanie wizualne) i Clear Constraints (usuń więzy),
po czym kliknij przycisk OK, aby wypalić dane animacyjne wygenerowane przez
więzy Follow Path (rysunek 5.28).

Rysunek 5.28. Ustawianie parametrów wypalania animacji


Źródło: Blender.

Po wypaleniu animacji w oknach edytorów pojawią się klatki kluczowe (rysunek 5.29).
Teraz możesz wyeksportować siatkę do Unity jako plik FBX z domyślnym ujęciem
sceny. Tam zaimportujesz ją jak typową siatkę animowaną, zgodnie ze wskazówkami
podanymi w podrozdziale „Prosta animacja kluczowana — od Blendera do Unity”.
Gratulacje! Teraz już możesz bez przeszkód przenosić animacje z Blendera do Unity!
172 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.29. Podczas wypalania animacji generowane są klatki kluczowe


Źródło: Blender.

Miksowanie kształtów i klucze kształtu


W Unity 4.3 wprowadzono obsługę animacji morfingowych, zwanych też miksowa-
niem kształtów (głównie w Unity i programie Maya). W Blenderze nazwano tę funkcję
kluczowaniem kształtu. Wszystkie rozpatrywane do tej pory animacje operują na po-
ziomie obiektowym — to znaczy, że wywołują ruch całego obiektu, np. postaci. Nato-
miast miksowanie kształtów działa na poziomie struktury obiektu i pozwala animować
wierzchołki, krawędzie oraz ścianki w obrębie wybranej siatki. Ten rodzaj animacji
przydaje się do symulowania zmiennych wyrazów twarzy, ruchów warg, mrugania
oczami i jest potrzebny wszędzie tam, gdzie nie chodzi o ruch obiektu jako całości, a je-
dynie o zmianę jego struktury.
Blenderowe kluczowanie kształtów umożliwia modelowanie postaci w rozmaitych
pozach i zapisywanie poszczególnych póz jako kluczy kształtu. Każdemu kluczowi
można też przypisać niezależną wartość wagową (z przedziału od 0 do 1 w Blenderze i od 0
do 100 w Unity) określającą siłę, z jaką dana poza będzie wpływała na kształt siatki pod-
czas animacji.
Spójrzmy na konkretny przykład. Otwórz plik blendshape_start.blend dostępny w mate-
riałach zamieszczonych na stronie powiązanej z książką. Znajdziesz w nim standardowy
obiekt blenderowy w kształcie małpiej głowy (rysunek 5.30), który możesz też utworzyć
własnoręcznie przez wybranie polecenia Add/Mesh/Monkey (dodaj/siatka/małpa). Celem
ćwiczenia będzie nadanie temu obiektowi różnych form i póz — czyli przypisanie mu
różnych kluczy kształtu — aby po przeniesieniu do Unity można było zastosować
miksowanie kształtów.
Miksowanie kształtów i klucze kształtu 173

Rysunek 5.30. Przygotowanie do tworzenia kluczy kształtu


Źródło: Blender.

Najpierw trzeba utworzyć pozę bazową (Basis). Będzie ona reprezentowała neutralną
(domyślną) konfigurację siatki, czyli taką, jaką ma bez przypisanej jakiejkolwiek pozy.
Będzie to domyślny układ wierzchołków siatki. Wykonaj więc następujące czynności:
1. Zaznacz głowę małpy w oknie widokowym.
2. W panelu Properties otwórz zakładkę Object data.
3. W rolecie Shape Keys (klucze kształtu) kliknij widoczną z prawej strony ikonę ze
znakiem plus (+), aby utworzyć pierwszy, bazowy klucz kształtu (rysunek 5.31).

Rysunek 5.31. Tworzenie bazowego klucza kształtu


Źródło: Blender.
174 Rozdział 5  Tok pracy animacyjnej

1. Utworzenie bazowego klucza kształtu jest równoznaczne z zapisaniem kopii siatki


i jej bieżącego stanu. Aby utworzyć nowy stan, dodaj nowy klucz kształtu, po czym
zdeformuj siatkę, używając standardowych narzędzi modelarskich. (Rób to w takiej
właśnie kolejności! Najpierw dodawaj klucz, a potem deformuj). Kliknij więc po-
nownie ikonę ze znakiem plus (+) w rolecie Shape Keys (rysunek 5.32). Modyfikacje,
jakie teraz przeprowadzisz, zostaną zapisane w tym kluczu kształtu, który jest zazna-
czony na liście. Ja utworzyłem dwa stany: Raised (uniesiony) i Lowered (obniżony).
Zauważ, że gdy opuszczasz tryb edycji i wracasz do trybu obiektowego, wszystkie
modyfikacje kształtu obiektu przestają być widoczne w oknie widokowym — wy-
świetlany jest stan bazowy.

Rysunek 5.32. Definiowanie kluczy kształtu


Źródło: Blender.

2. Gdy już utworzysz wszystkie potrzebne klucze kształtu, wybierz jeden z nich i zmiksuj
z kluczem bazowym przez wpisanie odpowiedniej liczby w polu Value (wartość).
Każdemu kluczowi możesz przypisać inną wartość z zakresu od 0 do 1, która okre-
śli, jak mocno dany klucz ma się mieszać z kluczem bazowym i innymi kluczami
przypisanymi siatce. Wartość 0 oznacza, że klucz nie ma żadnego wpływu na wygląd
siatki, a przy wartości równej 1 jego wpływ jest największy. Przykład mieszania
kluczy kształtów jest pokazany na rysunku 5.33.
3. Przed zaimportowaniem siatki z kluczami kształtu sprawdź w Unity, czy w panelu
Inspector jest włączona opcja Import BlendShapes (importuj mieszane kształty) —
rysunek 5.34.
Miksowanie kształtów i klucze kształtu 175

Rysunek 5.33. Aby wykonać morfing siatki bazowej, zwiększ wartość (Value) klucza Raised
Źródło: Blender.

Uwa ga
Blender umożliwia też animowanie zawartości pola Value, a to oznacza, że można tworzyć animowane
przejścia pomiędzy poszczególnymi stanami. Wszystko sprowadza się do utworzenia klatek kluczowych
z różnymi liczbami w polu Value i wygenerowania klatek pośrednich, które spowodują, że przejście od
jednego stanu do drugiego będzie płynne, a nie skokowe. Takiej animacji nie da się jednak przenieść do
Unity (przynajmniej w czasie pisania tej książki), mimo że same klucze kształtu są przez tę aplikację akcepto-
walne. Później pokażę, jak można ten problem rozwiązać, a na razie poprzestaniemy na wyeksportowaniu
małpiej głowy z kluczami kształtu do standardowego pliku FBX i zaimportowaniu jej do Unity.

4. Dodaj importowaną siatkę do sceny, zaznacz ją, a następnie sprawdź jej komponenty
w panelu Inspector. Znajdziesz tam komponent o nazwie Skinned Mesh Renderer
(renderer siatki pokrytej skórą), który w rolecie BlendShapes (mieszane kształty)
wyświetla wszystkie zaimportowane klucze kształtów. Każdy klucz ma własną wartość
w postaci liczby zmiennoprzecinkowej z przedziału od 0 do 100 (a nie, jak w Blenderze,
od 0 do 1), która domyślnie wynosi 0. Aby uzyskać morfing siatki bazowej, musisz
zwiększyć tę wartość — podobnie jak robiłeś to w Blenderze (rysunek 5.35).
176 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.34. Aby zaimportować blenderowe klucze kształtów, włącz opcję Import BlendShapes
Źródło: Blender.
Kości i rigowanie 177

Rysunek 5.35. Stosowanie kluczy kształtów w Unity po zaimportowaniu ich z Blendera


Źródło: Unity Technologies.

Jak już wspominałem, blenderowe klatki kluczowe wygenerowane dla kluczy kształ-
tów nie przenoszą się do Unity jak inne klatki kluczowe — taka jest sytuacja, gdy piszę
tę książkę. W praktyce oznacza to, że mieszania kształtów nie da się importować jako
danych animacyjnych. Problem ten można rozwiązać na dwa sposoby.
■ Utwórz wszystkie animacje dla kluczy kształtów w Unity. Użyj do tego dawnego edyto-
ra animacji dostępnego po wybraniu polecenia Window/Animation (okno/animacja).
■ Utwórz w Blenderze animację obiektu pozornego z klatkami kluczowymi dla ruchu
wzdłuż jednej tylko osi (np. Y) i z ograniczeniem położenia do wartości z przedziału
od 0 do 100. Następnie zaimportuj ten obiekt do Unity i użyj krzywych funkcyjnych
jego animacji do sterowania wartościami kluczy kształtów komponentu Skinned
Mesh Renderer. Powiązanie między obiektem pozornym a kluczami kształtu musisz
ustalić za pomocą odpowiedniego skryptu.

Kości i rigowanie
Trzeci i ostatni rodzaj animacji obsługiwany zarówno przez Blendera, jak i przez Unity to
animacja szkieletowa. Polega na deformowaniu siatki za pośrednictwem zbudowanego
w tym celu szkieletu (hierarchicznego układu kości). Szkielet zawiera też symulacje sta-
wów i innych połączeń międzykostnych. Proces łączenia go z modelem nosi nazwę skin-
ningu (czyli oblekania skórą). W Unity struktura szkieletowa nazywana jest rigiem,
a w Blenderze otrzymała nazwę armatury (rysunek 5.36).
Szczegółowe objaśnianie technicznych aspektów kości i rigowania wykracza poza ramy
tej książki. Zakładam, że zagadnienia te nie są Ci całkowicie obce, i raczej skoncentruję
się na omówieniu praktycznych aspektów przygotowywania szkieletów w Blenderze,
zwłaszcza takich, które mają być wykorzystane również w Unity.
178 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.36. Model postaci z armaturą w sekwencji animacyjnej chodu


Źródło: Blender.

Zawsze nadawaj nazwy poszczególnym kościom


Dobrym nawykiem jest nadawanie opisowych nazw wszystkim kościom szkieletu, po-
nieważ zarówno Blender, jak i Unity często wymagają wskazania określonej kości na
podstawie jej nazwy. Nie odkładaj tego na później. Wpisuj nazwy natychmiast po utwo-
rzeniu kości.
Warto też przyjąć określoną konwencję nazewniczą, zwłaszcza w odniesieniu do szkie-
letów postaci humanoidalnych i ogólnie istot żywych. Powszechnym standardem jest
oznaczanie symetrycznie rozłożonych kości przyrostkami .l lub .r (ewentualnie _left
lub _right) w zależności od tego, czy dana kość leży po lewej (left), czy po prawej (right)
stronie szkieletu. A zatem kości rąk będą miały nazwy ręka.l i ręka.r, kości udowe —
udo.l i udo.r itd. Stosowanie tego typu nazw to nie tylko ułatwienie dla współpracujących
z Tobą artystów i programistów; jest po prostu konieczne przy realizacji niektórych
zadań w Blenderze i Unity. Blender stosuje symetryczne nazwy dla kości tworzonych
za pomocą funkcji X-Axis Mirror (odbicie lustrzane względem osi X), a Unity używa
ich do automatycznego konfigurowania kości w awatarze postaci (więcej informacji
na ten temat znajdziesz w punkcie „Importowanie zrigowanych postaci do Unity” pod
koniec rozdziału) — rysunek 5.37.

Szkielety symetryczne a funkcja X-Axis Mirror


Większość postaci ludzkich, humanoidalnych i zwierzęcych ma budowę symetryczną.
Na przykład jeśli przyjąć kręgosłup za oś symetrii, człowiek ma po obu stronach rękę
i nogę. W rzeczywistości nie są one idealnie symetryczne, ale w grafice komputerowej
można śmiało założyć, że właśnie tak jest.
Kości i rigowanie 179

Rysunek 5.37. Nie zapominaj o nadawaniu kościom stosownych nazw


Źródło: Blender.

Wprawdzie możesz tworzyć każdą kość oddzielnie i rigować obie strony szkieletu nieza-
leżnie jedną od drugiej, ale dużo czasu i pracy zaoszczędzisz, jeśli skorzystasz z blende-
rowej funkcji X-Axis Mirror. Wystarczy wtedy, że utworzysz tylko jedną stronę szkieletu,
a druga zostanie wygenerowana automatycznie.
Aby funkcja zadziałała prawidłowo, kości muszą być odpowiednio ponazywane. Nazwy
muszą być zgodne z konwencją przyrostkową. Lustrzane odbicie ręki lub nogi po-
wstanie tylko wówczas, gdy utworzonej kości nadasz nazwę zakończoną przyrostkiem
.l lub .r. Aby w trakcie edycji armatury uruchomić funkcję X-Axis Mirror, zaznacz
w przyborniku pole wyboru o takiej właśnie nazwie (rysunek 5.38).

Rysunek 5.38. Podczas tworzenia szkieletu symetrycznego włącz funkcję X-Axis Mirror
Źródło: Blender.
180 Rozdział 5  Tok pracy animacyjnej

Uwa ga
Pamiętaj, że nazwy kości możesz zmieniać w oknie Outliner (organizator), w panelu N i na zakładce Bone
(kość) panelu Properties (rysunek 5.38).

Kinematyka prosta i odwrotna


Podczas pracy z długimi łańcuchami kości, takimi jak ręce, nogi czy inne kończyny
(np. ramiona ośmiornicy), często powstaje problem ułożenia ich odpowiednio do żąda-
nej pozy. Zazwyczaj animator chce ustawić w ustalonym położeniu dłoń lub stopę (czyli
koniec łańcucha kości) — choćby po to, żeby postać wzięła do ręki filiżankę z kawą
lub postawiła stopę na kolejnym stopniu schodów.
Domyślnie Blender przypisuje każdemu szkieletowi kinematykę prostą, co w praktyce
znacznie utrudnia animowanie takich póz, ponieważ wymaga manipulowania (przesu-
wania i obracania) wszystkimi elementami łańcucha, a nie tylko ostatnią kością. W przy-
padku ręki trzeba ustawić we właściwym położeniu nie tylko dłoń, ale także przedramię,
łokieć i ramię, a może nawet i bark.
Inaczej sprawa wygląda w kinematyce odwrotnej (Inverse Kinematics — IK). Tutaj
wystarczy ustawienie tylko końcówki łańcucha, np. dłoni lub stopy. Pozostałe kości
ustawi Blender, dbając przy tym, żeby wszelkie transformacje poszczególnych kości prze-
biegały zgodnie z ograniczeniami wynikającymi z ich wzajemnych połączeń. Wymaga
to jednak specjalnego skonfigurowania systemu szkieletowego na etapie rigowania, ale
o tym za chwilę.
Włączanie kinematyki odwrotnej dla ręki czy nogi przebiega, ogólnie rzecz biorąc,
podobnie. Zobaczmy zatem, jak wygląda to w przypadku nogi. Wykonaj następujące
czynności:
1. Włącz tryb układania póz (Pose Mode) i zaznacz kość piszczelową.
2. Z zakładki Bone Constraints (więzy kości) panelu Properties wybierz więzy o nazwie
Inverse Kinematics (kinematyka odwrotna) — rysunek 5.39.
3. We właściwościach kinematyki odwrotnej wskaż jako cel (Target) kość stopy, czyli
koniec łańcucha, który ma być animowany.
4. W polu Chain Length (długość łańcucha) określ długość łańcucha objętego kine-
matyką odwrotną. W przypadku nogi, która składa się z dwóch kości — piszczelowej
i udowej — długość łańcucha należy ustawić na 2 (rysunek 5.40).
To wszystko! Do skonfigurowania kinematyki odwrotnej dla nogi wystarczyło wyko-
nanie tych kilku czynności. Jeśli teraz przesuniesz lub obrócisz stopę bądź tułów, noga
automatycznie zegnie się w kolanie, aby dopasować się do nowej pozy całego szkieletu.
Kości i rigowanie 181

Rysunek 5.39. Kinematykę odwrotną przypisujemy kościom jako rodzaj więzów


Źródło: Blender.

Rysunek 5.40. Konfigurowanie nogi z kinematyką odwrotną


Źródło: Blender.

Uwa ga
Darmowa wersja Unity nie obsługuje kinematyki odwrotnej, ale to nie oznacza, że zrigowanych w ten
sposób modeli nie da się zaimportować. Podczas eksportowania animacji opartej na kinematyce od-
wrotnej Blender utworzy odpowiednie klatki kluczowe i w Unity będzie można taką animację odtworzyć.
Nie da się jednak skorzystać z kinematyki odwrotnej w czasie rzeczywistym.
182 Rozdział 5  Tok pracy animacyjnej

Kości deformowane i sterujące


Z punktu widzenia rigowania kości dzielą się na dwa podstawowe rodzaje:
■ Sterujące — do których animator ma bezpośredni dostęp i którymi może mani-
pulować. Zazwyczaj są to elementy końcowe łańcuchów IK (takie jak stopy czy dło-
nie), a także inne istotne dla animacji kości, typu głowa, tors czy biodra.
■ Deformowane — zwane też kośćmi mechanizmu — są tymi, które w wyniku prze-
mieszczania kości sterujących deformują się, ale animator nie ma do nich bezpo-
średniego dostępu. Innymi słowy: animator edytuje wyłącznie kości sterujące, a nigdy
deformowane.
Podział ten nie został oficjalnie wprowadzony ani w Blenderze, ani w Unity; stworzyli
go sami animatorzy, którzy podczas opracowywania animacji w różny sposób używają
poszczególnych kości szkieletu.
Dobrą praktyką jest, aby wszystkie kości deformowane umieszczać na odrębnej war-
stwie i na czas rigowania ukrywać je, pozostawiając widoczne jedynie kości sterujące.
Wtedy praca nad animacją staje się dużo łatwiejsza. Sama procedura ukrywania kości
deformowanych wygląda następująco:
1. Zaznacz w szkielecie wszystkie kości deformowane.
2. Wciśnij klawisz M, aby otworzyć okno dialogowe Change Bone Layers (zmień war-
stwy kości).
3. Wskaż nieużywaną warstwę. Na niej zostaną umieszczone zaznaczone kości (rysu-
nek 5.41). (Przeniesienie kości na inną warstwę wpływa jedynie na ich widoczność,
a nie na funkcjonowanie).

Eksportowanie zrigowanych postaci


Rigowane i animowane postacie można eksportować zarówno do formatu FBX (.fbx),
jak i Collada (.dae). Służą do tego polecenia odpowiednio File/Export/Autodesk FBX
i File/Export/Collada. Na rysunku 5.42 pokazane są typowe ustawienia eksportu do for-
matu FBX, a na rysunku 5.43 — analogiczne ustawienia dla formatu Collada. Jeśli wybie-
rzesz format Collada, pamiętaj, żeby eksportowana postać miała pozę spoczynkową.
Kości i rigowanie 183

Rysunek 5.41. Ukrywanie deformowanych kości na nieużywanej warstwie


Źródło: Blender.

Rysunek 5.42. Eksportowanie zrigowanej siatki do formatu FBX


Źródło: Blender.
184 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.43. Eksportowanie zrigowanej siatki do formatu DAE


Źródło: Blender.

Importowanie zrigowanych postaci do Unity


Wprowadzony w Unity 4 animacyjny system Mecanim oferuje bogaty zestaw funkcji
służących do pracy ze zrigowanymi postaciami. Import takiej postaci odbywa się niemal
tak samo jak import zwykłej siatki — wystarczy przeciągnąć plik z Eksploratora (Win-
dows) lub Findera (Mac OS) do panelu Project w Unity. Po zaimportowaniu postaci
trzeba jednak dokonać pewnych modyfikacji w ustawieniach dostępnych w panelu In-
spector. Na zakładce Rig należy rozwinąć listę Animation Type i wybrać z niej pozycję
Humanoid — tak jak na rysunku 5.44. Będzie to sygnałem dla Unity, że zaimportowana
siatka jest nie tylko animowana, ale ma także humanoidalny szkielet. Po takim uści-
śleniu informacji Unity udostępni dodatkowe funkcje, które sprawią, że praca z posta-
cią stanie się łatwiejsza. (Więcej szczegółów na ten temat znajdziesz w ramce poniżej).
Kości i rigowanie 185

Rysunek 5.44. Importowanie siatki zrigowanej postaci do Unity


Źródło: Unity Technologies.

Op c je dl a szki el e tu h um a n oi da l n eg o
Gdy wybierzesz z listy Animation Type opcję Humanoid, Unity wygeneruje dla zaimportowanej postaci
awatar, a mówiąc dokładniej: jego definicję. Jest to specjalny element, który Unity łączy z siatką postaci.
Dokładnie rzecz biorąc, wyznacza on swego rodzaju odwzorowanie przypisujące każdej kości szkieletu
określony sposób deformowania otaczającej ją siatki. Odwzorowanie to nosi nazwę Muscles (mięśnie).
W przypadku siatki zaimportowanej w jednym pliku ze szkieletem stosowanie awatara może wydawać
się zbędne, bo przecież wszystkie dane skinningowe wiążące kości z siatką zostały już ustalone w Blen-
derze jako wagi wierzchołków. Wprowadzenie awatara otwiera jednak dostęp do całej potęgi retarge-
tingu. Dzięki awatarom można sterować różnymi postaciami za pomocą tego samego szkieletu i jego
animacji. Za pośrednictwem awatara można określić, jak szkielet ma być powiązany z modelem. Zwykłe
przedefiniowanie sposobu powiązania kości z mięśniami pozwala użyć tego samego szkieletu do stero-
wania postaciami różniącymi się np. rozmiarami.

Podgląd i edycja awatara są dostępne w trybie edycji awatara (Avatar Editor) uruchamia-
nym przez kliknięcie przycisku Configure (konfiguruj) w panelu Inspector. Jeśli szkielet
ma typowo humanoidalną formę i zawiera właściwe kości, Unity stanie na wysokości
zadania i skonfiguruje awatara bez Twojego udziału. Zazwyczaj nie będziesz musiał
niczego poprawiać (rysunek 5.45).
186 Rozdział 5  Tok pracy animacyjnej

Rysunek 5.45. Podgląd awatara


Źródło: Unity Technologies.

W trybie edycji awatara okno widokowe Scene (scena) wyświetla zrigowany model,
a w panelu Hierarchy (hierarchia) wyświetlana jest w pełni rozwinięta blenderowa hierar-
chia kości. W panelu Inspector wyświetlane są powiązania między kośćmi a siatką (za-
kładka Mapping) oraz parametry mięśni (zakładka Muscles). Powiązania powinny być
w kolorze zielonym. Barwa czerwona oznacza problem i zazwyczaj wtedy potrzebna jest
interwencja w postaci ręcznego ustawienia właściwych powiązań. Można to zrobić przez
przeciągnięcie kości z panelu Hierarchy na odpowiednie pole anatomiczne w panelu
Inspector. Tylko z właściwie przypisanymi kośćmi bioder, kręgosłupa, głowy, rąk i nóg
awatar będzie działał prawidłowo. Poświęć trochę czasu, aby go należycie zdefiniować.

Podsumowanie
W tym rozdziale omówiłem skomplikowane i ważne zagadnienia związane z tworze-
niem animacji za pomocą Blendera i Unity. Blender oferuje trzy formy animacyjne,
które można bez przeszkód eksportować do Unity: podstawową animację z klatkami
kluczowymi (w tym animacja wzdłuż ścieżki), klucze kształtu i animacje szkieletowe.
Łącznie umożliwiają one tworzenie animacji ciała sztywnego (czyli ruchów polegających
na zmianie położenia lub orientacji całego obiektu) oraz animacji na poziomie struk-
turalnym (gdy obiekt jako całość pozostaje nieruchomy, a zmienia się jedynie jego
struktura — np. gdy postać porusza ustami). Używając tych form, można stworzyć
niemal każdą animację potrzebną w grach komputerowych, a to oznacza, że Blender
i Unity tworzą duet o naprawdę wielkich możliwościach.
R OZ DZ I AŁ 6

O BIEKTY , ZALEŻNOŚCI
I PROGRAMOWANIE
ZDARZENIOWE

Złożoność rzeczy — rzeczy w rzeczach — wydaje się nieskończona.


To znaczy, że nic nie jest łatwe i nic nie jest proste.
— Alice Munro

Po przeczytaniu tego rozdziału powinieneś:


■ rozumieć zależności zaprogramowane i znać sposoby ich eliminowania;
■ umieć pracować z komponentami i komunikatami;
■ wiedzieć, na czym polega programowanie zdarzeniowe;
■ umieć tworzyć systemy zdarzeń i powiadomień;
■ rozumieć relacje hierarchiczne między obiektami.
W poprzednich rozdziałach koncentrowałem się głównie na prezentowaniu takich
metod pracy w Blenderze, których rezultaty mogą być użyteczne w Unity. Pokazywa-
łem więc, jak należy tworzyć elementy gry, takie jak modułowe środowiska, tereny czy
siatki animowane, aby dało się je przenieść z Blendera do Unity przy zachowaniu jak
największej liczby ich funkcji. Teraz jednak zmienię podejście i skupię się bardziej na
praktycznych aspektach pracy w Unity. Szczególnie dużo uwagi zamierzam poświęcić
zależnościom zaprogramowanym na sztywno i sposobom ich rozwikływania. Zacznę
jednak od wyjaśnienia, czym te zależności są i jak powstają.

187
188 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

Zależności zaprogramowane
Gra komputerowa jest formą programu i powstaje jako wytwór inżynierii oprogra-
mowania. W większości dziedzin inżynieryjnych wytwarzanie polega na składaniu
pewnej całości z mniejszych elementów i nieważne, czy jest to silnik samochodu,
most, tunel, budynek czy program komputerowy — gotowy wyrób jest z technicznego
punktu widzenia sumą określonej liczby części. Może to budzić zastrzeżenia artystów
i estetów, ale w ujęciu strukturalnym całość jest po prostu rezultatem połączenia skład-
ników. Solidność i niezawodność wytwarzanego w ten sposób produktu zależą w naj-
wyższej mierze od tego, jakie części zostały użyte i jak je połączono. Ale to nie wszystko
— od jakości zastosowanych elementów zależy także łatwość utrzymania w dobrym
stanie raz zbudowanej konstrukcji.
Rozważmy uproszczony przypadek idealnego zegara złożonego z wielu wzajemnie
połączonych kół zębatych. (Wyobraź sobie olbrzymi, klasyczny zegar podobny do Big
Bena w Londynie lub Abraj Al Bait w Mekce). Jeśli koła się obracają, zegar działa. Gdy
dochodzi do awarii, zegarmistrz sprawdza każde z nich, znajduje wadliwe i wymienia
na nowe, takie samo jak oryginalne. Nowe koło zębate integruje się z pozostałymi do-
kładnie tak samo jak jego poprzednik i cały system zaczyna znów działać, jakby nic się
nie stało.
Taka izolowana naprawa jest możliwa, ponieważ każde koło, chociaż ściśle współpra-
cuje z pozostałymi, konstrukcyjnie jest od nich niezależne. Wymiana jednego z nich
nie wpływa więc w żaden sposób na inne części systemu. Gdyby jednak konstruktor
zegara wymyślił zmodyfikowane koło zębate z dodatkowymi elementami, zależnymi od
innych składników mechanizmu, wówczas naprawa wymagająca wymiany koła byłaby
bardziej skomplikowana. Powodem większych komplikacji byłyby właśnie te dodatkowe
połączenia z innymi elementami. Takie koło nie byłoby już konstrukcyjnie niezależne od
pozostałych. Zależności te byłyby ustanawiane już na etapie wytwarzania.
Przy tworzeniu gier też możemy mieć do czynienia z tego typu zależnościami, zwłasz-
cza gdy stosujemy programowanie obiektowe, kiedy to jedna klasa jest tworzona jako
bezpośrednia lub pośrednia pochodna innej klasy. Powiedzmy, że na potrzeby gry
RPG tworzysz postać czarnoksiężnika i w języku C# definiujesz dla niego klasę o nazwie
Wizard (czarnoksiężnik). Z pewnością będziesz chciał, aby Twój bohater mógł za pomocą
zaklęć zadawać wrogom obrażenia. Również sam powinien ucierpieć, jeśli zostanie
zaatakowany. Zdarzenia zachodzące w czasie gry, takie jak ukończenie zadania czy poko-
nanie wroga, powinny przenosić postać na wyższy poziom i zwiększać liczbę posiadanych
przez nią punktów doświadczenia.
Żeby to wszystko mogło działać, klasa Wizard musi „wiedzieć”, że takie czy inne zda-
rzenie zaistniało, mimo że każde z tych zdarzeń dzieje się poza nią. Krótko mówiąc:
klasa ta — jak większość klas funkcjonujących w grze — nie może istnieć w całkowitej
izolacji od otoczenia. Wcześniej czy później twórca gry musi ją powiązać z innymi klasami.
Zależności zaprogramowane 189

Rodzi się tylko pytanie: czy takie powiązania da się ustanowić bez zaprogramowania
ich na sztywno?
Ogólnie rzecz biorąc: zależności zaprogramowane są złe, ponieważ ustanawiają stałe
połączenia między klasami i obiektami. Zamiana, modyfikacja lub usunięcie jednej
klasy oznacza zatem konieczność wprowadzenia zmian także w innych klasach. Wróć-
my do przykładu z czarnoksiężnikiem rzucającym czary na swoich wrogów. Listing 6.1
przedstawia powiązanie czarnoksiężnika z wrogiem zakodowane na sztywno w języku C#.

Listing 6.1. Klasa Wizard z zaprogramowanymi zależnościami


public class Wizard
{
//Referencja do klasy wroga.
public MyEnemy Enemy;
//Funkcja wywoływana, gdy czarnoksiężnik rzuca zaklęcie ognistej kuli.
public void OnCastFireBallSpell()
{
//Zadaje wrogowi 20 punktów obrażeń.
Enemy.DealDamage(20);
}
}

Listing 6.1 przedstawia klasyczny przykład zależności zaprogramowanych. Klasa Wizard


utrzymuje bezpośrednią i wewnętrzną referencję do obiektu wroga, aby za pomocą
funkcji DealDamage (zadaj obrażenie) uszczuplać jego siły. Oczywiście program sam
w sobie nie jest zły, jeśli tylko działa. Problem w tym, że bardzo łatwo można dopro-
wadzić do jego awarii. Nie musisz się specjalnie starać, żeby zaczął źle funkcjonować.
Przykładowo: jeśli w jakimś momencie uznasz, że klasę Wizard trzeba całkowicie usunąć,
postać wroga nie dozna więcej obrażeń, ponieważ nie będzie już funkcji OnCast
FireBallSpell (rzucanie zaklęcia ognistej kuli), która te obrażenia wywołuje. Natu-
ralnie mogłaby istnieć jeszcze inna klasa wywołująca obrażenia ogniowe, ale byłoby to
powielaniem tego, co robi już klasa Wizard (takie powielanie też nie jest dobre, po-
nieważ prowadzi do niepotrzebnego wydłużania kodu). Co więcej, jeśli zmodyfikujesz
klasę Enemy, zamieniając funkcję DealDamage na precyzyjniej nazwaną DealFireDamage
(zadaj obrażenie ogniowe), kompilator zgłosi błąd, ponieważ postać czarnoksiężnika
będzie chciała wywołać funkcję DealDamage, a tej już nie będzie.
Krótko mówiąc: chodzi o to, że z powodu wzajemnych zależności między klasami nie
można tak po prostu zmienić jednej z nich i nie modyfikować pozostałych. W takich
prostych przypadkach jak ten z listingu 6.1 nie jest to wielki problem, ale gdy dotyczy
to wszystkich klas rozbudowanego programu (gry), wówczas powstaje taka plątanina
wzajemnych powiązań, że zapewnienie sprawności działania kodu staje się wręcz nie-
możliwe. Na szczęście są sposoby radzenia sobie z tego typu problemami.
190 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

Rozwiązanie DI1 — projektowanie komponentowe


i komunikaty
W obiektowo zorientowanym środowisku języka C# problem programowanych zależ-
ności rozwiązuje się — na ile jest to w praktyce możliwe — przez stosowanie funkcji
wirtualnych, interfejsów i polimorfizmu. Ostatnio pojawiło się jednak kilka rozwiązań
o charakterze zewnętrznym w stosunku do środowisk zorientowanych obiektowo. W Unity
są to komponenty i komunikaty. Aby móc z nich skorzystać, trzeba dobrze zrozumieć,
czym są i jak działają. Zobaczmy zatem, co kryje się pod każdym z tych pojęć.

Projektowanie komponentowe
W Unity poziom lub środowisko gry to po prostu scena. Składa się ona z hierarchii
obiektów, których nazwy są wyświetlane w panelu Hierarchy (hierarchia), gdy tylko
scena jest otwarta w edytorze. Na rysunku 6.1 pokazana jest scena zawierająca jedynie
kamerę i umieszczony w punkcie centralnym sześcian.

Rysunek 6.1. Scena jest hierarchicznym układem obiektów


Źródło: Unity Technologies.

Tak jak scenę można rozłożyć na poszczególne obiekty, tak i każdy obiekt można roz-
bić na mniejsze elementy. Każdy obiekt uczestniczący w grze jest zbudowany z kom-
ponentów. Obowiązkowo w każdym obiekcie musi być komponent Transform (prze-
kształcenie), który określa położenie, orientację i skalę obiektu względem globalnego
układu współrzędnych. Zazwyczaj obiekty zawierają jeszcze inne komponenty. Na
przykład sześcian z rysunku 6.2 ma ich cztery: Transform, Mesh Filter (filtr siatki), Box
Collider (zderzacz prostopadłościenny) i Mesh Renderer (renderer siatki). Pierwszy
określa dane transformacyjne obiektu, drugi zawiera dane siatkowe (wierzchołki, kra-
wędzie i wielokąty), trzeci definiuje prostopadłościan służący do wykrywania kolizji,
a czwarty umożliwia wyświetlanie siatki w trakcie gry.

1
Skrót DI oznacza wstrzykiwanie zależności (Dependency Injection) — przyp. tłum.
Rozwiązanie DI — projektowanie komponentowe i komunikaty 191

Rysunek 6.2. Każdy obiekt na scenie gry składa się z komponentów


Źródło: Unity Technologies.

Definiowanie obiektów w kategoriach modułowych komponentów, jak to robi Unity,


jest zasadniczo odmienne od tradycyjnego podejścia obiektowego. Zamiast jednej klasy,
zamykającej przy użyciu mechanizmów dziedziczenia hermetycznie cały sześcian wraz
z danymi siatkowymi i transformacyjnymi, mamy komponenty stanowiące mniejsze
i mniej hermetyczne bloki programowe. W ujęciu komponentowym każdy obiekt jest
po prostu określonym zestawem powiązanych ze sobą komponentów.
Tutaj obiekty są traktowane jak nowo powstałe byty i dlatego czasami projektowanie
komponentowe jest określane jako system bytów (entity system). Siatka sześcianu staje
się tym, czym jest, ponieważ tak określają ten byt cztery komponenty (Transform/Mesh
Filter, Box Collider i Mesh Renderer). Jeśli usuniesz jeden z tych komponentów (z wyjąt-
kiem Transform), nadal będziesz miał obiekt gry, ale inny. Jeśli tym usuniętym kompo-
nentem będzie Mesh Renderer, otrzymasz sześcian niewidzialny. Jeśli usuniesz Box Colli-
der, sześcian zostanie pozbawiony cech materialnych i każdy inny obiekt będzie przez
niego swobodnie przenikał bez żadnych kolizji. A jeśli pozbawisz go komponentu Mesh
Filter, pozostanie Ci tylko zderzacz.
Krótko mówiąc: przez definiowanie obiektów i myślenie o nich w kategoriach kompo-
nentów unikasz, przynajmniej do pewnego stopnia, zaplątania się w programowane za-
leżności. Przestań traktować obiekty gry jako skończone, kompletne elementy, a za-
cznij o nich myśleć jak o bytach powstałych z połączenia odpowiednich komponentów.
Oczywiście metoda ta ma zastosowanie nie tylko do rozważanego tu sześcianu, ale do
wszystkich obiektów.

Komunikaty
W listingu 6.1 klasa Wizard bezpośrednio zwraca się do klasy Enemy, by zadać obrażenia.
Takie podejście wymaga, aby klasa Wizard znała choć trochę szczegóły implementacji
klasy Enemy — powinna przynajmniej wiedzieć, że funkcja DealDamage jest dostępna.
192 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

A zatem w praktyce, żeby kompilacja kodu z listingu 6.1 przebiegła pomyślnie, klasa
Enemy musi mieć wbudowaną funkcję DealDamage. Zależność taka jest dla programistów
istotnym ograniczeniem.
W Unity można ten problem ominąć przez zastosowanie systemu komponentów, którym
do wzajemnej komunikacji nie jest potrzebna żadna wiedza na temat ich wewnętrznej
budowy. Oznacza to, że jeden komponent może odwoływać się do drugiego, nie wie-
dząc, co tamten robi i jak działa. Prześledźmy to na konkretnym przykładzie. Dla sze-
ścianu z rysunku 6.2 utworzymy dwa nowe komponenty (aby utworzyć sześcian, wy-
bierz z menu GameObject/Create Other/Cube, czyli: obiekt gry/utwórz inny/sześcian).
Jeden z tych komponentów będzie miał nazwę Wizard, a drugi — Enemy. Zobaczymy,
jak się komunikują.
Przypominam, że pliki skryptowe tworzymy w Unity za pomocą polecenia Assets/
Create/C# Script (elementy/utwórz/skrypt C#) — rysunek 6.3. Unity umożliwia two-
rzenie skryptów także w językach JavaScript i Boo, ale nie będziemy z nich korzystać.

Rysunek 6.3. Tworzenie skryptu w języku C#


Źródło: Unity Technologies.

Kod komponentu Wizard jest podany w listingu 6.2, a komponentu Enemy — w listin-
gu 6.3. Objaśnienia tych kodów znajdują się za listingami. Oba komponenty powinny
być powiązane z tym samym obiektem gry. Ja powiązałem je z sześcianem, co widać
na rysunku 6.4.
Rozwiązanie DI — projektowanie komponentowe i komunikaty 193

Rysunek 6.4. Przyłączanie skryptów do obiektu gry


Źródło: Unity Technologies.

Uwa ga
Aby powiązać skrypty z obiektem, po prostu przeciągnij je z panelu Project na obiekt w scenie.

Listing 6.2. Wizard.cs


using UnityEngine;
using System.Collections;
public class Wizard : MonoBehaviour
{
//Aktualizacja wykonywana w każdej klatce.
void Update ()
{
//Jeśli gracz naciśnie przycisk strzelania…
if(Input.GetButtonDown("Fire"))
{
//…zadaj obrażenia wrogom, których komponenty są powiązane z tym obiektem.
SendMessage("ApplyDamage", 10.0f,SendMessageOptions.DontRequireReceiver);
}
}
}

Listing 6.3. Enemy.cs


using UnityEngine;
using System.Collections;
public class Enemy : MonoBehaviour
{
//Funkcja wywoływana, aby zadać wrogowi obrażenie.
public void ApplyDamage(float Damage = 0.0f)
{
Debug.Log ("Damage Dealt - ouch!");
}
}
194 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

A oto kilka uwag na temat tych listingów.


■ Klasa Wizard wysyła za pomocą funkcji SendMessage (wysyłanie komunikatu) komu-
nikat ApplyDamage do obiektu gry (tego, z którym jest powiązany komponent Wizard).
Komunikat ten odbiorą wszystkie inne komponenty powiązane z tym obiektem.
■ Komponenty odbiorą komunikat w formie wywołania funkcji. Skoro w komunikacie
jest wymieniona funkcja ApplyDamage, to właśnie ona zostanie wywołana w ramach
danego komponentu. Jeśli komponent nie ma takiej funkcji, to po prostu nic się
w nim nie wydarzy.
■ Argument SendMessageOptions.DontRequireReceiver (opcje wysyłania komuni-
katu — nie wymaga odbiorcy) pełni funkcję swoistego zabezpieczenia na wypadek,
gdyby się okazało, że żaden z komponentów nie ma zaimplementowanej funkcji
ApplyDamage. Dzięki jego obecności system nie potraktuje tego jako błąd.

Uwa ga
Więcej informacji na temat funkcji SendMessage znajdziesz w dokumentacji programu Unity
(http://docs.unity3d.com/Documentation/ScriptReference/GameObject.SendMessage.html).

Wielką zaletą systemu opartego na komunikatach i komponentach jest to, że kompo-


nent (nadawca) może wysyłać komunikaty do innych (odbiorców) i wcale nie musi
znać ich szczegółów implementacyjnych. Odbiorca może odpowiedzieć nadawcy, ale nie
musi. Dzięki takiemu systemowi wymiany komunikatów komponenty mogą współpra-
cować ze sobą, mimo że nie są połączone zaprogramowanymi na stałe zależnościami.

Uwa ga
Z systemem komponentów i komunikatów wiążą się dość poważne problemy wydajnościowe. Chodzi
głównie o to, że funkcja SendMessage (a także BroadcastMessage, o której więcej powiem już za
chwilę) wykorzystuje koncepcję znaną jako mechanizm refleksji (reflection). Mówiąc w skrócie:
za każdym razem, gdy wywoływana jest funkcja SendMessage, Unity musi przejrzeć wewnętrzną
tablicę zaimplementowanych funkcji, aby na podstawie nazwy podanej w argumencie ustalić, którą
funkcję i w którym komponencie należy uruchomić (jeśli właściwa zostanie odnaleziona). Jeśli ten proces bę-
dzie przeprowadzany często i dla wielu obiektów, to może wydatnie spowolnić działanie całego programu,
szczególnie na urządzeniach mobilnych, których moce obliczeniowe są z reguły dość ograniczone. Podsumo-
wując: stosowanie funkcji SendMessage i BroadcastMessage powinno być dobrze przemyślane.

Funkcja BroadcastMessage i hierarchie


Czasami bywa konieczne wywołanie określonych funkcji w wielu obiektach jednocześnie.
Może to być np. grupa wrogów, którzy powinni zginąć w wyniku eksplozji, a może
czarnoksiężnik rzuca czary działające grupowo (np. mass-healing). Aby coś takiego
osiągnąć, można wielokrotnie użyć funkcji SendMessage i wysłać odpowiedni komunikat
Wysyłanie komunikatów do wybranych obiektów 195

do wielu obiektów, ale znacznie wygodniejsze jest użycie funkcji BroadcastMessage


(rozpowszechnianie komunikatu). Umożliwia ona przesłanie komunikatu nie tylko do
jednego, konkretnego obiektu, ale także do wszystkich jego potomków w scenicznej
hierarchii. Innymi słowy: działa podobnie jak SendMessage, tyle że wysyłany przez nią
komunikat rozprzestrzenia się kaskadowo w dół hierarchicznej struktury obiektów.
A zatem jeśli masz obiekt nadrzędny z wieloma potomkami i chcesz wysłać komunikat
do nich wszystkich, to powinieneś skorzystać z funkcji BroadcastMessage. Przykład jej
użycia pokazuje listing 6.4.

Listing 6.4. Rozsyłanie komunikatu ApplyDamage do bieżącego obiektu i wszystkich jego potomków
BroadcastMessage("ApplyDamage", 10.0f, SendMessageOptions.DontRequireReceiver);

Jeśli dobrze zaplanujesz hierarchiczny układ obiektów tworzących scenę, to funkcja


BroadcastMessage może się okazać bardzo przydatna. Przy ustalaniu tej hierarchii warto
rozważyć wstawienie do sceny obiektu pustego i ustawienie go jako nadrzędnego dla
wszystkich pozostałych (rysunek 6.5). Umożliwi to później łatwe rozsyłanie komunika-
tów, które powinny dotrzeć do każdego obiektu — najczęściej będą to powiadomienia
systemowe, takie jak Exit-Game (wyłącz grę), Load-Game (wczytaj grę) czy Save-Game
(zapisz grę).

Uwa ga
Aby otworzyć pusty obiekt gry, wybierz GameObject/Create Empty (obiekt gry/utwórz pusty). Puste
obiekty gry są tym samym co obiekty pozorne w programach do grafiki 3D. Ich jedynym komponentem
jest Transform.

Wysyłanie komunikatów do wybranych obiektów


Do tej pory rozpatrywaliśmy wysyłanie komunikatów do obiektów pojedynczych i do
połączonych ze sobą więzami hierarchicznymi. A co z dowolnymi zestawami obiek-
tów? Może trzeba rozesłać komunikat odrodzenia (respawn) do wszystkich martwych
wrogów lub do wszystkich wygasłych dopalaczy (power-upów). Może trzeba zamknąć
wszystkie drzwi w reakcji na alarm wywołany przez niepożądanego gościa. A może
trzeba tymczasowo wyłączyć wszystkie rodzaje broni będące w posiadaniu graczy, żeby
nie mogli atakować.
Czasami konieczne jest wysłanie komunikatu do wyselekcjonowanej grupy obiektów,
które niekoniecznie muszą należeć do tej samej hierarchii. Możesz wtedy wysłać odpo-
wiedni komunikat kolejno do każdego z tych obiektów za pomocą funkcji SendMessage,
ale są sposoby pozwalające uprościć to zadanie. Metoda zaprezentowana w listingu 6.5
polega na zebraniu docelowych obiektów w jedną tablicę, a następnie wysłaniu komuni-
katu do wszystkich jej elementów.
196 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

Rysunek 6.5. Tworzenie scen z jednym obiektem nadrzędnym


ułatwia rozsyłanie ogólnych komunikatów
Źródło: Unity Technologies.

Listing 6.5. Wysyłanie komunikatu do obranych obiektów


//Umieść w tablicy wszystkie obiekty określonego typu (wszystkich wrogów).
Enemy[] Enemies = Object.FindObjectsOfType<Enemy>();
//Wyślij komunikat do każdego elementu tablicy.
foreach(Enemy E in Enemies)
E.SendMessage("ApplyDamage", 10.0f, SendMessageOptions.DontRequireReceiver);
//Zrealizuj polecenie zawarte w komunikacie.

Uwa ga
Więcej informacji na temat funkcji FindObjectsOfType (wyszukaj obiekty typu) znajdziesz
w oficjalnej dokumentacji programu Unity (http://docs.unity3d.com/Documentation/ScriptReference/Object.
FindObjectsOfType.html). Unikaj stosowania jej w procedurach uruchamianych wraz z rysowaniem po-
szczególnych klatek obrazu.
Wysyłanie komunikatów do obiektów nadrzędnych 197

Wysyłanie komunikatów do obiektów nadrzędnych


Zdarzają się też sytuacje, w których konieczne jest wysłanie jakiegoś sygnału w górę
hierarchii. Na przykład gdy w strzelance kosmicznej postać bossa dysponuje bronią
wyposażoną w kilka różnych głowic i trzeba te wszystkie głowice unieszkodliwić. Naj-
prawdopodobniej będą one zaimplementowane jako obiekty potomne jednego wspólne-
go przodka — bossa. Gdy gracz unieszkodliwi taką głowicę, obiekt nadrzędny (przo-
dek) powinien zostać o tym poinformowany. Aby umożliwić obiektowi potomnemu
wysłanie powiadomienia do jego przodka, możesz użyć funkcji SendMessageUpwards
(wysyłanie komunikatu w górę). Działa ona podobnie jak funkcja BroadcastMessage,
tyle że wysyła komunikat do obiektów nadrzędnych (przodków), a nie podrzędnych
(potomków). Trzeba jednak uważać, bo wysłany w ten sposób komunikat nie zatrzy-
muje się na pierwszym napotkanym przodku, lecz wędruje dalej, aż do najwyższego
poziomu hierarchii. Przykład wywołania tej funkcji prezentuje listing 6.6.

Listing 6.6. Wysyłanie komunikatu w górę (do przodków)


SendMessageUpwards("ApplyDamage", 10.0f, SendMessageOptions.DontRequireReceiver);

System powiadomień
Stosowanie funkcji SendMessage i BroadcastMessage pozwala uniknąć logicznych za-
leżności i wzajemnych powiązań między obiektami, ale czasami może to nie wystar-
czyć. Przykładowo: gdy czarnoksiężnik zadaje obrażenia wrogowi, korzystając z funkcji
SendMessage, zapewne jeszcze kilka innych obiektów w scenie powinno być poinfor-
mowanych o tym zdarzeniu. Klasa GUI musi przecież takie rzeczy wiedzieć, chociażby
po to, żeby zaktualizować informacje wyświetlane na pasku stanu gry. Również inni
wrogowie chcieliby mieć taką informację, by na jej podstawie ich sztuczna inteligencja
mogła podjąć decyzję np. o ucieczce. Ogólnie rzecz biorąc: zawsze jest pewna liczba
klas, które powinny wiedzieć, co zdarzyło się w grze — i dotyczy to nie tylko jednego
zdarzenia, lecz wszystkich, jakie mają miejsce w czasie trwania gry.
Jeśli komunikaty między obiektami przesyłasz za pomocą funkcji SendMessage
i BroadcastMessage, czyli w sposób bezpośredni, bez udziału żadnych struktur po-
średniczących, to przy dużych projektach możesz mieć problemy z obsługą zdarzeń.
Żeby ich uniknąć, powinieneś już na wstępnym etapie programowania gry utworzyć
wyspecjalizowane centrum zarządzania powiadomieniami o zdarzeniach obsługujące
wszystkie obiekty gry. Cały system powiadamiania powinien być tak skonstruowany, aby
sprawca zdarzenia (nadawca komunikatu) przekazywał informację o typie tego zda-
rzenia do centrali i dopiero ta rozsyłała ją do wszystkich klas nasłuchujących (listeners),
które zostały zarejestrowane jako oczekujące na taki właśnie sygnał.
Listing 6.7 przedstawia pełny kod źródłowy kompletnego systemu obsługi zdarzeń
(o nazwie NotificationsManager) zapisany w języku C#. W następnych podrozdziałach
objaśnię jego działanie i pokażę, jak można go w praktyce wykorzystać.
198 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

Uwa ga
System NotificationsManager, a także przykład jego użycia w projekcie Unity z obiektami cza-
rownika i wrogów znajdziesz w materiałach powiązanych z książką (w folderze Rozdział06).

Listing 6.7. NotificationsManager


//KLASA ZARZĄDZAJĄCA ZDARZENIAMI — do przyjmowania powiadomień i powiadamiania
//listenerów (klas nasłuchujących).
//––––––––––––––––––––––––––––––––––––––––––––––––
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//––––––––––––––––––––––––––––––––––––––––––––––––
public class NotificationsManager : MonoBehaviour
{
//Zmienne prywatne.
//––––––––––––––––––––––––––––––––––––––––––––––––
//Metoda dostępowa do singletonu.
public static NotificationsManager Instance
{
get{
if(!instance) instance = new NotificationsManager();
return instance;
}
}
//Wewnętrzna referencja do instancji obiektu.
private static NotificationsManager instance = null;
//Wewnętrzna referencja do wszystkich listenerów.
private Dictionary<string, List<Component>> Listeners =
new Dictionary<string, List<Component>>();
//Metody
//––––––––––––––––––––––––––––––––––––––––––––––––
//wywoływane przy uruchamianiu gry.
void Awake()
{
//Jeśli instancja jest aktywna, usuń ją…
if(instance) {DestroyImmediate(gameObject); return;}
//lub ustaw bieżącą instancję jako jedyną.
instance = this;
}
//––––––––––––––––––––––––––––––––––––––––––––––––
//Funkcja rejestrująca nowy listener.
public void AddListener(Component Sender, string NotificationName)
{
//Dodaj listener do słownika powiadomień.
if(!Listeners.ContainsKey(NotificationName))
Listeners.Add (NotificationName, new List<Component>());
//Dodaj obiekt do listenerowej listy nadawców danego powiadomienia.
Listeners[NotificationName].Add(Sender);
}
//––––––––––––––––––––––––––––––––––––––––––––––––
//Funkcja usuwająca listener ze słownika powiadomień.
public void RemoveListener(Component Sender, string NotificationName)
{
System powiadomień 199

//Jeśli w słowniku nie ma takiego klucza, to zakończ.


if(!Listeners.ContainsKey(NotificationName))
return;
//Przejrzyj listę listenerów i gdy znajdziesz właściwy, usuń go.
for(int i = Listeners[NotificationName].Count-1; i>=0; i--)
{
//Sprawdź identyfikator instancji.
if(Listeners[NotificationName][i].GetInstanceID() == Sender.GetInstanceID())
Listeners[NotificationName].RemoveAt(i); //Pasuje. Usuń z listy.
}
}
//––––––––––––––––––––––––––––––––––––––––––––––––
//Funkcja wysyłająca powiadomienie do listenerów.
public void PostNotification(Component Sender, string NotificationName)
{
//Jeśli w słowniku nie ma żadnego klucza, to zakończ działanie.
if(!Listeners.ContainsKey(NotificationName))
return;
//W przeciwnym razie wyślij powiadomienie do właściwych listenerów.
foreach(Component Listener in Listeners[NotificationName])
Listener.SendMessage(NotificationName, Sender,
SendMessageOptions.DontRequireReceiver);
}
//––––––––––––––––––––––––––––––––––––––––––––––––
//Funkcja usuwająca wszystkie listenery.
public void ClearListeners()
{
//Usuń wszystkie listenery.
Listeners.Clear();
}
//––––––––––––––––––––––––––––––––––––––––––––––––
//Funkcja usuwająca ze słownika redundantne listenery — usunięte i nieistniejące.
public void RemoveRedundancies()
{
//Utwórz nowy słownik.
Dictionary<string, List<Component>> TmpListeners = new Dictionary<string,
List<Component>>();
//Przejrzyj wszystkie pozycje w słowniku.
foreach(KeyValuePair<string, List<Component>> Item in Listeners)
{
//Przejrzyj listę obiektów listenerów i usuń wpisy z wartością null.
for(int i = Item.Value.Count-1; i>=0; i--)
{
//Jeśli pozycja ma wartość null, usuń tę pozycję.
if(Item.Value[i] == null)
Item.Value.RemoveAt(i);
}
//Jeśli lista listenerów dla danego powiadomienia nie jest pusta, dodaj to powiadomienie do
//tymczasowego słownika.
if(Item.Value.Count > 0)
TmpListeners.Add (Item.Key, Item.Value);
}
//Zamień dotychczasowy słownik na nowy, zoptymalizowany.
Listeners = TmpListeners;
}
//––––––––––––––––––––––––––––––––––––––––––––––––
200 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

//Funkcja wywoływana przy dodawaniu nowego poziomu; usuwa zbędne wpisy w słowniku
//pozostawione przez poprzednią scenę.
void OnLevelWasLoaded()
{
//Usuń zbędne wpisy.
RemoveRedundancies();
}
//––––––––––––––––––––––––––––––––––––––––––––––––
}

NotificationsManager w szczegółach
Podsumowując: system NotificationsManager umożliwia obiektom typu listener re-
jestrowanie się za pomocą funkcji AddListener jako oczekujące na powiadomienie o za-
istnieniu określonego zdarzenia. Na każdy rodzaj zdarzeń (atak wroga, ponowne roz-
poczęcie poziomu, śmierć gracza itp.) może oczekiwać kilka listenerów, jeden albo
żaden. Gdy tylko zdarzenie zaistnieje, wszystkie listenery zarejestrowane jako oczekujące
na ten właśnie typ zdarzenia zostaną o tym fakcie poinformowane. Komponent wywo-
łujący w trakcie gry określone zdarzenie wysyła stosowne powiadomienie do obiektu
klasy NotificationsManager za pomocą funkcji PostNotification. Po odebraniu powia-
domienia obiekt NotificationsManager przesyła je dalej do wszystkich listenerów zain-
teresowanych tego rodzaju zdarzeniem. Przykładowo: klasa Enemy dzięki zarejestrowaniu
się jako oczekująca na zdarzenie ApplyDamage może zareagować na każde jego wystą-
pienie (listing 6.8).

Listing 6.8. Rejestracja klasy Enemy w systemie NotificationsManager


using UnityEngine;
using System.Collections;
public class Enemy : MonoBehaviour
{
void Start()
{
NotificationsManager.Instance.AddListener(this, "ApplyDamage");
}
//Funkcja wywoływana w celu zadania obrażeń wrogowi (zostanie wywołana automatycznie
//przez obiekt klasy NotificationsManager).
public void ApplyDamage(Component Sender)
{
Debug.Log ("Damage Dealt - ouch!");
}
}

Jak widać, klasa Enemy wykorzystuje standardową funkcję Start(), aby zarejestrować się
w systemie zarządzania powiadomieniami jako oczekująca na powiadomienia o wszyst-
kich zdarzeniach typu ApplyDamage. Rejestracja jest czymś, co każdy listener musi zrobić,
ale tylko raz. Gdy wystąpi zdarzenie oczekiwane przez listener, system wyśle mu powia-
domienie za pomocą funkcji SendMessage, co spowoduje wywołanie w nim odpowiedniej
Singletony 201

metody. Nazwa metody powinna być zgodna z nazwą oczekiwanego zdarzenia. W li-
stingu 6.8 zarówno metoda klasy Enemy, jak i oczekiwane przez nią zdarzenie mają nazwę
ApplyDamage. Przy zachowaniu tych wszystkich reguł informacja o każdym zdarzeniu
może być przekazana do dowolnej liczby listenerów — a zatem wielu wrogów może
odebrać informację o ataku i odpowiednio zareagować.
Zobaczmy teraz, jak wygląda działanie systemu zarządzania powiadomieniami z per-
spektywy obiektu wywołującego zdarzenie, o którym powinny zostać powiadomione
listenery (listing 6.9).

Listing 6.9. Przykładowa klasa Wizard wywołująca atak na obiekty klasy Enemy
using UnityEngine;
using System.Collections;
public class Wizard : MonoBehaviour
{
//Funkcja aktualizacyjna wywoływana w każdej klatce.
void Update ()
{
//Jeśli gracz wciska przycisk Fire…
if(Input.GetButtonDown("Fire1"))
{
//…powiadom o tym wrogów.
NotificationsManager.Instance.PostNotification(this, "ApplyDamage");
}
}
}

Listing ten nie wymaga dodatkowego komentarza (chociaż jest tu widoczny pewien
ważny aspekt zarządzania powiadomieniami, ale o tym powiem szerzej w następnym
podrozdziale) — po prostu gdy tylko zdarzenie ma miejsce, obiekt, który je wygene-
rował, wysyła powiadomienie do obiektu NotificationsManager.

Uwa ga
Jeśli chcesz zobaczyć obiekt NotificationsManager w działaniu, zajrzyj do plików z projektu Unity
w materiałach powiązanych z książką (w folderze Rozdział06).

Singletony
NotificationsManager jest obiektem specjalnego rodzaju. Zazwyczaj klasę lub kom-
ponent projektuje się po to, by na tej podstawie utworzyć więcej podobnych do siebie
obiektów (instancji klasy lub komponentu). Taki charakter mają przykładowe klasy
Wizard i Enemy i jeśli tylko zechcemy, mogą posłużyć nam do zapełnienia sceny wieloma
czarnoksiężnikami i wrogami. I tak też się często dzieje. Inaczej jednak wygląda sprawa
z obiektem NotificationsManager, który z natury rzeczy jest jednostką centralną, a zatem
202 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

powinien być jedynym przedstawicielem swojej klasy na scenie, a wszystkie inne


obiekty gry powinny z nim współpracować jako z głównym elementem systemu
przesyłania powiadomień o zdarzeniach.
Praktyka też pokazuje, że jeden obiekt klasy NotificationsManager w scenie całkowi-
cie wystarcza i nie ma żadnych powodów, aby tworzyć kolejne jej instancje. A skoro
tak, to moglibyśmy po prostu przyjąć ten fakt do wiadomości i przejść do spraw bar-
dziej interesujących. Jest jednak pewna kwestia, która wymaga nieco głębszej anali-
zy. Wróć na chwilę do listingu 6.1 i przyjrzyj się następującym składnikom klasy
NotificationsManager: polu Instance (instancja) i metodzie Awake (budzenie). Zobacz
także w listingach 6.8 i 6.9, jak klasy Enemy i Wizard porozumiewają się z klasą
NotificationsManager, stosując konwencję NotificationsManager.Instance.

Obiekt NotificationsManager został zaimplementowany jako singleton, czyli należący


do klasy niezezwalającej na więcej niż jedną instancję. Singleton to obiekt, który nie
jest jedynym przedstawicielem swojej klasy przez przypadek — bo akurat więcej nie
potrzeba — lecz dlatego, że kolejnych instancji nie da się już utworzyć. Po prostu tak
jest zaprogramowana klasa. W praktyce oznacza to, że każda inna klasa występująca
gdziekolwiek w projekcie Unity może uzyskać dostęp do tej jedynej instancji klasy
NotificationsManager właśnie za pomocą konstrukcji NotificationsManager.Instance.
A zatem każda klasa ma pełny dostęp do systemu zarządzania powiadomieniami
o zdarzeniach! Sławny pisarz Arthur C. Clark powiedział kiedyś: „Każda dostatecznie
zaawansowana technologia jest jak magia”. Rzeczywiście, singletony mają w sobie coś
z magii. Za ich pomocą można naprawdę skutecznie rozwiązywać problemy z zarzą-
dzaniem klasami.

Komunikaty a obiekty aktywne


Jak już wspominałem, obiekt NotificationsManager wysyła powiadomienia do listenerów
za pomocą funkcji SendMessage. Jednak żeby jej działanie było prawidłowe i skuteczne,
muszą być spełnione pewne warunki. W Unity zarówno ta funkcja, jak i BroadcastMessage
oraz SendMessageUpwards są skuteczne tylko w odniesieniu do obiektów aktywnych,
czyli takich, u których pole activeInHierarchy (aktywny w hierarchii) ma wartość true
(prawda). Wartość tę można zmieniać bezpośrednio w panelu Inspector przez włączanie
lub wyłączanie opcji pokazanej na rysunku 6.6. To samo można zrobić za pomocą
skryptu, używając funkcji SetActive (ustaw aktywny). (Więcej informacji na ten temat
znajdziesz pod adresem: http://docs.unity3d.com/Documentation/ScriptReference/Game-
Object.SetActive.html). Gdy pole activeInHierarchy ma wartość false (fałsz), wówczas
obiekt ignoruje wszystkie powiadomienia i zachowuje się tak, jakby żadne powiadomie-
nie nigdy nie zostało wysłane. Dlatego jeśli chcesz, żeby dany obiekt właściwie współ-
pracował z systemem zarządzania powiadomieniami, upewnij się, że jest aktywny.
Przemierzanie hierarchii obiektów 203

Rysunek 6.6. Przełączanie stanu aktywności obiektu


Źródło: Unity Technologies.

Przemierzanie hierarchii obiektów


Niezależnie od rozsyłania komunikatów do całych grup obiektów przydatna byłaby też
możliwość wędrowania po całej hierarchii obiektów i modyfikowania jej za pośred-
nictwem poleceń skryptowych. Przykładowo: załóżmy, że gra zawiera obiekt magazy-
nowy, w którym przechowywane są rozmaite przedmioty, takie jak kolby chemiczne,
zbroje, karabiny czy napoje magiczne. Magazyn jest obiektem nadrzędnym, a umiesz-
czone w nim przedmioty są jego obiektowymi potomkami. Sam proces umieszczania
przedmiotów w magazynie i usuwania ich stamtąd powinien się odbywać dynamicznie,
a więc musi być sterowany za pomocą skryptu. Listing 6.10 przedstawia fragment kodu
odpowiedzialny za dodanie obiektu do magazynu.

Listing 6.10. Przypisanie obiektowi nowego przodka


//Przeszukaj scenę i znajdź obiekt o nazwie ObjectName.
GameObject Child = GameObject.Find(ObjectName);
//Jeśli nie ma takiego obiektu, zakończ procedurę.
if(Child == null) return;
//Zmień przodka.
Child.transform.parent = Parent.transform;

Z powyższego listingu wynika, że dane dotyczące przodka obiekt przechowuje w kom-


ponencie Transform, a konkretnie w polu transform.parent. Więcej informacji na temat
komponentu Transform znajdziesz pod adresem: http://docs.unity3d.com/Documentation/
Script-Reference/Transform.html.
Teraz rozważmy przypadek przetwarzania wszystkich potomków obiektu przez wy-
konanie pętli, w której każde przejście będzie poświęcone innemu potomkowi. Przykład
204 Rozdział 6  Obiekty, zależności i programowanie zdarzeniowe

takiej pętli zawiera listing 6.11. Od każdego potomka jest tam pobierany komponent
Transform, ale w taki sam sposób można uzyskać dostęp do każdego innego komponentu.

Listing 6.11. Pobieranie komponentu Transform od każdego obiektu potomnego


//Wykonaj pętlę po wszystkich obiektach potomnych.
for(int i=0; i<Parent.transform.childCount; i++)
{
//Pobierz potomka.

GameObject ChildObj = Parent.transform.GetChild(i).gameObject;


//Jeśli obiekt nie jest pusty…
if(ChildObj == null) continue;
//…pobierz od niego komponent Transform.
Transform TransComp = ChildObj.GetComponent<Transform>();
}

Podsumowanie
Ten rozdział poświęciłem wyłącznie powiązaniom między obiektami, komunikatami
i zdarzeniami. Przez wielu młodych i niedoświadczonych twórców gier zagadnienie to
jest traktowane jako marginalne i niezasługujące na większą uwagę. Mam więc nadzieję,
że udało mi się udowodnić, iż taki lekceważący stosunek do tych spraw jest całkowicie
nieuzasadniony. Starałem się również pokazać, jak ważne z punktu widzenia poprawności
działania systemu zarządzania powiadomieniami jest właściwe ustawienie hierarchii
obiektów. Szczegółowo omówiłem implementację singletonowej klasy Notifications
Manager, która dopuszcza istnienie tylko jednej swojej instancji. Użycie tej struktury
pozwala każdej klasie istniejącej w ramach projektu gry uzyskać dostęp do systemu za-
rządzającego przepływem informacji o zdarzeniach i przekazywać mu takie informacje
bądź je odbierać.
R OZ DZ I AŁ 7

R ETOPOLOGIZACJA

Upraszczaj, upraszczaj.
— Henry David Thoreau

Po przeczytaniu tego rozdziału powinieneś:


■ wiedzieć, czym jest retopologizacja i dlaczego należy jej używać;
■ umieć posługiwać się blenderowymi narzędziami rzeźbiarskimi;
■ wiedzieć, na czym polega przyciąganie do powierzchni i jak działa modyfikator
Shrinkwrap;
■ umieć ręcznie zretopologizować siatkę;
■ umieć zmniejszyć szczegółowość siatki za pomocą modyfikatora Decimate.
W początkowym okresie rozwoju grafiki 3D i gier wideo większość siatek była modelo-
wana popularną metodą pudełkową (box-modeling). Nazwa wzięła się stąd, że artyści
niemal zawsze zaczynają modelowanie od standardowej siatki w kształcie prostopadło-
ścianu, podobnie jak rzeźbiarze rozpoczynają pracę od bezkształtnego kawałka drewna,
kamienia czy gliny. Z taką siatką artysta może zrobić niemal wszystko. Może jej nadać
dowolny kształt przez wytłaczanie ścianek, rozcinanie ich, zagęszczanie, fazowanie, a także
przez bezpośrednie manipulowanie poszczególnymi krawędziami i wierzchołkami.
Modelowanie pudełkowe jest opisane w większości książek poświęconych podstawom
Blendera, więc nie będę go objaśniał. Ostatnio jednakże metoda ta stała się częścią bar-
dziej rozbudowanego toku pracy zawierającego również rzeźbienie siatki i modelowanie
wysokorozdzielcze (high-poly modeling). Co te pojęcia oznaczają? Co ważnego wnoszą
do tworzenia modeli w Blenderze? Jaki jest ich wpływ na eksportowanie modeli do silnika
Unity? Na te i inne pytania postaram się odpowiedzieć w pozostałej części rozdziału.
Ważne z punktu widzenia tych odpowiedzi okaże się również pojęcie retopologizacji.

205
206 Rozdział 7  Retopologizacja

Siatki high-poly, czyli o dużej gęstości


Rozdzielczość, lub inaczej: szczegółowość siatki jest określana liczbą wierzchołków.
Z technicznego punktu widzenia im więcej wierzchołków ma siatka, tym jest bardziej
szczegółowa, ponieważ każdy wierzchołek reprezentuje punkt kontrolny na powierzchni
siatki, za pomocą którego można kształtować szczegóły. Zazwyczaj, gdy siatka ma być
importowana do silnika gry, powinna mieć tak mało wierzchołków, jak to tylko możliwe,
żeby jej przetwarzanie nie zajmowało zbyt wiele czasu. (Oczywiście zalecenie to należy
stosować z umiarem, aby nie przesadzić z nadmiernym uproszczeniem siatki). Nie
oznacza to jednak, że o ograniczaniu liczby wierzchołków trzeba myśleć przez cały czas
modelowania siatki. Wielu artystów postępuje wręcz odwrotnie — najpierw tworzą
model o małej gęstości (low-poly), a potem w miarę jego uszczegółowiania zwiększają
rozdzielczość siatki, stosując dodatkowe podziały ścianek i krawędzi. W rezultacie otrzy-
mują siatkę wysokorozdzielczą — znaną też jako subdivision surface (powierzchnia wie-
lokrotnie dzielona) — rysunek 7.1. Na rysunku 7.2 pokazane jest, jak przez wielokrotne
dzielenie zagęścić siatkę zwykłego sześcianu (A) do poziomu umożliwiającego wymo-
delowanie mniejszych szczegółów (B).

Rysunek 7.1. Wysokorozdzielcza siatka głowy. Siatki tego typu mają zagęszczoną powierzchnię,
w której można łatwo wyrzeźbić niezbędne szczegóły
Źródło: Blender.
Siatki high-poly, czyli o dużej gęstości 207

Rysunek 7.2. Siatki o małej rozdzielczości można zagęszczać przez wielokrotny


podział ich powierzchni
Źródło: Blender.

Głównym celem dzielenia powierzchni siatki jest zwiększenie liczby jej wierzchołków, bo
umożliwia to modelowanie drobnych szczegółów. Szczegóły te to zazwyczaj zmarszczki,
szpary, fałdy tkaniny, chropowatość powierzchni, wybrzuszenia, pęknięcia, włosy, włók-
na itp. Zagęszczanie powierzchni nie pozostaje jednak bez wpływu na przebieg pracy
artysty. Zmniejsza się bowiem przydatność metod modelowania pudełkowego, które
wymagają od artysty bezpośredniego manipulowania poszczególnymi wierzchołkami
i ściankami. Przy dużych gęstościach siatki modelowanie na poziomie wierzchołkowym
byłoby niezwykle żmudne i czasochłonne. Znacznie lepszym rozwiązaniem jest rzeź-
bienie modelu za pomocą specjalnych narzędzi, które swym działaniem przypominają
rzeczywiste narzędzia rzeźbiarskie. Wiele z nich omówiłem już w rozdziale 4. przy okazji
tworzenia terenów (rysunek 7.3).

Rysunek 7.3. Blenderowe narzędzia rzeźbiarskie umożliwiają modelowanie wysokorozdzielczych siatek


Źródło: Blender.
208 Rozdział 7  Retopologizacja

Krótko mówiąc: siatki o dużych rozdzielczościach otwierają przed artystą niezwykle


bogaty świat szczegółów. Dysponując mocnym sprzętem i wydajnym oprogramowa-
niem, może on teraz formować takie detale, jakie dawniej mógł jedynie symulować za
pomocą tekstur. Niestety, każdy kij ma dwa końce. Większa szczegółowość siatek staje się
wielkim problemem logistycznym i właśnie tej kwestii poświęcam następny podrozdział.

Siatki wysokorozdzielcze a gry czasu rzeczywistego


Największym problemem szczegółowych siatek tworzonych na potrzeby gier jest ich
wysoka rozdzielczość. Podczas rzeźbienia w Blenderze renderują się one z akcepto-
walną szybkością, ale zupełnie inaczej wygląda sytuacja po przeniesieniu ich do Unity,
gdzie są renderowane wraz z kompletem tekstur i z wieloma innymi siatkami, a wszystko
musi się odbywać w czasie rzeczywistym. Siatki o dużych rozdzielczościach mogą powo-
dować poważne problemy wydajnościowe objawiające się chwilowym lub nawet całko-
witym zawieszeniem gry — i niekoniecznie tylko na urządzeniach mobilnych, ale rów-
nież na komputerach stacjonarnych i konsolach. Popularny sprzęt używany do gier nie
jest jeszcze przystosowany do szybkiego renderowania takich siatek. W przyszłości
pewnie się to zmieni, ale na razie trzeba się liczyć z tego typu ograniczeniem. Rodzi się więc
pytanie: czy tworzenie wysokorozdzielczych siatek w ogóle ma sens, skoro nie dają się
płynnie renderować w czasie rzeczywistym? Czy zajmowanie się nimi nie jest tylko
marnowaniem czasu?
Odpowiedzi na te pytania nie są tak proste, jak mogłoby się wydawać. Artysta może
bowiem zastosować technikę mapowania normalnych (normal mapping) polegającą
na wyrzeźbieniu szczegółowego modelu o dużej rozdzielczości, a następnie wypaleniu
(bake) jego powierzchni w formie obrazu zwanego mapą normalnych (normal map).
Mając taką mapę, może ją potem zrzutować na uproszczoną (odpowiednią dla gry)
wersję siatki, aby symulować istnienie tych wszystkich szczegółów, które wcześniej
wyrzeźbił w siatce wysokorozdzielczej. Użyta właściwie metoda ta pozwala nadać siatce
low-poly wygląd siatki high-poly. Innymi słowy: siatka taka wygląda na bardziej szcze-
gółową niż jest w rzeczywistości.
Aby wyprodukować obie siatki — pierwotną wysokorozdzielczą oraz uproszczoną,
o mniejszej rozdzielczości, która będzie eksportowana do silnika gry wraz z mapą
normalnych — artyści zazwyczaj stosują bardzo specyficzny tok pracy. Najpierw tworzą
siatkę o dużej rozdzielczości i kształtują ją za pomocą narzędzi rzeźbiarskich. Następnie
generują jej wersję uproszczoną; robią to ręcznie lub automatycznie. Proces generowa-
nia takiej wersji low-poly jest określany jako retopologizacja (retopologizing). Artysta
musi tu często stosować techniki modelowania pudełkowego, aby w sposób właściwy
zbudować nową topologię będącą dobrym przybliżeniem oryginału.
Retopologizacja w praktyce 209

Retopologizacja w praktyce
Pozostałą część rozdziału poświęcimy na analizowanie toku pracy związanego z reto-
pologizacją, czyli takiego, który po wymodelowaniu siatki szczegółowej ma doprowadzić
do utworzenia siatki uproszczonej (łatwej do przetwarzania) współgrającej z mapą nor-
malnych. Pliki ćwiczeniowe znajdują się w folderze Rozdział07, a poszczególne czynności
opisuję krok po kroku w kolejnych punktach. Na rysunku 7.4 pokazany jest model po-
staci w obu wersjach: wysokorozdzielczej i uproszczonej.

Rysunek 7.4. Model szczegółowy (po lewej) i jego wersja uproszczona (po prawej)
Źródło: Blender.

Etap 1. Wymodeluj metodą pudełkową wstępną wersję obiektu


Gdy zamierzasz wymodelować szczegółową siatkę postaci, samochodu, broni, organicz-
nej struktury czy jeszcze czegoś innego, zazwyczaj rozpoczynasz od zgrubnego ufor-
mowania siatki o niskiej rozdzielczości. Zwykle też robisz to metodami modelowania
pudełkowego, czyli przez wytłaczanie ścianek i manipulowanie nimi. W ten sposób two-
rzysz podstawową formę i strukturę przyszłego modelu. Na razie nie ma on jeszcze żad-
nych szczegółów, stanowi tylko ogólny zarys tego, co ma dopiero powstać. Na tym etapie
siatka jest zdecydowanie low-poly, a nie high-poly. A skoro tak, to możesz stosować
niemal wszystkie dostępne narzędzia przeznaczone do modelowania pudełkowego.
Blender udostępnia je w trybie Edit (edycja) za pośrednictwem menu Mesh (siatka) —
rysunek 7.5.
210 Rozdział 7  Retopologizacja

Rysunek 7.5. Zacznij od utworzenia bazowej siatki o niskiej rozdzielczości. Uformuj ją wstępnie
metodą modelowania pudełkowego. Odpowiednie narzędzia znajdziesz w menu Mesh po włączeniu
trybu edycji
Źródło: Blender.

Uwa ga
W przypadku modeli z jedną płaszczyzną symetrii (np. modele humanoidalne) zazwyczaj wystarczy
zbudować tylko jedną ich stronę (połowę). Potem można utworzyć jej lustrzane odbicie za pomocą mo-
dyfikatora Mirror (lustro). Więcej informacji na ten temat znajdziesz pod adresem: http://wiki.blender.
org/index.php/Doc:2.6/Manual/Modifiers/Generate/Mirror.

Siatka bazowa (taka jak na rysunku 7.5) stanowi punkt wyjścia do dalszych prac. Wkrót-
ce podzielisz jej ścianki na mniejsze (zagęścisz siatkę), ale bez naruszania ogólnego
kształtu i struktury. W ten sposób przygotujesz ją do kolejnego etapu prac, który będzie
polegał na rzeźbieniu szczegółów. Gdy już zaczniesz pracować z tak zagęszczoną siatką,
pamiętaj o następujących sprawach:
■ Stosuj tylko czworokąty (i trójkąty, ale tylko tam, gdzie to jest absolutnie ko-
nieczne). Innymi słowy: dąż do tego, aby model składał się wyłącznie ze ścianek
o czterech krawędziach. Trójkątne zostawiaj tylko tam, gdzie czworokątne być nie
mogą. Ścianki trójkątne lubią tworzyć ostre kanty i niepożądane załamania. Unikaj
też wielokątów o większej liczbie boków, ponieważ mogą być przyczyną problemów
przy dzieleniu ich na mniejsze kawałki podczas zagęszczania siatki (rysunek 7.6).
Retopologizacja w praktyce 211

Rysunek 7.6. Siatkę bazową utwórz z czworokątów. Trójkąty stosuj tylko tam,
gdzie jest to nieuniknione. W ogóle nie używaj ścianek o liczbie boków większej niż cztery
Źródło: Blender.

■ Znormalizuj wymiary czworokątów. Staraj się utrzymać rozmiary wszystkich ścia-


nek na mniej więcej tym samym poziomie. W procesie zagęszczania siatki każda
ścianka zostanie podzielona na równej wielkości fragmenty, czyli mniejsze ścianki.
Jeśli w siatce podstawowej wszystkie ścianki mają zbliżone rozmiary, to skutki za-
gęszczania (gdy to nastąpi) będą przewidywalne i jednakowe na całej powierzchni
siatki. Jeśli natomiast niektóre ścianki będą znacząco większe od pozostałych — np.
na ramionach będą dłuższe niż na torsie — to zagęszczenie siatki stanie się nierów-
nomierne i jedne obszary mogą być bardziej szczegółowe niż inne (rysunek 7.7).

Rysunek 7.7. Zadbaj, aby wszystkie ścianki miały podobne rozmiary.


Duża dokładność nie jest potrzebna
Źródło: Blender.
212 Rozdział 7  Retopologizacja

■ Wyznacz charakterystyczne linie sylwetki. Określ położenie ważnych linii modelu,


takich jak talia, linia kolan, szyi, klatki piersiowej, barków, stawów łokciowych, oczu,
nosa itp. Następnie dopasuj geometrię siatki do tych linii. W praktyce polega to na
ułożeniu krawędzi w sposób ułatwiający późniejsze uwydatnienie tych linii oraz ani-
mowanie modelu bez zbytniego deformowania siatki w miejscach przegubowych,
takich jak kolana czy łokcie (rysunek 7.8).

Rysunek 7.8. Ułóż krawędzie wzdłuż ważnych linii modelu


Źródło: Blender.

Etap 2. Zwiększ rozdzielczość siatki


Po wykonaniu siatki bazowej trzeba ją zagęścić, aby możliwe było rzeźbienie szczegółów.
Stopień zagęszczenia powinien być odpowiedni do rozmiarów detali, które zamierzasz
uformować. Jeśli będzie za mały, siatka zyska wygląd kanciasty zamiast gładkiego, or-
ganicznego. Przed rozpoczęciem dzielenia ścianek na mniejsze warto też zatwierdzić
wszystkie modyfikatory użyte podczas wstępnego modelowania. Szczególnie trzeba pa-
miętać o modyfikatorze Mirror (pod warunkiem, że był użyty), bo jeśli pozostanie nie-
zatwierdzony, może pozostawić po sobie ślad w postaci wyraźnego szwu wzdłuż przecięcia
siatki z płaszczyzną symetrii. Zatwierdzenie go umożliwi algorytmom wygładzającym
działanie na całej powierzchni modelu, a nie tylko na jego połówkach. Poza tym w trakcie
Retopologizacja w praktyce 213

rzeźbienia będzie możliwe formowanie szczegółów w sposób asymetryczny, co z kolei


pozwoli w pewien sposób zróżnicować obie strony modelu. Aby zatwierdzić modyfikator
Mirror, po prostu kliknij przycisk Apply (zastosuj) w panelu Properties (właściwości) —
rysunek 7.9.

Rysunek 7.9. Zatwierdzanie modyfikatora Mirror


Źródło: Blender.

W Blenderze jest kilka sposobów na zwiększenie rozdzielczości siatki. Chyba najprościej


jest zaznaczyć wszystkie ścianki, a następnie wybrać polecenie Mesh/Edges/Subdivide
(siatka/krawędzie/podziel). Metoda ta nie powoduje jednak żadnego wygładzania siatki;
zwiększa liczbę jej ścianek, ale nie zmienia jej kształtu ani formy. W pewnych sytu-
acjach może to być korzystne, np. przy modelowaniu samochodu, ale gdy trzeba wy-
modelować jakieś struktury organiczne, takie jak kwiaty, ludzie czy grzyby, wygładzanie
będzie tak samo przydatne jak zagęszczanie (rysunek 7.10).
Innym sposobem zwiększenia rozdzielczości siatki — tym razem w połączeniu z wygładza-
niem — jest zastosowanie modyfikatora Subdivision Surface (rysunek 7.11). Modyfikator
ten nie tylko dzieli ścianki siatki, ale również wygładza jej powierzchnię. Siłę jego działania
można regulować za pomocą parametrów View (widok) i Render (renderowanie).
214 Rozdział 7  Retopologizacja

Rysunek 7.10. Polecenie Subdivide zachowuje kształt siatki, ale zwiększa liczbę jej ścianek
Źródło: Blender.

Pierwszy z nich określa stopień wygładzenia i podziału powierzchni modelu wyświe-


tlanego w oknie widokowym, a drugi pozwala na określenie tego stopnia odrębnie dla
procesu renderowania przy użyciu renderera Blender Render (będzie omawiany w roz-
dziale 9.) lub Cycles Renderer. Jeśli model jest tworzony na potrzeby gry, istotna jest
tylko wartość parametru View, ponieważ docelowy rendering będzie wykonywany
w Unity, a nie w Blenderze. Istotnym mankamentem tego modyfikatora jest to, że nie
pozwala na stosowanie odrębnego poziomu podziału siatki dla trybu rzeźbienia. Poziom
ten można ustalać wyłącznie w odniesieniu do podglądu w oknie widokowym i do ren-
derowania. Dlatego dla procesu rzeźbienia lepszym rozwiązaniem jest to, które pre-
zentuję poniżej.
Najlepsza metoda zagęszczania i wygładzania siatki przeznaczonej do rzeźbienia polega
na zastosowaniu modyfikatora Multiresolution (wielorozdzielczość) — rysunek 7.12.
Aby go użyć, należy go wybrać z listy modyfikatorów na zakładce Modifiers panelu
Properties, a następnie kliknąć przycisk Subdivide (podziel), co spowoduje zwiększenie
stopnia podziału o jeden poziom. Wysokorozdzielcza siatka z rysunku 7.4 (ta po lewej)
została zagęszczona do poziomu siódmego.
Retopologizacja w praktyce 215

Rysunek 7.11. Modyfikator Subdivision Surface


Źródło: Blender.

Rysunek 7.12. Modyfikator Multiresolution z trzecim poziomem zagęszczenia siatki


Źródło: Blender.
216 Rozdział 7  Retopologizacja

Im wyższy poziom zagęszczenia zastosujesz, tym drobniejsze szczegóły będziesz mógł


wyrzeźbić. Za pomocą parametrów Preview (podgląd), Sculpt (rzeźbienie) i Render
(renderowanie) możesz ustawić różne poziomy podziału siatki dla tych trzech trybów,
co może być przydatne w sytuacji, gdy trzeba zmniejszyć rozdzielczość siatki w celu
poprawienia wydajności komputera przy rzeźbieniu lub oglądaniu modelu. Kolejne
poziomy zagęszczenia dodawaj ostrożnie, ponieważ wyższe poziomy mogą negatywnie
wpływać na wydajność komputera i powodować opóźnienia w jego działaniu. Ustal eks-
perymentalnie, do jakiej wartości możesz się posunąć, i staraj się jej nie przekraczać.

Etap 3. Rzeźbij i dziel


Po przypisaniu siatce modyfikatora Multiresolution możesz rozpocząć proces rzeźbienia.
Ja zazwyczaj robię to etapami, stosując coraz to wyższe poziomy podziału. Maksymal-
na gęstość nie jest konieczna do wyrzeźbienia detali o stosunkowo dużych rozmiarach,
a tylko niepotrzebnie obciążałaby komputer. Dlatego zwiększam poziom zagęszczenia
dopiero wtedy, gdy tego naprawdę potrzebuję — gdy muszę wymodelować jeszcze
mniejsze szczegóły.
Przebieg takiego procesu wygląda następująco:
1. Wybierz narzędzie rzeźbiarskie. W tym celu musisz zaznaczyć model i włączyć tryb
rzeźbienia (Sculpt Mode) — rysunek 7.13.

Rysunek 7.13. Po zaznaczeniu siatki włącz tryb rzeźbienia


Źródło: Blender.
Retopologizacja w praktyce 217

2. Włącz pierwszy poziom zagęszczenia siatki — w rolecie z ustawieniami modyfikatora


Multiresolution kliknij przycisk Subdivide.
3. Wyrzeźbij detale, których rozmiary są odpowiednie dla aktualnej rozdzielczości siatki.
4. Ponownie kliknij przycisk Subdivide, aby włączyć kolejny poziom zagęszczenia,
i wyrzeźbij nieco mniejsze detale.
5. Powtarzaj ten cykl rzeźbienia, zagęszczania i znowu rzeźbienia, aż dojdziesz do
maksymalnego poziomu gęstości i szczegółowości modelu (rysunek 7.14).

Rysunek 7.14. Przeplataj rzeźbienie z zagęszczaniem siatki


Źródło: Blender.

Podczas rzeźbienia pamiętaj o następujących kwestiach:


■ Jeśli Cię stać, zafunduj sobie tablet graficzny i używaj go do rzeźbienia (zamiast
myszy). Tablet, dzięki temu że reaguje na nacisk piórka, pozwala bardziej precy-
zować działanie narzędzi rzeźbiarskich. W lewym panelu z ustawieniami narzędzia
możesz ustalić, które parametry mają być uzależnione od nacisku, a które nie (rysunek
7.15). W tym celu musisz włączyć opcję Enable tablet pressure sensitivity for… (włącz
wrażliwość tabletu na nacisk dla…) widoczną na prawo od pola danego parametru.
218 Rozdział 7  Retopologizacja

Rysunek 7.15. Włącz wrażliwość tabletu na nacisk piórka podczas rzeźbienia


Źródło: Blender.

■ Stosuj lustrzane odbicie przy rzeźbieniu detali symetrycznych. Jeśli musisz wy-
rzeźbić identyczne szczegóły po obu stronach modelu, włącz w sekcji Mirror (lustro)
rolety Symmetry (symetria) odpowiednią oś odbicia lustrzanego. To, co wyrzeźbisz
po jednej stronie, automatycznie pojawi się po drugiej stronie siatki. Właśnie w taki
sposób zostały zdeformowane policzki postaci z rysunku 7.16. Stosowanie odbicia
lustrzanego może zaoszczędzić dużo czasu, więc korzystaj z tej funkcji, gdy tylko po-
zwala na to symetryczność modelu.
Retopologizacja w praktyce 219

Rysunek 7.16. Przy rzeźbieniu symetrycznych detali stosuj lustrzane odbicie


Źródło: Blender.

■ Wybieraj narzędzie odpowiednie do zadania, jakie masz wykonać. Ludzie często


przywiązują się do jednego narzędzia i za jego pomocą usiłują robić wszystko, rów-
nież to, o czym projektant narzędzia nawet nie pomyślał. Narzędzi rzeźbiarskich
jest kilka i każde ma swoją specjalność (rysunek 7.17). Zapoznaj się z nimi wszystkimi.
Brush (pędzel) i SculptDraw (rzeźbiące wyciąganie) są najlepsze w łagodnym wy-
ciąganiu lub wpychaniu okrągłych fragmentów siatki, więc można ich używać do
modelowania gładkich szczegółów organicznych, czyli wszelkiego rodzaju guzów,
wybrzuszeń, zagłębień i szczelin. To prawda, że za pomocą tych narzędzi można
wymodelować również mnóstwo innych rzeczy, ale czasami ich użycie staje się po
prostu niewygodne. Przykładowo: przy rzeźbieniu fałdów, kantów, pęknięć czy
zmarszczek znacznie lepiej spisują się narzędzia Crease (kant), Nudge (popychanie)
i Pinch (szczypanie). Właśnie ich użyłem do wymodelowania fałdek skóry wokół
ust i nosa na twarzy przykładowej postaci.
220 Rozdział 7  Retopologizacja

Rysunek 7.17. Używaj wszystkich dostępnych pędzli


Źródło: Blender.

■ Używaj parametru Texture (tekstura). Rzeźbienie z użyciem tekstury jako ele-


mentu sterującego działaniem pędzla jest doskonałym sposobem na modelowanie
porów skóry, włosów, tkanin, zmarszczek na wargach i palcach oraz wielu innych
tego typu szczegółów. Po prostu wybierz właściwą teksturę, a ona zmusi pędzel do
zróżnicowania siły działania w zależności od zapisanych w niej wartości kolorów.
Aby z tego skorzystać, musisz najpierw przygotować odpowiednią teksturę. Może to
być tekstura proceduralna, np. Clouds (chmury), ale może też być wczytana z pliku.
Wszystko to ustalisz na zakładce Texture panelu Properties. Wymagany rodzaj tek-
stury wybierz z listy rozwijanej Type (typ). Gdy już ustalisz wszystkie właściwości
tekstury, wskaż ją w próbniku dostępnym po kliknięciu okna podglądu w rolecie
Texture przybornika (rysunek 7.18). Ja wykorzystałem teksturę chmurową do
wyrzeźbienia łuków brwiowych.
Retopologizacja w praktyce 221

Rysunek 7.18. Do rzeźbienia tak drobnych szczegółów jak brwi użyj pędzla z odpowiednią teksturą
Źródło: Blender.

Etap 4. Retopologizuj
Po zakończeniu rzeźbienia wysokorozdzielczego modelu możesz przystąpić do jego re-
topologizacji, czyli tworzenia wersji uproszczonej, z siatką o mniejszej gęstości. Blender
umożliwia przeprowadzenie tej operacji na wiele sposobów, oferując zarówno własne
narzędzia, jak i z komercyjnych dodatków. Ja skoncentruję się na dwóch metodach
ręcznego retopologizowania na podstawie narzędzi blenderowych. Są to metody z pew-
nością żmudniejsze niż te oparte na bardziej zautomatyzowanych narzędziach (takich
jak Contours Retopology), ale gdy raz poznasz metodę ręczną, będziesz mógł retopo-
logizować siatki niezależnie od tego, czy masz dostęp do komercyjnych narzędzi, czy nie.
Jest takie znane powiedzenie: „Dasz biedakowi rybę, to będzie syty przez jeden dzień,
ale jeśli nauczysz go łowić ryby, będzie syty do końca życia”. Ja chcę Cię nauczyć ło-
wienia ryb i dlatego opiszę najpierw metodę z przyciąganiem do powierzchni, a potem
z modyfikatorem Shrinkwrap (owijanie).

Retopologizowanie z przyciąganiem do powierzchni


Metoda z przyciąganiem do powierzchni pozwala utworzyć siatkę low-poly stopniowo,
ścianka po ściance. Zacznij od włączenia widoku lokalnego (Local), czyli takiego, w któ-
rym wyświetlana będzie tylko siatka zaznaczona (pozostałe będą niewidoczne), aby móc
pracować szybciej, gdyż Blender będzie miał mniej ścianek do wyrenderowania. W tym
celu zaznacz właściwą siatkę i wciśnij klawisze Shift+I (jeśli masz włączony tryb sterowa-
nia z programu Maya) lub wybierz polecenie View/View Global/Local (widok/widok
globalny/lokalny) — rysunek 7.19.
W razie potrzeby możesz pójść dalej i jeszcze bardziej ułatwić pracę sobie oraz Blen-
derowi. Możesz mianowicie włączyć tryb edycji, zaznaczyć niepotrzebne w danym
momencie ścianki i ukryć je. Aby ukryć zaznaczone ścianki, wciśnij klawisze Ctrl+H
222 Rozdział 7  Retopologizacja

Rysunek 7.19. W widoku lokalnym wyświetlana jest tylko siatka zaznaczona


Źródło: Blender.

lub wybierz polecenie Mesh/Show/Hide/Hide Selected (siatka/pokaż/ukryj/ukryj zazna-


czone). Aby przywrócić widoczność ukrytych ścianek, wciśnij klawisze Shift+Ctrl+H
lub wybierz Mesh/Show/Hide/Show Hidden (siatka/pokaż/ukryj/pokaż ukryte) — rysu-
nek 7.20. Chodzi o to, żeby widoczny był tylko ten fragment siatki, który właśnie zamie-
rzasz zretopologizować.

W s k a z ów ka
Możesz oczywiście retopologizować siatkę w całości, ale łatwiej jest robić to etapami. Po zretopologizo-
waniu jednej części przechodź do następnej itd. Za każdym razem ukrywaj te fragmenty siatki, którymi
nie będziesz się zajmował. Tak pracuje się znacznie łatwiej.

Po tych wstępnych przygotowaniach zacznij tworzyć nową, uproszczoną siatkę. Wykonaj


następujące czynności:
1. Włącz widok siatki od przodu.
2. Wstaw do sceny nowy obiekt płaszczyzny. W tym celu kliknij przycisk Plane (płasz-
czyzna) w przyborniku po lewej stronie interfejsu (rysunek 7.21) lub wybierz
z górnego menu polecenie Add/Mesh/Plane (dodaj/siatkę/płaszczyzna) — jeśli uży-
wasz Blendera w wersji starszej niż 2.7.
Retopologizacja w praktyce 223

Rysunek 7.20. Przywracanie widoczności ukrytych ścianek


Źródło: Blender.

Rysunek 7.21. Utwórz płaszczyznę jako pierwszy wielokąt siatki low-poly


Źródło: Blender.
224 Rozdział 7  Retopologizacja

3. W ustawieniach tworzonej płaszczyzny zaznacz pole Align to View (wyrównaj do


widoku), aby ustawić ją równolegle do powierzchni okna widokowego.
4. Jeśli jest to potrzebne, zmniejsz lub zwiększ wymiary płaszczyzny.
5. Ustaw płaszczyznę w dogodnym położeniu przed wysokorozdzielczą siatką. Nie
obracaj jej. Płaszczyzna jest pierwszym wielokątem siatki niskorozdzielczej.
6. Płaszczyzna będzie przedmiotem wielu zabiegów, więc powinna być dobrze widoczna
na tle siatki wysokorozdzielczej. Aby poprawić widoczność płaszczyzny, zaznacz ją,
po czym w panelu Properties (właściwości) otwórz zakładkę Object (obiekt) i w rolecie
Display (wyświetlanie) włącz następujące opcje:
 X-Ray (rentgen) — spowoduje, że płaszczyzna będzie zawsze widoczna przed
siatką;
 Wire (kontury);
 Draw All Edges (rysuj wszystkie krawędzie).
Dodatkowo z listy rozwijanej Maximum Draw Type (maksymalny typ rysunku)
wybierz Wire, aby płaszczyzna była renderowana w trybie konturowym. Umożliwi
to rysowanie konturowej struktury siatki niskorozdzielczej wokół siatki retopolo-
gizowanej (rysunek 7.22).

Rysunek 7.22. Popraw widoczność siatki niskorozdzielczej


Źródło: Blender.

W ramach przygotowań do retopologizacji musisz jeszcze uaktywnić tryb przyciągania


do powierzchni, aby za każdym razem, gdy przesuniesz wierzchołek siatki low-poly,
był on przyciągany — przysuwany automatycznie — do najbliższego punktu powierzchni
Retopologizacja w praktyce 225

siatki high-poly. Umożliwi Ci to budowanie ścianka po ściance nowej siatki, która bę-
dzie automatycznie dopasowywana do trójwymiarowych kształtów modelu wysokoroz-
dzielczego, a więc na pewno będzie dobrym jego przybliżeniem.
Aby uaktywnić przyciąganie do powierzchni, wykonaj następujące czynności:
1. Włącz funkcję przyciągania (snapping). W tym celu kliknij ikonę w kształcie ma-
gnesu znajdującą się na pasku narzędziowym okna 3D View (widok 3D).
2. Rozwiń listę Snap Element (element przyciągający) i jako element przyciągający
wybierz ściankę (Face), ponieważ siatka low-poly ma być dopasowana do ścianek
siatki high-poly.
3. Aby mieć pewność, że przyciągany będzie element aktywny, czyli zaznaczony, wy-
bierz z listy rozwijanej Snap Target (cel przyciągania) opcję Active (aktywny).
4. Włącz funkcję Project individual elements on the surface of other objects (rzutowanie
poszczególnych elementów na powierzchnię innych obiektów). Dzięki temu przy-
ciąganie będzie mogło funkcjonować między zupełnie odrębnymi siatkami, a więc
wierzchołki siatki low-poly będą przyciągane do ścianek siatki high-poly. Pełna konfi-
guracja funkcji przyciągania jest pokazana na rysunku 7.23.

Rysunek 7.23. Uaktywnienie przyciągania do powierzchni wymaga ustawienia kilku różnych opcji
Źródło: Blender.

W końcu, gdy już wszystko jest gotowe do retopologizacji, wykonaj następującą procedurę:
1. Przy zaznaczonej siatce płaszczyzny włącz tryb edycji (Edit Mode).
2. W ortogonalnym widoku od przodu ustaw wierzchołki płaszczyzny w ważnych
punktach siatki high-poly. Staraj się zachować kształt i kontury oryginału, układając
pętle krawędziowe tam, gdzie prawdopodobnie byłyby, gdybyś od początku mo-
delował całą siatkę metodą pudełkową. Przesuwane przez Ciebie wierzchołki będą
automatycznie przyciągane do powierzchni oryginału. Kontynuuj ten proces, dodając
kolejne wielokąty przez wytłaczanie (Extrude) istniejących (rysunek 7.24).
226 Rozdział 7  Retopologizacja

Rysunek 7.24. Wymodeluj siatkę niskorozdzielczą, stosując techniki znane z metody pudełkowej
Źródło: Blender.

3. Po ustawieniu kilku ścianek obejrzyj model pod różnymi kątami w widoku per-
spektywicznym. Zobacz, jak dzięki przyciąganiu do powierzchni nowe ścianki do-
pasowały się do kształtu siatki pierwotnej (rysunek 7.25).

Rysunek 7.25. Przyciąganie do powierzchni skutecznie pomaga w dopasowywaniu nowej


geometrii do kształtu siatki wysokorozdzielczej
Źródło: Blender.
Retopologizacja w praktyce 227

4. Postępuj tak aż do wygenerowania całej siatki niskorozdzielczej (rysunek 7.26).


Ostrzegam: ręczna retopologizacja jest czasochłonna. Gdy w grę wchodzi model po-
staci ludzkiej, proces ten może zająć kilka godzin.

Rysunek 7.26. Siatka low-poly wygenerowana z użyciem


funkcji przyciągania dobrze przylega do modelu wysokorozdzielczego
Źródło: Blender.

Uwa ga
Więcej informacji na temat funkcji przyciągania do siatek znajdziesz w dokumentacji Blendera na stronie:
http://wiki.blender.org/index.php/Doc:2.6/Manual/3D_interaction/Transform_Control/Snap_to_Mesh.

Retopologizowanie z użyciem modyfikatora Shrinkwrap


Metoda ta jest rzadziej używana, bo nie jest tak uniwersalna jak poprzednia, ale za to
znakomicie sprawdza się, gdy trzeba szybko zretopologizować siatkę lub jej fragment
o kształcie symetrycznym, wydłużonym i najlepiej cylindrycznym, np.: nogę, rękę czy
nawet tors. Gorzej wypada, gdy siatka jest niesymetryczna i nieliniowa, jak w przypadku
ucha, dłoni czy fryzury. Nic jednak nie stoi na przeszkodzie, aby stosować ją tam, gdzie
szybko daje dobre rezultaty, a w trudniejszych obszarach sięgać po metodę opartą na
przyciąganiu do powierzchni. Żeby poznać bliżej modyfikator Shrinkwrap (owijanie),
rozważmy przypadek retopologizacji siatki wysokorozdzielczej samych nóg modelu
humanoidalnego (rysunek 7.27).
228 Rozdział 7  Retopologizacja

Rysunek 7.27. Modyfikator Shrinkwrap przydaje się do szybkiego retopologizowania długich,


cylindrycznych siatek
Źródło: Blender.

Oczywiście można by te nogi zretopologizować również omówioną wcześniej metodą


przyciągania do powierzchni, ale modyfikator Shrinkwrap pozwoli nam zaoszczędzić
trochę czasu. Oto procedura jego użycia:
1. Wykonaj cylindryczną siatkę, aby aproksymować wymodelowaną nogę. Zacznij od
utworzenia okręgu — w przyborniku otwórz panel Create (tworzenie) i kliknij przy-
cisk Circle (okrąg). Korzystając z widoków od przodu i z boku, ustaw okrąg na wy-
sokości kostki lewej bądź prawej nogi (rysunek 7.28).
2. Włącz tryb edycji. Następnie zaznacz wszystkie krawędzie okręgu i wytłocz je w górę,
tworząc pionowe ścianki (wzdłuż osi Z) jako powierzchnię boczną walca. Walec
powinien być tak długi jak noga (rysunek 7.29).
3. Wstaw kilka dodatkowych pętli krawędziowych i rozstaw je w miejscach istotnych
dla kształtu nogi. Z grubsza uformuj walec, ale nie trać czasu na dokładne modelo-
wanie, ponieważ zrobi to za Ciebie modyfikator Shrinkwrap (rysunek 7.30).
Retopologizacja w praktyce 229

Rysunek 7.28. Aproksymowanie nogi rozpocznij od utworzenia okręgu


Źródło: Blender.

Rysunek 7.29. Przez wytłoczenie krawędzi okręgu utwórz walec wysoki jak noga
Źródło: Blender.
230 Rozdział 7  Retopologizacja

Rysunek 7.30. Z grubsza uformuj siatkę walca


Źródło: Blender.

4. Wstaw jeszcze kilka pętli pomiędzy tymi, które utworzyłeś poprzednio, aby uzyskać
odpowiednią rozdzielczość nowej siatki (rysunek 7.31).

Rysunek 7.31. Zwiększ nieco rozdzielczość nowej siatki przez wstawienie


dodatkowych pętli krawędziowych
Źródło: Blender.
Dziesiątkowanie 231

5. Teraz możesz użyć modyfikatora Shrinkwrap. Zaznacz więc cylindryczną siatkę


nogi i na zakładce Modifiers panelu Properties wybierz modyfikator Shrinkwrap.
6. W polu Target (cel) ustaw nazwę wysokorozdzielczej nogi. Siatka niskorozdzielcza
automatycznie się do niej dopasuje. Po prostu modyfikator przyciągnie jej wierzchoł-
ki do powierzchni siatki docelowej (rysunek 7.32).

Rysunek 7.32. Przez użycie modyfikatora Shrinkwrap do retopologizowania siatek cylindrycznych


można zaoszczędzić sporo czasu
Źródło: Blender.

7. Po zatwierdzeniu modyfikatora może się okazać, że niektóre wierzchołki wylądowały


nie tam, gdzie powinny. W takim przypadku po prostu zastosuj standardową techni-
kę przyciągania do powierzchni i ustaw te wierzchołki we właściwych miejscach.

Dziesiątkowanie
Omówię jeszcze jedną metodę upraszczania siatek, szybką, ale mało dokładną. Polega
ona na zastosowaniu modyfikatora Decimate (dziesiątkowanie). Chociaż nie jest on
uznawany oficjalnie jako narzędzie retopologizacyjne, umożliwia osiągnięcie podobnego
rezultatu, czyli uproszczonej siatki.
Modyfikator Decimate ma charakter proceduralny i parametryczny, co oznacza, że jego
działanie jest zależne w dużym stopniu od wpisanych przez Ciebie liczb. Na podstawie
tych liczb redukuje szczegółowość siatki i zmniejsza liczbę jej ścianek. Określam tę
metodę jako „szybką i niedokładną”, ponieważ jest rzeczywiście szybka, ale tylko w nie-
232 Rozdział 7  Retopologizacja

wielkim stopniu pozwala na sterowanie procesem tworzenia nowej topologii siatki.


Czasami daje rezultat, o jaki chodziło, a czasami nie. Ty tylko wpisujesz liczbę, a resztę
załatwia Blender. Może Ci się spodoba, a może nie!
Procedura użycia modyfikatora Decimate wygląda następująco:
1. Zaznacz siatkę i na zakładce Modifiers panelu Properties wybierz modyfikator De-
cimate (rysunek 7.33).

Rysunek 7.33. Dziesiątkowanie to szybka metoda na zmniejszenie szczegółowości siatki.


Tutaj zastosowano je w odniesieniu do głowy postaci
Źródło: Blender.

2. Za pomocą parametru Ratio (stopień) ustal, w jakim stopniu siatka ma być zdzie-
siątkowana. Przy wartości 1 nic się nie zmieni. Gdy ustawisz 0, siatka w zasadzie
zniknie. A zatem zwykle będzie to wartość większa od 0 i mniejsza od 1. Im mniej-
szą wpiszesz, tym mniej zostanie ścianek i szczegółów siatki. Cała sztuka polega na
tym, by parametr Ratio miał jak najmniejszą wartość, ale żeby siatka zachowała
przy tym należyty wygląd (rysunek 7.34).
Jako ciekawostkę podam, że w przypadku modelu z rysunku 7.34 modyfikator Decimate
wykonał kawał roboty, zmniejszając liczbę ścianek głowy z ponad miliona do zaledwie
kilku tysięcy. Jednakże gdy już zatwierdziłem modyfikator i w trybie edycyjnym zacząłem
sprawdzać topologię nowej siatki, wyszły na jaw typowe dla tej metody problemy.
Otóż modyfikator, dziesiątkując ścianki, nie zwracał uwagi na strukturę topologiczną
nowej siatki i w zupełnie niepotrzebnych miejscach powstawiał ścianki trójkątne.
Uzyskana w ten sposób siatka właściwie nie nadaje się do animacji (rysunek 7.35).
Dziesiątkowanie 233

Rysunek 7.34. Zmniejszanie szczegółowości siatki za pomocą modyfikatora Decimate


Źródło: Blender.

Rysunek 7.35. Modyfikator Decimate zazwyczaj pozostawia po sobie wielki nieład. Zgrabne
deformowanie takiej siatki jest raczej niemożliwe
Źródło: Blender.
234 Rozdział 7  Retopologizacja

Podsumowanie
W tym rozdziale omówiłem zagadnienie retopologizacji (czasami określanej krótko
retopo). Celem tego procesu jest po prostu przekształcenie szczegółowej siatki wyso-
korozdzielczej w uproszczoną siatkę o niskiej rozdzielczości — taką, którą da się łatwo
przenieść do silnika gry (np. Unity) i którą będzie można tam łatwo przetwarzać. Mo-
del wysokorozdzielczy jest potrzebny do wypalenia mapy normalnych, czyli specjalnej
tekstury zawierającej informacje o detalach jego powierzchni. Później, podczas trwania
gry, mapa ta będzie rzutowana na uproszczoną siatkę modelu w celu zasymulowania tych
wszystkich szczegółów. Do map normalnych i ich wypalania wrócimy w rozdziale 9.
W Blenderze stosuje się trzy podstawowe metody retopologizacji: z przyciąganiem do
powierzchni, z modyfikatorem Shrinkwrap i z modyfikatorem Decimate. Najdokładniej-
szą i zarazem najbardziej elastyczną metodą jest ręczne budowanie nowej siatki z au-
tomatycznym przyciąganiem jej wierzchołków do ścianek siatki pierwotnej. Modyfikator
Shrinkwrap może być przydatny, gdy siatka pierwotna jest długa i cylindryczna. Na-
tomiast modyfikator Decimate nadaje się do retopologizowania wyłącznie siatek, które
nie będą animowane i deformowane.
R OZ DZ I AŁ 8

Z APISYWANIE STANU GRY


A TRWAŁOŚĆ DANYCH

Trudno sobie wyobrazić moc, jaką można posiąść, mając dostęp do tak wielu
rodzajów danych.
— Tim Berners-Lee

Po przeczytaniu tego rozdziału powinieneś:


■ rozumieć pojęcie trwałości danych;
■ znać klasę PlayerPrefs;
■ mieć świadomość ograniczeń klasy PlayerPrefs;
■ wiedzieć, czym jest XML i na czym polega serializacja danych;
■ umieć tworzyć, zapisywać i wczytywać stany gry.
Jednym z wielu zadań, jakie stoją przed każdym twórcą gier, jest umożliwienie graczowi
zapisania bieżącego stanu gry, aby po przerwie mógł ją wznowić dokładnie od tego
momentu, w którym ją przerwał. Chodzi o zapisanie tzw. danych trwałych (persistent
data), które w stanie niezmienionym mogą być przechowywane w pamięci masowej
i gdy zajdzie potrzeba, posłużą do odtworzenia wszystkich parametrów niezbędnych
do wznowienia gry. Użytkownik, nawet gdy wyłącza komputer, powinien mieć pew-
ność, że jeśli włączy go ponownie, dane te będą nadal dostępne. Pod tym względem są
one przeciwieństwem danych ulotnych (np. bieżące położenie wskaźnika myszy), które
są przechowywane w pamięci RAM i bezpowrotnie tracone z chwilą zakończenia gry
lub wyłączenia komputera. W tym rozdziale obiektem naszych zainteresowań będą
wyłącznie dane trwałe. Pokażę mianowicie, jak w programie Unity można zaprogramować
ich tworzenie, zapisywanie i wczytywanie. Unity oferuje dwa podejścia do tego zagadnienia
i oba zostaną opisane.

235
236 Rozdział 8  Zapisywanie stanu gry a trwałość danych

Uwa ga
W tym rozdziale skupimy się na Unity, nie na Blenderze. Przedmiotem rozważań będzie głównie pisanie
w języku C# skryptów realizujących zadania tworzenia, zapisywania i wczytywania stanu gry.

Dane trwałe
Niemal w każdej grze da się wyróżnić dwa podstawowe rodzaje danych trwałych. Są to:
■ Dane odnoszące się do gry. Są to wszystkie dane związane z elementami gry. Pozo-
stają one niezmienne przez cały czas trwania gry i obejmują dane definiujące sceny,
dźwięki, ruchy, animacje, siatki, tekstury itp. Dane te muszą istnieć zarówno w trakcie
trwania gry, jak i po wyłączeniu komputera, a na dodatek nie mogą być w żaden
sposób modyfikowane przez gracza. Są po prostu stałą częścią gry.
■ Dane odnoszące się do użytkownika. Należą do nich wszystkie dane wewnętrzne,
które mogą się zmieniać w trakcie gry i których stan ma znaczenie dla jej przebiegu.
Mają zatem dwie ważne cechy: zdolność do zmieniania się i powiązanie z przebiegiem
gry. Dane odnoszące się do użytkownika ulegają zmianom, gdy gracz przenosi
się w inny rejon sceny, gdy postać wroga rusza w pościg za postacią gracza lub gdy
główny bohater otwiera drzwi i ich nie zamyka (zmienia stan drzwi z zamkniętych
na otwarte). W takich i podobnych przypadkach dochodzi do zmiany — obiekt
przechodzi z jednego stanu do innego. Jak już wspomniałem, drugą ważną cechą
danych odnoszących się do użytkownika jest ich stopień powiązania z przebiegiem
gry. Załóżmy przykładowo, że scena zawiera ptaka, który gdzieś w oddali leci sobie
po wytyczonej ścieżce i jedyną jego rolą jest spotęgowanie wrażenia, że gra toczy
się w środowisku naturalnym. Obiekt ten, chociaż ulega zmianom, nie ma jednak
większego znaczenia dla samej istoty gry i tak naprawdę trudno jego stan zaliczyć
do danych, które trzeba zapisywać. Gdy użytkownik będzie zapisywał stan gry,
ptak może być rzeczywiście w innym położeniu niż początkowe, ale tak naprawdę
nie ma ważnego powodu, by taką zmianę zachowywać. Po wznowieniu gry nie będzie
przecież miało znaczenia, czy ptak wznowi swój lot z miejsca zapisanego, czy po prostu
zacznie go od nowa.
Jedynym rodzajem danych, które trzeba zapisywać jako stan gry, są te odnoszące się
do użytkownika. Przy ustalaniu, co i jak należy zapisać, wystarczy, że skupisz się na
określonego typu obiektach i wybranych mechanizmach zapisu. Warto zrobić to dość
wcześnie, aby pod tym kątem zoptymalizować cały projekt gry. Nie od rzeczy jest myślenie
o zapisywaniu stanu gry już na etapie przygotowań i wstępnego projektowania. Poświęć
trochę czasu na przemyślenie tych kwestii i wcześniej ustal, które obiekty trzeba będzie
brać pod uwagę przy zapisie stanu gry, a które można pominąć. Nie myśl, że będziesz
mógł to zrobić na końcu, gdy gra jest już niemal gotowa.
Preferencje gracza 237

Preferencje gracza
W Unity najszybszym i chyba najprostszym sposobem na zapisywanie danych trwałych,
który można stosować na wszystkich platformach, jest posłużenie się klasą PlayerPrefs
(skrót od player preferences — preferencje gracza). Zgodnie z nazwą jest ona przeznaczona
do zapisywania pewnego rodzaju danych odnoszących się do użytkownika, a konkretnie
preferencji gracza, czyli zdefiniowanych przez niego ustawień parametrów gry. A za-
tem jeśli potrzebujesz zapisać dane, takie jak rozdzielczość obrazu, stopień trudno-
ści, napisy, jasność, język, system sterowania, tryb okienkowy itp., możesz śmiało użyć
klasy PlayerPrefs.
Jedną z zalet klasy PlayerPrefs jest to, że do posługiwania się nią nie jest wcale po-
trzebna znajomość takich spraw, jak nazwy plików czy ścieżki systemowe. Można się przy
tym skoncentrować wyłącznie na gromadzeniu informacji i zapisywaniu ich w od-
powiednim momencie. Klasa ta działa jak baza danych, do której można wprowadzać
dane i je stamtąd pobierać, ale wszystkie potrzebne do tego mechanizmy systemowe są
uruchamiane wewnętrznie przez Unity.
Zobaczmy na kilku przykładach, jak to wygląda w praktyce. Spójrz na listing 8.1 z kodem
zapisu bieżącej rozdzielczości w bazie danych PlayerPrefs.

Listing 8.1. Zapisywanie rozdzielczości przy użyciu klasy PlayerPrefs


PlayerPrefs.SetInt("ScreenWidth",Screen.width);
PlayerPrefs.SetInt("ScreenHeight",Screen.height);
PlayerPrefs.Save();

Uwa ga
Metoda Save() klasy PlayerPrefs jest wywoływana automatycznie przy zamykaniu programu
Unity. Natomiast w przypadku awarii lub przedwczesnego wyjścia z głównej pętli gry żadne dane nie są zapi-
sywane. Dlatego warto ręcznie wywoływać tę metodę i zapisywać dane, gdy tylko taka potrzeba zachodzi.

Klasa PlayerPrefs zawiera kilka metod służących do zapisywania danych. SetInt za-
pisuje wartości całkowite, SetFloat — wartości zmiennoprzecinkowe, a SetString —
wartości tekstowe. W listingu 8.1 do zapisu wymiarów okna, czyli szerokości i wysokości,
wyrażonych w pikselach użyto metody SetInt. (Zazwyczaj okno gry obejmuje cały ekran,
ale nie zawsze tak musi być).
Wszystkie wymienione wyżej metody zapisujące mają taką samą postać. Pierwszy ar-
gument określa unikatową nazwę zapisywanej wartości. W listingu 8.1 są to łańcuchy
znakowe ScreenWidth i ScreenHeight. Wynika stąd, że właśnie pod takimi nazwami
zostaną zapisane w bazie danych PlayerPrefs rekordy z liczbami całkowitymi oznaczają-
cymi szerokość i wysokość ekranu. Liczby te można w każdym momencie trwania gry
pobrać w sposób pokazany w listingu 8.2.
238 Rozdział 8  Zapisywanie stanu gry a trwałość danych

Listing 8.2. Wczytywanie rozdzielczości przy użyciu klasy PlayerPrefs


int ScreenWidth = PlayerPrefs.GetInt("ScreenWidth");
int ScreenHeight = PlayerPrefs.GetInt("ScreenHeight");

Klasa PlayerPrefs do każdej metody Set dodaje jej odpowiednik typu Get (istnieją
więc pary GetInt i SetInt, GetFloat i SetFloat oraz GetString i SetString). W sumie daje
to pełny zestaw funkcji zapisu i odczytu danych. Same polecenia są, jak widać, bardzo
proste, ale w związku z tym rodzą się pytania:
■ Gdzie dane są fizycznie zapisywane?
■ Co się stanie, gdy na tym samym komputerze dwie różne gry będą zapisywały dane do
rekordów o tych samych nazwach i z tych samych rekordów będą je odczytywały?
Co się stanie np. wtedy, gdy obie gry zapiszą różne wartości w rekordzie ScreenWidth?
Czy wystąpi między nimi konflikt, czy po prostu nowsza wartość zastąpi starszą?
Przyjrzyjmy się tym kwestiom nieco bliżej.

Preferencje gracza — ciąg dalszy


Klasa PlayerPrefs jest z założenia klasą abstrakcyjną. Skoro ma działać na różnych
platformach i być maksymalnie intuicyjna, to musi ukrywać przed użytkownikiem
wszystkie operacje niskiego poziomu specyficzne dla poszczególnych systemów. Jako
twórca gier otrzymujesz więc spójny i uniwersalny interfejs dostępowy do bazy danych —
taki, który działa na wszystkich obsługiwanych platformach. Działanie to jest jednak
trochę różne na poszczególnych platformach. W zależności od systemu operacyjnego
zmieniają się miejsce i sposób zapisu danych. Szczegółowo jest to opisane w internetowej
dokumentacji programu Unity pod hasłem PlayerPrefs, natomiast my skupimy się jedynie
na praktycznych konsekwencjach wspomnianych różnic.

Uwa ga
Więcej informacji na temat klasy PlayerPrefs można znaleźć w dokumentacji programu Unity zamiesz-
czonej pod adresem: https://docs.unity3d.com/Documentation/ScriptReference/PlayerPrefs.html.

Przede wszystkim, zanim się przystąpi do tworzenia gry, warto w programie Unity wpi-
sać jej tytuł oraz nazwę firmy, ponieważ klasa PlayerPrefs używa tych informacji pod-
czas zapisywania danych. Po prostu wybierz polecenie Edit/Project Settings/Player (edycja/
ustawienia projektu/gracz) — rysunek 8.1 — i w panelu Inspector (inspektor) wypełnij
pola Company Name (nazwa firmy) oraz Product Name (nazwa produktu). Jeśli pozo-
stawisz w tych polach wartości domyślne, firma otrzyma nazwę DefaultCompany (firma
domyślna), a gra zostanie zatytułowana source (źródło).
Wybieranie danych trwałych 239

Rysunek 8.1. Ustalanie nazwy firmy i tytułu gry w programie Unity


Źródło: Unity Technologies.

W zależności od systemu operacyjnego baza danych PlayerPrefs jest zapisywana w na-


stępujących lokalizacjach:
■ Na platformach Windows jest to rejestr systemowy. Dane trafiają tam do klucza HKCU\
Software\[nazwafirmy]\[nazwaproduktu]. (Wartości [nazwafirmy] i [nazwaproduktu]
zostaną zastąpione zawartością odpowiednich pól z panelu Inspector). Informacje
na temat odczytywania i modyfikowania zawartości rejestru wykraczają poza ramy
tej książki. Więcej szczegółów na temat rejestru w systemie Windows można znaleźć
pod adresem: http://windows.microsoft.com/en-gb/windows-vista/what-is-the-registry.
■ W systemach Mac preferencje gracza można znaleźć w folderze Library\Preferences
jako plik o nazwie unity.[nazwafirmy].[nazwaproduktu].plist. (Wartości [nazwafirmy]
i [nazwaproduktu] zostaną zastąpione zawartością odpowiednich pól z panelu
Inspector).
■ W Linuksie dane składające się na preferencje gracza są umieszczane w folderze
/.configunity3d [nazwafirmy]/[nazwaproduktu]. (I tu też wartości [nazwafirmy]
i [nazwaproduktu] zostaną zastąpione zawartością odpowiednich pól z panelu
Inspector).

Wybieranie danych trwałych


PlayerPrefs jest wygodną i użyteczną klasą interfejsu programistycznego, która robi
dokładnie to, na co wskazuje jej nazwa: obsługuje zapis i odczyt preferencji gracza.
Zazwyczaj jednak trzeba zachowywać też i inne dane. Muszą przecież być zapamięty-
wane kompletne stany gry, czyli położenia wrogów, położenie głównego bohatera, jego
stan zdrowia, stan zdrowia wrogów, zebrane sztuki broni, status drzwi (czy są otwarte,
czy zamknięte), status szuflad itp. Można oczywiście zapisywać te wszystkie dane, uży-
wając klasy PlayerPrefs i wywołując odpowiednią liczbę razy metody Set i Get, ale mo-
głoby to spowodować nadmierne rozbudowanie plików konfiguracyjnych lub rejestru,
240 Rozdział 8  Zapisywanie stanu gry a trwałość danych

a nawet wolniejsze działanie systemu. Krótko mówiąc: zastosowanie klasy PlayerPrefs


do zapisu dużych ilości danych nie jest rozwiązaniem optymalnym. Znacznie lepsze
może być użycie plików XML i właśnie tym zajmiemy się w następnym podrozdziale.

Pliki XML — a może JSON lub binarne


Pisanie skryptów C# w Unity polega w dużej mierze na pracy w środowisku programi-
stycznym typu open source o nazwie Mono, które z kolei opiera się na microsoftowej
platformie programistycznej .NET. Mono jest darmową i uniwersalną implementacją
tej platformy proponującą podobne funkcje i klasy. W naturalny sposób obsługuje pliki
w tekstowym formacie XML, który stanowi chyba najczęściej stosowaną metodę zapisu
danych w produkowanych obecnie grach. Mono udostępnia kilka metod korzystania
z plików XML, ale tym razem skupimy się na metodzie zwanej serializacją danych (data
serialization). Przykład zapisu stanu gry zrealizowany w ten właśnie sposób jest przed-
stawiony w listingu 8.3.

Listing 8.3. Przykład zapisu stanu gry w pliku XML


<GameData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Enemies>
<DataEnemy>
<PosRotScale>
<X>1.94054472</X>
<Y>0.019997187</Y>
<Z>-8.58917</Z>
<RotX>0</RotX>
<RotY>129.9697</RotY>
<RotZ>0</RotZ>
<ScaleX>1</ScaleX>
<ScaleY>1</ScaleY>
<ScaleZ>1</ScaleZ>
</PosRotScale>
<EnemyID>3</EnemyID>
<Health>100</Health>
</DataEnemy>
</Enemies>
<Player>
<PosRotScale>
<X>12.1057281</X>
<Y>1.05</Y>
<Z>-17.1096153</Z>
<RotX>0</RotX>
<RotY>39.75003</RotY>
<RotZ>0</RotZ>
<ScaleX>1</ScaleX>
<ScaleY>1</ScaleY>
<ScaleZ>1</ScaleZ>
</PosRotScale>
<CollectedCash>200</CollectedCash>
Pliki XML — a może JSON lub binarne 241

<CollectedGun>true</CollectedGun>
<Health>50</Health>
</Player>
</GameData>

Uwa ga
O platformie programistycznej Mono dowiesz się więcej ze strony: http://www.mono-project.com/Main_Page.

Zanim przejdziemy do bardziej szczegółowego omówienia plików XML, warto wspo-


mnieć o jeszcze dwóch innych formatach, których można by tutaj użyć. Poniżej podaję
ich krótkie opisy wraz z uzasadnieniami, dlaczego je odrzuciłem. Oczywiście powody
te mogą się okazać nieuzasadnione w innych projektach. Krótko mówiąc: do każdego
przypadku trzeba podchodzić indywidualnie.

Pliki JSON
Format JavaScript Object Notation (JSON), podobnie jak XML, ma charakter tekstowy,
co oznacza, że po otwarciu takiego pliku można łatwo przeczytać jego zawartość. Jest to
jednak format znacznie uproszczony w porównaniu z XML-em. Pod wieloma wzglę-
dami świetnie nadaje się do zapisu stanów gry, ale niestety Unity nie ma wbudowanej
jego obsługi i nie jest też obsługiwany przez środowisko programistyczne Mono. Istnieją
wprawdzie dodatki, które problem obsługi tego formatu rozwiązują, ale nie są to stałe
składniki pakietu Unity, a ponieważ przyjąłem zasadę, że będę opisywał tylko te na-
rzędzia, które są na stałe wbudowane w Unity, muszę format JSON pominąć.

Uwa ga
Więcej informacji na temat możliwości stosowania formatu JSON w Unity znajdziesz pod adresem:
http://wiki.unity3d.com/index.php/SimpleJSON.

Pliki binarne
W odniesieniu do plików pojęcie binarny oznacza każdy plik, który nie jest tekstowy.
Pliki tego typu po otwarciu w zwykłym edytorze tekstowym wyglądają raczej bezsen-
sownie (rysunek 8.2), ale właśnie to czyni je bardzo zdatnymi do zapisu stanów gry,
ponieważ niemożność odszyfrowania ich zawartości znakomicie utrudnia graczom
oszukiwanie przez manipulowanie zapisami. Mono ma wbudowaną obsługę takich
plików, a służy do tego klasa binaryFormatter. Na razie pozostanę jednak przy formacie
XML, ponieważ w trakcie tworzenia gry tekstowej zapisy jej stanów są bardzo pożądane
jako pomoc w debugowaniu i dopracowywaniu finalnej wersji. Dzięki temu, że zapisane
stany gry dają się łatwo odczytać, można szybko zweryfikować ich spójność z głównym
kodem. Można też bez problemu sprawdzić, jak będą wyglądały rozmaite scenerie gry,
bo przecież wystarczy odpowiednio zmodyfikować zapis jej stanu, aby szybko przejść
do dowolnego etapu.
242 Rozdział 8  Zapisywanie stanu gry a trwałość danych

Rysunek 8.2. Plik binarny otwarty w zwykłym edytorze tekstowym


Źródło: Notepad++.

Serializacja klasy
Platforma Mono oferuje dwie główne metody zapisu danych trwałych w plikach XML.
■ Zapis ręczny. Metoda ta polega na tworzeniu węzłów i przeprowadzaniu analizy
składniowej zapisywanych danych. Mono oferuje kilka klas ułatwiających wykonanie
tych zadań. Między innymi są tam klasy XmlDocument i XmlReader, które służą do zapi-
sywania i odczytywania plików XML węzeł po węźle. Stosowanie ich oznacza ko-
nieczność tworzenia nowego węzła dla każdej zapisywanej wartości, co może być
tak samo żmudne jak tworzenie rekordów w przypadku stosowania klasy Player
Prefs. Przy dużej liczbie zapisywanych danych może też prowadzić do nadmiernego
wydłużenia kodu.

Uwa ga
Więcej informacji na temat klasy XmlDocument znajdziesz pod adresem:
http://msdn.microsoft.com/en-us/library/system.xml.xmldocument%28v=vs.110%29.aspx.

■ Serializacja. Serializacja polega na zapisywaniu całych obiektów (w sensie struktur


programowych) jako strumieni bajtów. Wygenerowany w ten sposób plik jest tak
zorganizowany, że przy jego odczycie następuje odtworzenie zapisanych wcześniej
obiektów. Bez stosowania serializacji programista musi sam przeszukiwać klasy
i obiekty, aby wybrać te dane, które mają być zapisane. Natomiast gdy stosuje se-
rializację, po prostu kieruje do pliku całą klasę. Są pewne ograniczenia, ponieważ
nie wszystkie typy danych można w ten sposób zapisać, ale jest to problem, który
daje się łatwo rozwiązać. W następnym podrozdziale pokażę, jak to się robi.
Przygotowanie danych do serializacji 243

Przygotowanie danych do serializacji


Aby zobaczyć, jak w praktyce wygląda zapisywanie stanu gry, rozważmy prosty przy-
kład gry FPS w stylu Duke Nukem czy Doom, w której obok postaci gracza występują
także wrogowie. Zapiszmy transformacje wrogów (położenie, orientację i skalę) obec-
nych w scenie, a także niektóre istotne dane dotyczące gracza, np. jego transformacje.
Zapisanie takich danych pozwoli później na odtworzenie położenia wszystkich postaci.
Aby zrobić to metodą serializacji, trzeba najpierw utworzyć dla tych danych dodatkowe
klasy, których typ musi być zmieniony na potrzeby serializacji. Klasy te mogą zawierać
tylko podstawowe typy danych wbudowane w język C#, a nie pochodzące z API czy
z jakiejś biblioteki.
Przykładowo: w Unity wektory są instancjami specyficznej dla tego środowiska klasy
Vector3, a tak naprawdę są to tylko powiązane ze sobą trójki liczb zmiennoprzecin-
kowych określających składowe wektorów względem osi X, Y i Z. Podobnie orientacje,
czyli obroty, są w Unity reprezentowane przez czteroskładnikowe struktury zwane
kwaternionami, a w gruncie rzeczy to samo można zapisać za pomocą trójki liczb
zmiennoprzecinkowych określających kąty obrotu względem trzech osi układu odnie-
sienia. A zatem wszystkie informacje dotyczące transformacji obiektu można wyrazić za
pomocą jedynie fundamentalnych typów danych. I właśnie dla takich danych utworzymy
nową klasę (listing 8.4).

Listing 8.4. Klasa danych transformacyjnych nadająca się do serializacji


public struct DataTransform
{
public float X;
public float Y;
public float Z;
public float RotX;
public float RotY;
public float RotZ;
public float ScaleX;
public float ScaleY;
public float ScaleZ;
}

Uwa ga
W listingu 8.4 zastosowano typ danych float (zmiennoprzecinkowe), ale nie jest to jedyny typ dozwolony
w serializacji. Dopuszczalne są również typy bool (dane logiczne), int (liczby całkowite), string (dane
tekstowe) i list (lista). Więcej informacji na temat typów danych i klas zdatnych do serializacji znaj-
dziesz pod adresem: http://msdn.microsoft.com/en-us/library/ms731923%28v=vs.110%29.aspx.

Spójrz na listing 8.5. Prezentuje on niemal całą zawartość pliku źródłowego (SaveState.cs)
zawierającego przykładowy zestaw klas służących do obsługi serializacji danych opi-
sujących stan gry — są to dane dotyczące postaci gracza i wrogów. Dodatkowe objaśnie-
nia umieściłem za listingiem.
244 Rozdział 8  Zapisywanie stanu gry a trwałość danych

Listing 8.5. Przykładowy zestaw klas C# potrzebnych do zapisu stanu gry metodą serializacji
//Zapisuje i odczytuje stan gry, korzystając z formatu XML.
//-----------------------------------------------
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
//-----------------------------------------------
public class SaveState
{
//Zapisz dane gry.
[XmlRoot("GameData")]
//-----------------------------------------------
//Dane transformacyjne obiektu znajdującego się w scenie.
[System.Serializable]
public struct DataTransform
{
public float X;
public float Y;
public float Z;
public float RotX;
public float RotY;
public float RotZ;
public float ScaleX;
public float ScaleY;
public float ScaleZ;
}
//-----------------------------------------------
//Ogólnie dostępna klasa dla postaci wroga.
public class EnemyData
{
//Dane transformacyjne wroga.
public DataTransform Transformation;

//Czy wróg jest uzbrojony?


public bool Armed = false;
}
//-----------------------------------------------
//Ogólnie dostępna klasa dla postaci gracza.
public class PlayerData
{
//Dane transformacyjne gracza.
public DataTransform PlayerTransform;
}
//-----------------------------------------------
//Klasa przechowująca dane zasadnicze.
public class GameData
{
//Dane dotyczące wrogów.
public List<EnemyData> Enemies = new List<EnemyData>();

//Dane dotyczące gracza.


Przesyłanie danych do pliku XML 245

public PlayerData PD = new PlayerData();


}
//-----------------------------------------------
//Składnik klasy GameData (dane gry).
public GameData GD = new GameData();
}
//-----------------------------------------------

Klasa SaveState (zapis stanu) zawiera pełny zestaw klas służących do przechowywania
danych mających kluczowe znaczenie dla zapisu i przywracania stanu gry. Klasy te są
zebrane w składniku GD (instancji klasy GameData).
Klasa GameData (dane gry) zawiera składnik PlayerData (dane gracza) z transforma-
cjami gracza i listę wrogów. Wrogowie tworzą strukturę typu lista, która w trakcie
trwania gry może się dynamicznie wydłużać lub skracać, aby pomieścić dokładnie tyle
elementów, ile potrzeba do zapisania wszystkich wrogów.

Przesyłanie danych do pliku XML


Opisana w poprzednim podrozdziale klasa SaveState zawiera wszystko, co na pozio-
mie klasy jest potrzebne do przechowywania informacji na temat położenia postaci
gracza i wrogów. Wszystkie tego typu dane są zebrane w składniku GameData i właści-
wie on sam wystarczyłby jako źródło danych definiujących stan gry. Na razie klasa
SaveState nie ma jeszcze składnika, który by te dane przeniósł do pliku. Aby ten brak
nadrobić, dodamy jej metodę Save() (zapisz). Argumentem tej metody będzie pełna
ścieżka dostępu do pliku XML, do którego zostanie skierowany strumień danych. Szcze-
góły implementacyjne metody Save() są pokazane w listingu 8.6.

Listing 8.6. Zapisywanie danych do pliku


//Zapisuje dane gry do pliku XML.
public void Save(string FileName = "GameData.xml")
{
//Teraz zapisz dane gry.
XmlSerializer Serializer = new XmlSerializer(typeof(GameData));
FileStream Stream = new FileStream(FileName, FileMode.Create);
Serializer.Serialize(Stream, GD);
Stream.Close();
}

Najpierw metoda Save()przyjmuje argument w postaci łańcucha znakowego o nazwie


FileName (nazwa pliku), który wskazuje, gdzie w lokalnym systemie pamięci masowej
powinien być zapisany plik XML. Następnie korzysta ona z klasy XmlSerializer (seriali-
zator XML), aby utworzyć obiekt typu FileStream (strumień plikowy) odpowiedzialny
za przesyłanie danych do pliku. Cała operacja kończy się serializacją obiektu GameData
i zamknięciem strumienia przesyłowego. Żeby się jednak wszystko udało, trzeba spełnić
246 Rozdział 8  Zapisywanie stanu gry a trwałość danych

jeden podstawowy warunek — argument metody Save()musi reprezentować prawidło-


wą ścieżkę dostępu do miejsca zapisu pliku. Pod koniec rozdziału pokażę, jak należy
ten argument konstruować, aby działał na większości platform komputerowych.

Odczytywanie danych z pliku XML


Listing 8.6 pokazuje, jak można wykonać serializację obiektu GameData i zapisać go w pli-
ku XML, używając klasy XmlSerializer. A jak teraz przywrócić zapisane w ten sposób
dane? Mówiąc inaczej: jak przeprowadzić ich deserializację? Odpowiedzią na to pytanie
jest metoda Load()(wczytaj) z listingu 8.7.

Listing 8.7. Przywracanie danych zapisanych w pliku XML


//Wczytuje dane z pliku XML.
public void Load(string FileName = "GameData.xml")
{
XmlSerializer Serializer = new XmlSerializer(typeof(GameData));
FileStream Stream = new FileStream(FileName, FileMode.Open);
GD = Serializer.Deserialize(Stream) as GameData;
Stream.Close();
}

Jak widać, metoda Load() jest bardzo podobna do metody Save(). Z formalnego punktu
widzenia różnią się one tylko tym, że jedna wykorzystuje funkcję Serialize(), a druga
robi użytek z funkcji Deserialize(). To właśnie za pomocą funkcji Deserialize()metoda
Load() odtwarza instancję klasy GameData — tworzy ją i inicjalizuje na podstawie danych
zapisanych w pliku XML. Pełną definicję klasy SaveState z dodanymi już metodami
Save()i Load() przedstawia listing 8.8.

Listing 8.8. Kompletna klasa SaveState


//Zapisuje i odczytuje stan gry, korzystając z formatu XML.
//-----------------------------------------------
//Nie zapomnij dołączyć wszystkich klas potrzebnych do zapisania stanu gry.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
//-----------------------------------------------
//Zapisem i odczytem danych zajmie się klasa SaveState.
public class SaveState
{
//Zapisz dane gry.
[XmlRoot("GameData")]
//-----------------------------------------------
//Dane transformacyjne obiektu znajdującego się w scenie.
[System.Serializable]
public struct DataTransform
Odczytywanie danych z pliku XML 247

{
public float X;
public float Y;
public float Z;
public float RotX;
public float RotY;
public float RotZ;
public float ScaleX;
public float ScaleY;
public float ScaleZ;
}
//-----------------------------------------------
//Ogólnie dostępna klasa dla postaci wroga
//ma przechowywać dane dotyczące postaci wroga, które mają być zapisane w pliku XML.
public class EnemyData
{
//Dane transformacyjne wroga (położenie, obrót i skala).
public DataTransform Transformation;

//Czy wróg jest uzbrojony?(O ile to ma sens w danej grze).


public bool Armed = false;
}
//-----------------------------------------------
//Ogólnie dostępna klasa dla postaci gracza.
public class PlayerData
{
//Dane transformacyjne gracza.
public DataTransform PlayerTransform;
}
//-----------------------------------------------
//Klasa przechowująca dane zasadnicze.
public class GameData
{
//Dane dotyczące wrogów.
public List<EnemyData> Enemies = new List<EnemyData>();

//Dane dotyczące głównego gracza.


//Instancja przechowująca wszystkie dane dotyczące gracza (położenie, obroty, skala itp.).
public PlayerData PD = new PlayerData();
}
//-----------------------------------------------

//Składnik klasy GameData (dane gry).


//Główna struktura danych zawiera wszystkie dane przeznaczone do zapisu w pliku XML.
public GameData GD = new GameData();
//-----------------------------------------------
//Zapisuje dane gry do pliku XML.
public void Save(string FileName = "GameData.xml")
{
//Teraz zapisz dane gry.
XmlSerializer Serializer = new XmlSerializer(typeof(GameData));
FileStream Stream = new FileStream(FileName, FileMode.Create);
Serializer.Serialize(Stream, GD);
Stream.Close();
}
//-----------------------------------------------
248 Rozdział 8  Zapisywanie stanu gry a trwałość danych

//Wczytuje dane z pliku XML.


public void Load(string FileName = "GameData.xml")
{
XmlSerializer Serializer = new XmlSerializer(typeof(GameData));
//Otwiera plik i przesyła jego zawartość (w formie strumienia danych) do obiektu GameData.
FileStream Stream = new FileStream(FileName, FileMode.Open);
GD = Serializer.Deserialize(Stream) as GameData;
Stream.Close();
}
//-----------------------------------------------
}
//-----------------------------------------------

Uwa ga
Kompletna klasa SaveState jest zamieszczona w materiałach powiązanych z książką. Szukaj jej w folderze
Rozdział08.

Dodatkowe uwagi na temat klasy SaveState


Teraz klasa SaveState zawiera już wszystko, co jest potrzebne do zapisania stanu gry.
Gdy gra utworzy instancję tej klasy i wypełni składnik GameData odpowiednimi warto-
ściami, będzie on gotowy do serializacji. Proces ten zostanie przeprowadzony, gdy tylko
wywołamy metodę Save(). Potem, żeby wczytać zapisany stan gry, wystarczy wywołać
metodę Load(). Trzeba jednak obu tym metodom podać ścieżkę do miejsca, w którym
plik ma być zapisany lub już się znajduje. Jak ustalić tę ścieżkę?
Na szczęście Unity potrafi wykonać to zadanie za nas i automatycznie wygenerować
właściwy łańcuch znakowy. Spójrz na listing 8.9, który przedstawia funkcję Update()
(aktualizacja). Za każdym razem, gdy użytkownik wciśnie klawisz S, funkcja ta zapisze
stan gry (przy użyciu klasy SaveState), a przywróci go, gdy użytkownik wciśnie klawisz L.
W tym listingu klasa SaveState jest reprezentowana przez obiekt SS.

Listing 8.9. Zapisywanie i wczytywanie stanów gry


//Aktualizacja jest wywoływana raz na klatkę.
void Update()
{
//Jeśli wciśnięto S, zapisz stan gry.
if(Input.GetKeyDown(KeyCode.S))
{
SS.Save(Application.persistentDataPath + "/GameState.xml");
}
//Jeśli wciśnięto L, wczytaj stan gry.
if(Input.GetKeyDown(KeyCode.L))
{
SS.Load(Application.persistentDataPath + "/GameState.xml");
}
}
Podsumowanie 249

Z listingu 8.9 wynika, że wygenerowany łańcuch znajduje się w zmiennej Application.


persistentDataPath. Ścieżka będzie się zmieniała w zależności od komputera, sys-
temu operacyjnego i tego, jak ten system jest skonfigurowany, ale zawsze będzie wska-
zywała miejsce w lokalnym systemie pamięci masowej, gdzie informacje o stanie gry
mogą być bezpiecznie zapisane.
Gratulacje! Własnoręcznie zbudowałeś system zapisu i odczytu danych. W materiałach
towarzyszących książce (w folderze Rozdział08) znajduje się przykładowy projekt, w któ-
rym zastosowano klasę SaveState do zapisywania i odczytywania danych. Zachęcam
do przeanalizowania tego projektu.

Uwa ga
Więcej informacji na temat zmiennej persistentDataPath znajdziesz w internetowej dokumenta-
cji programu Unity na stronie: https://docs.unity3d.com/Documentation/ScriptReference/Application-
persistentDataPath.html.

Podsumowanie
W tym rozdziale omówiłem zapisywanie i odczytywanie stanów gry. Przedstawiłem dwie
zasadnicze metody postępowania. Pierwsza polega na zastosowaniu klasy PlayerPrefs,
a druga wymaga użycia klasy XmlSerializer. W obu przypadkach dane były zapisywane
w pliku XML, którego zawartość można łatwo odczytać i modyfikować za pomocą zwy-
kłego edytora tekstu. Obie metody pozwalają na zapisanie właściwie każdego rodzaju
danych potrzebnych do zdefiniowania stanu gry.
250 Rozdział 8  Zapisywanie stanu gry a trwałość danych
R OZ DZ I AŁ 9

W YPALANIE

Sukces zależy od wcześniejszego przygotowania, a bez takiego przygotowania


klęska jest pewna.
— Konfucjusz

Po przeczytaniu tego rozdziału powinieneś:


■ wiedzieć, czym jest wypalanie;
■ umieć wypalać tekstury i mapy okluzji otoczenia w Blenderze;
■ umieć komponować wypalone tekstury w GIMP-ie;
■ rozumieć mapowanie światła w Unity;
■ umieć obchodzić się z próbnikami światła w Unity.
Z jednej strony, autorzy gier ciągle szukają nowych sposobów na przełamywanie twór-
czych barier, kreowanie coraz wspanialszych efektów i sprawianie, by gry stawały się
jeszcze bardziej realistyczne i wciągające. Z drugiej strony, muszą ciągle myśleć o kwe-
stiach związanych z optymalizacją i wydajnością. Muszą być świadomi ograniczeń
sprzętowych i konfrontować swoje kreatywne wizje z możliwościami używanego po-
wszechnie sprzętu. Istnienie tych dwóch antagonistycznych skrajności — przełamywania
barier i respektowania ograniczeń — oznacza, że twórca gry musi sporo czasu poświęcić
na szukanie właściwej równowagi między tym, co chciałby uzyskać, a tym, co większość
potencjalnych użytkowników będzie w stanie uruchomić na swoim sprzęcie. Jednym
ze sposobów godzenia tych dwóch skrajności jest stosowanie rozmaitych technik
optymalizacyjnych, a jedną z nich jest tzw. wypalanie (baking). W tym rozdziale sku-
pimy się na rozmaitych formach wypalania zarówno w Blenderze i Unity, jak i poza
tymi programami.

251
252 Rozdział 9  Wypalanie

Czym jest wypalanie?


W trakcie trwania gry komputer ciągle wykonuje mnóstwo rozmaitych obliczeń. Musi
przecież na bieżąco wyznaczać położenie wrogów i innych postaci, określać parametry
efektów świetlnych, ustalać poziom dźwięku w zależności od tego, gdzie znajduje się po-
stać gracza itp. Danych do przetworzenia jest tak wiele, że nie sposób je tutaj wszystkie
wymienić.
Jeśli tylko uda Ci się uwolnić komputer od przetwarzania jakichś danych w czasie rze-
czywistym, gra zyska na wydajności, bo komputer będzie miał więcej czasu na pozostałe
obliczenia. A zatem jeśli tylko możesz wykonać jakieś obliczenia wcześniej i umieścić
w grze ich gotowe wyniki, zrób to, aby komputer nie musiał się tym zajmować podczas
działania gry. Proces przygotowywania takich danych nosi nazwę wypalania, a same
dane określane są jako wypalone (baked data).
W tym rozdziale omówię trzy rodzaje wypalania danych w Unity i Blenderze:
■ wypalanie oświetlenia statycznego,
■ wypalanie oświetlenia dynamicznego,
■ wypalanie nawigacji.

Wypalanie oświetlenia statycznego


Wypalanie oświetlenia polega na wcześniejszym wykonaniu obliczeń związanych z efek-
tami świetlnymi. Wypalanie takie przybiera różne formy, ale niemal zawsze sprowadza
się do wykonania odpowiednich tekstur z zakodowanymi poziomami światła. Najbar-
dziej rozpowszechnioną techniką jest mapowanie światła (lightmapping). Polega ona
na obliczeniu oświetlenia dla wszystkich obiektów statycznych (nieruchomych) i zapi-
saniu rezultatu w formie specjalnych tekstur zwanych mapami światła (lightmaps).
Często zawierają one zarówno oświetlenie bezpośrednie, jak i pośrednie, a także cienie.
W trakcie działania gry tekstury te są nakładane na siatki obiektów i mieszane z ich
zwykłymi teksturami, aby wywołać złudzenie rzeczywistego oświetlenia światłem po-
chodzącym ze źródeł umieszczonych w scenie na stałe. Przykład sceny z nałożonymi
mapami światła jest pokazany na rysunku 9.1.
Nieco inną techniką jest wypalanie oświetlenia (z okluzją otoczenia) w standardowych
teksturach za pomocą Blendera i następnie importowanie do Unity siatek już oświe-
tlonych — system mapowania światła w Unity jest wtedy całkowicie pomijany. Do-
kładniejszy opis tej metody znajdziesz w dalszej części rozdziału.

Wypalanie oświetlenia dynamicznego


Mapowanie światła — i w ogóle oświetlenie wypalane w teksturach — napotyka istot-
ne ograniczenia, jeśli chodzi o oświetlanie obiektów dynamicznych (czyli takich, które
w trakcie działania gry zmieniają swoje położenie). Wcześniejsze obliczenie i wypalenie
Czym jest wypalanie? 253

Rysunek 9.1. Scena z nałożonymi mapami światła w Unity (plik z tą sceną znajduje się
w materiałach powiązanych z książką, w folderze Rozdział09)
Źródło: Unity Technologies.

oświetlenia jest w takim przypadku po prostu niemożliwe, ponieważ nie da się z góry
określić, gdzie i kiedy dany obiekt będzie się znajdował. Oświetlenie siatki, która jest
w ruchu, może się zmieniać na nieskończenie wiele sposobów, gdyż ciągle zmienia się jej
usytuowanie względem źródeł światła. Dlatego mapowanie światła stosuje się na ogół
tylko w odniesieniu do obiektów nieruchomych.
Obliczenia związane z oświetleniem siatek dynamicznych często przeprowadza się w cza-
sie rzeczywistym, bo wtedy efekty są najdokładniejsze i najbardziej realistyczne. Takie
rozwiązanie jest jednak zaprzeczeniem optymalizacji. Dlatego w Unity wprowadzono
możliwość stosowania techniki pośredniej, polegającej na połowicznym wypalaniu
oświetlenia dla obiektów dynamicznych (rysunek 9.2). Jej istotą jest stosowanie tzw.
próbników światła (light probes).

Wypalanie nawigacji
Wypalanie wiąże się najczęściej z oświetleniem i teksturami, ale bywa stosowane także
przy opracowywaniu innych elementów gry. Może to być np. wyznaczanie tras i nawiga-
cja. Postacie inne niż postać gracza (non-player characters — NPCs) powinny przecież
poruszać się w sposób inteligentny. Muszą „wiedzieć”, dokąd zmierzają, i po drodze
omijać wszelkie przeszkody. Muszą przechodzić przez drzwi, a nie przez ściany. Wy-
znaczanie właściwych tras może jednak wymagać wielu obliczeń — szczególnie w roz-
budowanym środowisku i przy dużej liczbie postaci. Jednym z rozwiązań mogących
ułatwić i przyspieszyć ten proces jest wypalenie, albo inaczej: wygenerowanie specjalnej
254 Rozdział 9  Wypalanie

Rysunek 9.2. Próbniki światła umożliwiają symulację oświetlenia dynamicznego


Źródło: Unity Technologies.

siatki reprezentującej możliwe do przejścia obszary środowiska (rysunek 9.3). Jest ona
powszechnie nazywana siatką nawigacyjną (navmesh) i może w znacznym stopniu
przyspieszyć obliczenia nawigacyjne. Jak taka siatka działa w praktyce, zobaczysz w dal-
szej części rozdziału.

Rysunek 9.3. Siatka nawigacyjna ułatwia wyznaczanie możliwych do przejścia tras


Źródło: Unity Technologies.
Przygotowanie mapowania światła w Unity 255

Przygotowanie mapowania światła w Unity


Wróćmy do pierwszej formy wypalania w Unity, czyli do mapowania światła, albo ina-
czej: do wypalania oświetlenia statycznych siatek środowiskowych, żeby w trakcie gry
środowisko wyglądało na oświetlone przez istniejące w scenie źródła światła. Zakładam,
że już masz jakieś środowisko zmontowane wcześniej w Unity. Jeśli nie masz, zajrzyj
do rozdziału 3. Tam znajdziesz wskazówki, które pozwolą Ci samodzielnie zbudować
środowisko metodą modułową. W ostateczności, jeśli nie chcesz robić tego teraz sam,
możesz wykorzystać gotowe moduły środowiska zapisane w powiązanych z książką plikach
z folderu Rozdział09/LightMapStart.
Rysunek 9.4 przedstawia utworzoną przeze mnie scenę, którą zamieściłem w plikach
dołączonych do książki. Są tu już lampy, ale mapowanie światła jeszcze nie zostało prze-
prowadzone. W tej chwili oświetlenie jest wyliczane na bieżąco (w czasie rzeczywistym),
co nie jest rozwiązaniem optymalnym, zwłaszcza że żadna z obecnych tu siatek nigdy
podczas gry nie będzie zmieniała pozycji. Zauważ też, że nie ma tu efektów oświetlenia
pośredniego i cieni, a cała scena jest dość ciemna. To, że jest ciemniej niż powinno,
może być nawet korzystne, ponieważ mapowanie światła prawie zawsze rozjaśnia scenę
przez dodanie oświetlenia pośredniego.

Rysunek 9.4. Scena gotowa do mapowania światła


Źródło: Unity Technologies.

Zanim przejdziemy dalej, wyłącz ogólne oświetlenie sceny (jeśli jeszcze nie jest wyłą-
czone). Domyślnie każda scena w Unity jest oświetlana ogólnym światłem otaczają-
cym, które jest stosunkowo słabe, rozchodzi się we wszystkich kierunkach i wszędzie
ma takie samo natężenie. Jest to podstawowe oświetlenie zapewniające widoczność
obiektów nawet wtedy, gdy nie wstawiliśmy jeszcze żadnego źródła światła. Oświetlenie
256 Rozdział 9  Wypalanie

takie przydaje się podczas budowania sceny, ale po wstawieniu wszystkich zaplano-
wanych źródeł światła należy to oświetlenie wyłączyć, ponieważ spłyca głębię prze-
strzenną, a to jest na ogół niepożądane. Aby wyłączyć światło otaczające, wybierz po-
lecenie Edit/Render Settings (edycja/ustawienia renderingu) i w panelu Inspector ustaw
w polu Ambient Light (światło otaczające) kolor czarny. Czerń oznacza brak światła
(ciemność), więc ustawienie takiego koloru jest równoznaczne z całkowitym wyłącze-
niem światła (rysunek 9.5).

Rysunek 9.5. Wyłączanie światła otaczającego


Źródło: Unity Technologies.

Następnie zaznacz wszystkie siatki środowiska i przypisz im status statycznych, włą-


czając w panelu Inspector opcję Static (statyczny) — rysunek 9.6. Mapowanie światła
ma zastosowanie tylko w odniesieniu do siatek statycznych (nieruchomych), takich
jak ściany, podłogi i wszelkie stałe rekwizyty. Pamiętaj: statyczność można przypisać
wielu obiektom jednocześnie!

Rysunek 9.6. W ramach przygotowań do mapowania światła oznacz odpowiednie


obiekty jako statyczne
Źródło: Unity Technologies.
Mapowanie światła. Rozdzielczość mapy światła 257

Mapowanie światła. Rozdzielczość mapy światła


Rozdzielczość mapy światła decyduje o szczegółowości wygenerowanej tekstury za-
wierającej zapis oświetlenia sceny. Więcej informacji na ten temat podam przy obja-
śnianiu kolejnych etapów poniższej procedury. Wykonaj następujące czynności:
1. Wybierz polecenie Window/Lightmapping (okno/mapowanie światła), aby otworzyć
edytor Lightmapping. Edytor ten zwykle otwiera się jako niezależne okno, ale ja
wolę go mieć zadokowanego po prawej stronie razem z panelem Inspector, tyle że na
oddzielnej zakładce. Dzięki temu mogę widzieć jednocześnie i ustawienia mapy
światła, i scenę (rysunek 9.7).

Rysunek 9.7. Edytor Lightmapping zadokowany obok okna widokowego


Źródło: Unity Technologies.

2. Kliknij zakładkę Bake (wypalanie) edytora, aby uzyskać dostęp do głównych opcji
mapowania światła (rysunek 9.8). W dolnej części znajduje się jeden z najważniejszych
parametrów tego procesu, a mianowicie Resolution (rozdzielczość). To od jego
wartości zależy, jak duża (w pikselach) i jak szczegółowa będzie wygenerowana
mapa światła.
3. Z parametrem Resolution powiązana jest opcja Show Resolution (pokaż rozdziel-
czość) umieszczona w oknie Lightmap Display (wyświetlanie mapy światła), które
pokazuje się w oknie widokowym, gdy tylko włączony jest edytor Lightmapping.
Jeśli włączysz wspomnianą opcję, na powierzchnię wszystkich ścianek zostanie
nałożona półprzezroczysta szachownica o gęstości zgodnej z gęstością mapy świa-
tła, jaka zostałaby wygenerowana przy bieżących ustawieniach (rysunek 9.9). Każde
pole szachownicy odpowiada jednemu pikselowi mapy światła. Gdy zwiększasz war-
tość parametru Resolution w edytorze Lightmapping, pola szachownicy stają się mniej-
sze, ponieważ przy większej rozdzielczości więcej pikseli (a więc i pól szachownicy)
258 Rozdział 9  Wypalanie

Rysunek 9.8. Rozdzielczość decyduje o rozmiarze tekstury pełniącej funkcję mapy światła
Źródło: Unity Technologies.

musi się zmieścić na tym samym obszarze. Krótko mówiąc: wraz ze wzrostem roz-
dzielczości rośnie liczba pikseli mapy światła, a ona sama staje się bardziej szcze-
gółowa. Wzrost liczby pikseli oznacza jednak większe zapotrzebowanie na pamięć
i większe obciążenie procesora. Trzeba więc szukać kompromisu i ustawiać rozdziel-
czość na najniższym poziomie, przy którym jakość oświetlenia będzie zadowalająca.

Rysunek 9.9. Podgląd rozdzielczości mapy światła


Źródło: Unity Technologies.
Tryb mapowania światła 259

Uwa ga
Rozdzielczość nie jest jedynym parametrem decydującym o rozmiarze wygenerowanej mapy światła.
Wartość tego parametru określa jedynie relację między rozmiarem piksela a globalną jednostką po-
wierzchni. Całkowita liczba pikseli w mapie światła zależy i od rozdzielczości, i od łącznej powierzchni
wszystkich siatek statycznych, a dokładnie: jest równa iloczynowi tych wartości.

Tryb mapowania światła


Drugim ważnym parametrem mapowania światła jest Mode (tryb). Od niego zależy
równowaga między oświetleniem obliczanym w czasie rzeczywistym a oświetleniem
zapisanym w mapie światła. To on decyduje, ile światła podczas gry będzie pochodziło
z bieżących obliczeń, a ile z teksturowej mapy światła. Parametr ten jest też odpowie-
dzialny za mieszanie obu rodzajów oświetlenia.
Jak wynika z rysunku 9.10, parametr ten może przyjmować jedną z trzech wartości.

Rysunek 9.10. Ustalanie trybu mapowania światła


Źródło: Unity Technologies.

■ Single Lightmaps (pojedyncze mapy światła). W tym trybie wszystkie efekty oświe-
tleniowe, włącznie z oświetleniem pośrednim i bezpośrednim, z okluzją otoczenia
i z cieniami, są wypalane w teksturach siatek statycznych. W naszym przykładzie
zastosujemy właśnie ten tryb.
■ Dual Lightmaps (podwójne mapy światła). Po wybraniu tego trybu tworzone są
dwie odmiany teksturowych map światła. Jedna (mapa dalsza) zawiera wszystkie
informacje oświetleniowe, podobnie jak pojedyncza mapa światła. Jest ona nakładana
na siatki, gdy te są oglądane z większej odległości. Gdy kamera przysuwa się bliżej,
miejsce mapy dalszej zajmuje mapa bliższa, która zawiera efekty oświetlenia pośred-
niego i okluzji otoczenia. Nie ma w niej efektów oświetlenia pośredniego, ponieważ
te zostaną wyliczone w czasie rzeczywistym i dopiero wtedy będą mieszane z wy-
260 Rozdział 9  Wypalanie

palonymi efektami oświetleniowymi, aby jeszcze bardziej urealnić ostateczny re-


zultat. Krótko mówiąc: tryb Dual Lightmaps został wprowadzony po to, aby zwięk-
szyć realizm scen, zwłaszcza w grach FPS, gdzie odległość kamery od siatek często
się zmienia.
■ Directional Lightmaps (kierunkowe mapy światła). Jest to jeszcze bardziej wyspe-
cjalizowana odmiana trybu Dual Lightmaps, która pozwala na wypalenie w mapie
światła dodatkowych danych, takich jak mapa normalnych. Właściwości tego trybu
wykraczają jednak poza ramy tej książki i nie będą omawiane.

Uwa ga
Więcej informacji na temat mapowania światła znajdziesz w internetowej dokumentacji programu
Unity (http://docs.unity3d.com/Documentation/Manual/LightmappingInDepth.html).

Uwa ga
Pojęcie oświetlenia bezpośredniego (direct illumination) odnosi się do oświetlenia powstałego
w wyniku padania promieni wyemitowanych przez źródło światła. Promienie te rozchodzą się po liniach
prostych i jeśli na swej drodze trafią na ścianę, podłogę czy inną siatkę, oświetlają ją. Z oświetleniem
pośrednim (indirect illumination) mamy do czynienia wtedy, gdy promienie oświetlające daną powierzchnię
wcześniej odbiły się od innej siatki (lub innych siatek). Oświetlenie bezpośrednie na ogół tworzy jaśniejsze
i bardziej rzucające się w oczy efekty świetlne, a oświetlenie pośrednie pełni raczej funkcję uzupełniającą.

Na potrzeby naszego przykładu wybierzemy tryb Single Lightmaps i wypalimy wszystkie


efekty oświetlenia statycznego w teksturach mapy światła.

Oświetlenie pośrednie i okluzja otoczenia


Jeśli używasz programu Unity w wersji Pro, to masz dostęp do pełnego zakresu funk-
cji związanych z mapowaniem światła, włącznie z wypalaniem efektów oświetlenia po-
średniego i okluzji otoczenia. Jeśli jednak nie masz wersji Pro, to i tak możesz to samo
zrobić, tyle że w Blenderze — będzie o tym mowa w jednym z następnych podroz-
działów. Na razie zakładam, że masz Unity Pro, i w związku z tym pozostaję przy oma-
wianiu wypalania efektów oświetlenia pośredniego oraz okluzji otoczenia za pomocą
funkcji dostępnych w tym programie.
Jak wynika z rysunku 9.11, Unity oferuje kilka różnych ustawień, za pomocą których
można sterować efektami oświetlenia pośredniego.
■ Bounces (odbicia). W tym polu można ustawić maksymalną liczbę odbić, jakim
może ulec promień światła, aby mógł jeszcze oświetlić kolejną powierzchnię. Licz-
ba 1 będzie oznaczała, że promień może się odbić tylko raz — gdy padnie na na-
stępną powierzchnię, oświetli ją, ale już się od niej nie odbije. Liczba 2 zezwoli na
Oświetlenie pośrednie i okluzja otoczenia 261

Rysunek 9.11. Parametry mapowania światła związane z oświetleniem pośrednim


Źródło: Unity Technologies.

maksymalnie dwa odbicia itd. Zmniejszenie tej wartości do 0 spowoduje całkowite


wyłączenie efektów oświetlenia pośredniego, ponieważ zakazane zostaną jakiekol-
wiek odbicia promieni świetlnych. W teorii wyższe wartości dają bardziej reali-
styczne rezultaty, ale dzieje się to kosztem wydłużenia czasu obliczeń. W praktyce
wartości 1 lub 2 są na ogół wystarczające.
■ Sky Light Color (kolor światła firmamentu) i Sky Light Intensity (natężenie światła
firmamentu). Te parametry określają barwę i natężenie światła otaczającego i wszech-
obecnego, które w scenach plenerowych pochodzi od kopuły nieba. W scenach
przedstawiających wnętrza oświetlenie to powinno być raczej wyłączone — należy
wartość parametru Sky Light Intensity ustawić na 0.
■ Bounce Boost (wzmocnienie odbicia). Za pomocą tego suwaka można symulować
większą liczbę odbić bez ponoszenia kosztów (czasu trwania obliczeń) związanych ze
zwiększeniem wartości parametru Bounces. Przydaje się, gdy scena jest zbyt ciemna
i chcielibyśmy ją rozjaśnić przez wzmocnienie oświetlenia pośredniego.
■ Bounce Intensity (intensywność odbicia). Parametr ten działa jak mnożnik i po-
zwala równomiernie zwiększać lub zmniejszać ogólną jasność oświetlenia pośred-
niego. Wartość 1 niczego nie zmienia, wartość 2 zwiększa jasność dwukrotnie,
wartość 0,5 zmniejsza ją o połowę itd. Podobnie jak Bounce Boost, przydaje się do
intensyfikowania lub tonowania oświetlenia pośredniego.
262 Rozdział 9  Wypalanie

■ Final Gather Rays (promienie Final Gather). W tym polu można ustalić całkowitą
liczbę promieni wysyłanych w kierunku sceny w celu ustalenia jej oświetlenia. Im
wyższa będzie ta liczba, tym dokładniejsze będzie oświetlenie. Często jednak wystar-
cza pozostawienie wartości domyślnej.
Pozostałe ustawienia dotyczą m.in. okluzji otoczenia, czyli efektu będącego rezultatem
oświetlenia pośredniego. Gdy światło odbija się od otoczenia, to z oczywistych powo-
dów częściej pada na przestrzenie duże i odsłonięte niż na małe i ciasno osłonięte in-
nymi powierzchniami, np.: w szparach, szczelinach między blisko położonymi obiek-
tami, zakamarkach, kątach utworzonych przez ściany, podłogi i sufity oraz w innych
tego typu miejscach. W rezultacie miejsca te są zacienione, a zjawisko to jest nazywane
cieniem kontaktowym (contact shadow). Okluzja otoczenia (ambient occlusion) jest
sposobem na symulowanie tego zjawiska (rysunek 9.12). Zastosowanie jej pomaga
wzmocnić trójwymiarowość obrazu. Aby ją włączyć, wystarczy za pomocą suwaka Am-
bient Occlusion ustawić jakąkolwiek wartość większą od 0. Im większą wartość ustawisz
(maksymalnie 1), tym efekt będzie mocniejszy (rysunek 9.13).

Rysunek 9.12. Ten sam obiekt z wyłączoną okluzją otoczenia (A) i z włączoną (B).
Okluzja otoczenia symuluje obecność cieni kontaktowych
Źródło: Unity Technologies.

Z suwakiem Ambient Occlusion skojarzone są parametry Max Distance (maksymalna


odległość) i Contrast (kontrast), za pomocą których można dostosować efekt do wła-
snych upodobań. Pierwszy z nich wpływa na rozległość cienia kontaktowego, a drugi
decyduje o jego intensywności. Jeśli chcesz spotęgować efekt cieni kontaktowych, za-
stosuj wyższe wartości tych parametrów.
Wypalanie map światła 263

Rysunek 9.13. Włączanie okluzji otoczenia


Źródło: Unity Technologies.

Wypalanie map światła


Na rysunku 9.14 pokazane są ustawienia, jakie zastosowałem przy wypalaniu mapy
światła w trybie Single Lightmaps. Jeśli już poustawiałeś wszystkie parametry według
własnego uznania, kliknij przycisk Bake Scene (wypal scenę) w dolnej części zakładki
Bake edytora Lightmapping. Spowoduje to uruchomienie specjalnego modułu o nazwie
Beast, który najpierw wyznaczy oświetlenie bezpośrednie i pośrednie wraz z okluzją
otoczenia, a następnie wygeneruje zestaw map światła. Cały ten proces może zająć od
kilku minut do wielu godzin w zależności od: liczby źródeł światła w scenie, rozdzielczo-
ści map światła, powierzchni siatek, parametrów oświetlenia pośredniego, mocy obli-
czeniowej komputera i wielu innych czynników. Gdy się zakończy, scena zostanie
oświetlona za pomocą wygenerowanych map światła (rysunek 9.15). Aby się przekonać,
że oświetlenie rzeczywiście jest teraz wypalone w teksturach nałożonych na siatki, wyłącz
na chwilę wszystkie lampy zainstalowane w scenie. Oświetlenie sceny nie powinno się
w ogóle zmienić!

Uwa ga
Beast jest nazwą wyspecjalizowanego w mapowaniu światła silnika, którego Unity używa do genero-
wania map światła.
264 Rozdział 9  Wypalanie

Rysunek 9.14. Finalne ustawienia parametrów mapowania światła


Źródło: Unity Technologies.

Rysunek 9.15. Scena oświetlona za pomocą map światła


Źródło: Unity Technologies.
Wypalanie map w Blenderze 265

Wypalone mapy światła zostaną dodane do projektu jako oddzielny zasób tekstur (ry-
sunek 9.16), a podczas zapisywania sceny zostaną umieszczone w automatycznie wy-
generowanym folderze.

Rysunek 9.16. Mapy światła stanowią odrębny element projektu


Źródło: Unity Technologies.

Zwróć uwagę na rozkład pikseli w mapach światła widocznych w oknie podglądowym


zajmującym dolną część panelu Inspector. Upewnij się, że są to tekstury maksymalnie
zoptymalizowane. Jeśli rozdzielczość mapy światła ustawiłeś zbyt niską w stosunku do
powierzchni siatek, mapa będzie zawierała dużo jednakowych pikseli niewiele wnoszą-
cych do ostatecznego rezultatu. Tekstury będą automatycznie powiększane do rozmiarów
będących kolejną potęgą liczby 2, aby pomieścić wszystkie piksele potrzebne dla mapy
światła bez skalowania czy ponownego próbkowania. Czasem jednak tekstura okazuje
się większa niż trzeba, a to oznacza, że jej powierzchnia nie jest optymalnie wykorzy-
stana — np. wtedy, gdy mapa ma więcej niż 512×512 pikseli, ale nie jest w stanie zapełnić
tekstury o wymiarach 1024×1024 (rysunek 9.17). W takiej sytuacji zmień wartość pa-
rametru Resolution i ponownie wypal mapę światła, aby zapełnić jak największą po-
wierzchnię tekstury.

Wypalanie map w Blenderze


Czasami lepiej jest — a nawet trzeba — ominąć system mapowania światła w Unity
i wygenerować mapy światła w Blenderze. Wtedy zazwyczaj wykonujemy oddzielne
tekstury z mapami okluzji otoczenia, podstawowymi mapami renderingu i innymi ro-
dzajami map oświetleniowych. Następnie w edytorze graficznym, takim jak GIMP czy
Photoshop, składamy z nich jedną teksturę i dopiero w takiej postaci importujemy do
Unity.
266 Rozdział 9  Wypalanie

Rysunek 9.17. Tekstura mapy światła o rozdzielczości równej 10. Taka wartość jest zbyt mała
i prowadzi do zmarnowania dużej części tekstury
Źródło: Unity Technologies.

Powody, dla których często stosuje się takie podejście, są dwojakiego rodzaju:
■ W darmowej wersji Unity nie wszystkie funkcje związane z wypalaniem map są do-
stępne. Nie ma tam obsługi oświetlenia pośredniego i okluzji otoczenia. W takiej
sytuacji najprostszym i najbardziej oczywistym rozwiązaniem — pomijając kupno
pełnej wersji programu Unity — jest wypalenie tych wszystkich map w Blenderze
i potem połączenie ich w jedną mapę światła rozproszonego (diffuse map).
■ Niekiedy, nawet jeśli mamy Unity Pro, trzeba ręcznie sterować procesem wypalania.
Najczęściej taka potrzeba zachodzi, gdy stosujemy własne shadery i typy materiałów
lub chcemy poprawić wydajność przez zmniejszenie liczby tekstur przetrzymywa-
nych w pamięci — wszystkie efekty oświetleniowe pakujemy wtedy do jednej tekstury
z mapą światła rozproszonego.
W tym podrozdziale zajmiemy się właśnie ręcznym wypalaniem map światła za pomocą
Blendera i GIMP-a. Aby ułatwić sobie śledzenie kolejnych etapów tej procedury, możesz
wczytać do Blendera zawartość powiązanego z książką pliku Rozdział09/blender_
environment/env_final.blend. Jest to zestaw modułów do budowy scenerii laboratorium
naukowego (rysunek 9.18). Oczywiście techniki wypalania, które zaprezentuję, będą
mogły być stosowane także w odniesieniu do innych siatek. Ten zestaw ma Ci tylko po-
móc w nauce posługiwania się odpowiednimi narzędziami.
Wypalanie map w Blenderze 267

Rysunek 9.18. Przygotowanie do wypalania tekstur oświetleniowych


Źródło: Blender.

Aby własnoręcznie wypalić teksturę, wykonaj następujące czynności:


1. Upewnij się, że jako domyślny renderer systemowy włączony jest wewnętrzny ren-
derer Blendera o nazwie Blender Render (a nie Cycles lub Blender Game). W tym celu
rozwiń na pasku Info (informacje) listę z rendererami i wybierz pozycję Blender Render
(rysunek 9.19).

Rysunek 9.19. Ustawianie systemu renderowania w Blenderze


Źródło: Blender.

2. Zacznij od wypalenia mapy okluzji otoczenia dla zestawu środowiskowego. Będzie


to odrębna tekstura w skali szarości reprezentująca dane dotyczące efektu okluzji
otoczenia będącego rezultatem oświetlenia pośredniego. Utwórz więc nową pustą
268 Rozdział 9  Wypalanie

teksturę, która przyjmie te dane, gdy efekt zostanie wyrenderowany. Zaznacz siatkę
zestawu w oknie widokowym, po czym wciśnij klawisze Ctrl+A, żeby zaznaczyć
wszystkie ścianki w siatce. Następnie zmień układ interfejsu na UV Editing (edycja
współrzędnych UV) i na pasku narzędziowym kliknij przycisk Create a new image
(utwórz nowy obraz) — rysunek 9.20.

Rysunek 9.20. Utwórz nową teksturę, aby zapisać w niej mapę okluzji otoczenia
Źródło: Blender.

3. Otworzy się okno dialogowe z ustawieniami. Wpisz nazwę nowego obrazu (ja wpi-
sałem AO_Map), ustaw biały kolor tła i wyłącz opcję Alpha (przezroczystość alfa
nie będzie potrzebna w teksturze z mapą okluzji otoczenia) — rysunek 9.21. Na-
stępnie kliknij przycisk OK. Wszystkie ścianki dopasują się kolorystycznie do nowej,
białej tekstury.

Rysunek 9.21. Parametry tekstury tworzonej dla okluzji otoczenia


Źródło: Blender.

4. W panelu Properties otwórz zakładkę Render (renderowanie). (W zależności od


aktualnie wybranego układu interfejsu być może będziesz musiał wrócić do układu
domyślnego. O zmienianiu układów interfejsu Blendera możesz przeczytać w roz-
dziale 2., w punkcie „Konfigurowanie interfejsu Blendera”). Przewiń zawartość za-
Wypalanie map w Blenderze 269

kładki Render, aby uzyskać dostęp do rolety Bake (wypalanie), rozwiń tam listę
Bake Mode (tryb wypalania) i wybierz Ambient Occlusion (okluzja otoczenia) —
rysunek 9.22. Włącz też opcję Normalized (znormalizowane), aby materiały przy-
pisane obiektom nie miały wpływu na renderowane efekty przez wywoływanie
odbić i załamywanie światła. Włączenie tej opcji spowoduje, że przy renderowaniu
efektów okluzji otoczenia właściwości materiałów nie będą uwzględniane.

Rysunek 9.22. Ustawianie parametrów wypalania na zakładce Render panelu Properties


Źródło: Blender.

5. W panelu Properties otwórz zakładkę World (świat) i zaznacz pola wyboru w roletach
Ambient Occlusion, Environment Lighting (oświetlenie środowiska) i Indirect Lighting
(oświetlenie pośrednie). Spowoduje to, że wyrenderowana mapa światła będzie
zawierała szeroki zakres efektów oświetlenia pośredniego. Na koniec włącz w role-
cie Gather (zbieranie) opcję Approximate (przybliżenie) — rysunek 9.23.
6. Aby uruchomić proces wypalania, zaznacz siatkę w oknie widokowym, otwórz po-
nownie zakładkę Render i kliknij przycisk Bake (wypal). Nie zapomnij o zaznacze-
niu siatki, ponieważ proces wypalania obejmie tylko zaznaczone obiekty. Rezultat
wypalania zostanie wyświetlony w oknie UV/Image Editor (edytor współrzędnych
UV i obrazów). Tutaj też możesz zapisać uzyskany obraz jako zwykłą teksturę. W tym
celu z menu edytora wybierz polecenie Image/Save as Image (obraz/zapisz jako obraz)
— rysunek 9.24.
270 Rozdział 9  Wypalanie

Rysunek 9.23. Ustawianie opcji wypalania na zakładce World


Źródło: Blender.

Rysunek 9.24. Zapisywanie mapy okluzji otoczenia jako obrazu


Źródło: Blender.
Komponowanie renderingów w GIMP-ie 271

Oczywiście wypalać możesz także inne mapy światła, włącznie z mapami odblasków,
normalnych, cieni, a nawet pełne renderingi zawierające w jednym obrazie wszystkie
efekty oświetleniowe. Większe korzyści daje jednak wypalanie poszczególnych efektów
oddzielnie — jeden obraz dla okluzji otoczenia, drugi dla odblasków, trzeci dla cieni itd.
Otóż przez to, że każdy efekt trafia do odrębnego pliku, możesz je potem swobodnie
komponować według własnego uznania, a więc zyskujesz dodatkową możliwość wpły-
wania na ostateczny wygląd sceny. I właśnie procesem komponowania efektów oświe-
tleniowych zajmiemy się w następnym podrozdziale.

Komponowanie renderingów w GIMP-ie


Za pomocą blenderowej funkcji wypalania możesz zapisać poszczególne przebiegi
renderujące w odrębnych plikach — przebiegi takie jak okluzja otoczenia, odblaski, cie-
nie, rozpraszanie światła itp. Gdy wykonujesz pełny rendering, Blender łączy rezultaty
tych wszystkich przebiegów w jeden skonsolidowany obraz. Jest to rozwiązanie na pewno
szybkie i wygodne, ale pozbawia Cię dodatkowej możliwości wpływania na sam proces
łączenia wygenerowanych efektów. Jeśli zapiszesz je w oddzielnych plikach, będziesz
mógł je umieścić na osobnych warstwach w edytorze graficznym, takim jak GIMP czy
Photoshop, a to da Ci możliwość łączenia ich na różne sposoby przy użyciu trybów
mieszania, poziomów krycia i innych parametrów. Omówię ten proces na przykładzie
łączenia mapy okluzji otoczenia ze standardową teksturą rozproszenia światła. Do
„współpracy” Blendera z GIMP-em wrócimy jeszcze w następnym rozdziale.

Uwa ga
Program GIMP można pobrać w wersjach dla systemów Windows, Mac i Linux za darmo z witryny:
http://www.gimp.org/. Do zrozumienia treści prezentowanych w tym podrozdziale potrzebna jest przy-
najmniej podstawowa znajomość tej aplikacji. Więcej informacji na jej temat znajdziesz jeszcze w rozdziale
10. i w dodatku A.

Na rysunku 9.25 widać otwartą w GIMP-ie teksturę z mapą rozproszenia światła na ele-
mentach zestawu środowiskowego. Plik z tą teksturą (env_diffuse.png) znajdziesz w ma-
teriałach powiązanych z książką, w folderze Rozdział09/GIMP. Tekstura ma wymiary
1024×1024 piksele i zawiera dane odnośnie do rozpraszania światła na powierzchni
obiektów tworzących środowisko gry. Nie obejmuje informacji na temat okluzji oto-
czenia i oświetlenia pośredniego. Reprezentuje teksturę, jaka w Unity byłaby przypisana
siatkom przed rozpoczęciem procesu mapowania światła. W GIMP-ie została umiesz-
czona na warstwie tła.
Mapa okluzji otoczenia (o takich samych wymiarach, czyli 1024×1024 pikseli) utwo-
rzona w poprzednim ćwiczeniu przejęła współrzędne UV od siatek elementów środo-
wiska. Oznacza to, że ma nie tylko takie same wymiary jak mapa rozproszenia światła, ale
również współrzędne UV, a zatem można je ze sobą łączyć. Aby mapę okluzji umieścić
272 Rozdział 9  Wypalanie

Rysunek 9.25. Najpierw otwórz teksturę z mapą rozpraszania światła


Źródło: GNU Project.

na odrębnej warstwie w jednym pliku z mapą rozproszenia, po prostu przeciągnij jej


plik z Eksploratora (Windows) lub Findera (Mac OS) do okna GIMP-a, w którym jest
już otwarty obraz z mapą rozproszenia. GIMP automatycznie umieści ją na nowej
warstwie. Gdyby się okazało, że mapa okluzji nie została umieszczona na szczycie stosu
warstw, przesuń ją w górę za pomocą strzałek widocznych na pasku narzędziowym
u dołu okna dialogowego Layers (Warstwy) — rysunek 9.26.
Znajdująca się na szczycie stosu warstw mapa okluzji otoczenia zakrywa całkowicie le-
żącą niżej mapę rozproszenia światła. Nie o takie połączenie jednak chodzi. Warstwy
te muszą być ze sobą zmieszane, a nie nałożone jedna na drugą. Mapa okluzji jest ob-
razem w skali szarości i z punktu widzenia technik komponowania ma to istotne zna-
czenie. Możesz bowiem od razu przypisać jej tryb mieszania Multiply (Mnożenie)
i skutecznie zmieszać jej zawartość z zawartością mapy rozproszenia (rysunek 9.27).
W rezultacie otrzymasz jeden obraz zawierający informacje, które w Unity byłyby
rozłożone na dwóch odrębnych mapach. Zmniejszysz więc liczbę używanych w grze
tekstur i tym samym obniżysz jej zapotrzebowanie na pamięć komputera.
Komponowanie renderingów w GIMP-ie 273

Rysunek 9.26. Przesuń warstwę okluzji otoczenia na szczyt stosu warstw


Źródło: GNU Project.

Rysunek 9.27. Mapa okluzji otoczenia skomponowana z mapą rozpraszania światła


Źródło: GNU Project.
274 Rozdział 9  Wypalanie

Wypalanie oświetlenia dynamicznego


z użyciem próbników światła
Mapowanie światła najlepiej sprawdza się w odniesieniu do obiektów statycznych
(nieruchomych), takich jak elementy scenerii i stałe rekwizyty. Zupełnie inaczej spra-
wa wygląda w przypadku obiektów dynamicznych, które w trakcie gry przemieszczają
się z miejsca na miejsce, zmieniając położenie względem otaczających je źródeł światła.
Oznacza to, że ich oświetlenie zmienia się wraz z każdym ich ruchem.
Unity ma wbudowane dwa sposoby obchodzenia się z takimi obiektami. Pierwszy
sprowadza się do zupełnej rezygnacji z wypalania jakichkolwiek map i całkowitego
przejścia na obliczanie oświetlenia w czasie rzeczywistym, zwłaszcza gdy źródła świa-
tła mają charakter kierunkowy, reflektorowy lub punktowy. Sposób drugi polega na
zastosowaniu próbników światła (light probes) wygenerowanych (wypalonych) na etapie
tworzenia gry w celu aproksymacji oświetlenia scenicznego. W czasie rzeczywistym po-
zostaje tylko odpowiednia interpolacja zawartych w nich informacji i to już pozwala
dość dobrze symulować oświetlenie obiektów dynamicznych.
Zanim przejdziemy do wykonywania praktycznych ćwiczeń z próbnikami światła, przy-
gotuj kompletną scenę lub cały poziom ze wszystkimi źródłami światła. Do celów ćwi-
czeniowych możesz wykorzystać zawartość pliku Rozdział09/Light_Probes_Start, który
znajdziesz w materiałach powiązanych z książką. Jest to scena z zestawem środowi-
skowym zaopatrzonym w mapy oświetlenia statycznego i dynamiczną postacią, której
oświetlenie jest obliczane w czasie rzeczywistym. Postać tę można przemieszczać po
całym poziomie w sposób typowy dla gier z perspektywą trzeciej osoby (rysunek 9.28).
Aby poprawić wydajność, zastąpimy istniejący sposób oświetlenia postaci metodą opartą
na próbnikach światła.

Rysunek 9.28. Scena gotowa do wygenerowania próbników światła


Źródło: Unity Technologies.
Wypalanie oświetlenia dynamicznego z użyciem próbników światła 275

Uwa ga
Próbniki światła są dostępne tylko w Unity Pro. W wersji darmowej można uzyskać podobne rezultaty
przez zastosowanie własnych shaderów lub utworzenie klasy, która uśredni wartości oświetlenia w scenie
i dopasuje kolor obiektu do barwy pobliskiego źródła światła.

Twórcy gier starają się uzyskać realistyczne oświetlenie ruchomych siatek przez sta-
ranne rozmieszczenie w scenie zestawu powiązanych ze sobą węzłów (próbników) sieci
oświetleniowej. W fazie realizacyjnej każdy próbnik rejestruje parametry oświetlenia
istniejącego w miejscu, w którym się znajduje. Zapisuje kierunek, natężenie i barwę świa-
tła docierającego do niego z otaczających go źródeł. Potem, w czasie trwania gry, próbni-
ki te automatycznie pocieniują i pokolorują każdą dynamiczną siatkę, która znajdzie
się w ich zasięgu. Oświetlenie siatki będzie rezultatem interpolacji danych pochodzących
od wszystkich otaczających ją próbników.
Żeby użyć próbników, trzeba je najpierw utworzyć i odpowiednio porozstawiać. Oto,
jak należy to zrobić.
1. Utwórz nowy pusty obiekt i ustaw go w środku globalnego układu współrzędnych.
2. Dodaj składnik Light Probe Group (grupa próbnika światła). Aby taki składnik dodać,
wybierz polecenie Component/Rendering/Light Probe Group (składnik/renderowanie/
grupa próbnika światła) — rysunek 9.29.

Rysunek 9.29. Do pustego obiektu dodaj komponent Light Probe Group, aby wszystkie dodawane
próbniki utworzyły jedną sieć
Źródło: Unity Technologies.
276 Rozdział 9  Wypalanie

3. Dodaj do sceny pierwszy próbnik. W tym celu kliknij przycisk Add Probe (dodaj
próbnik) w rolecie Light Probe Group panelu Inspector.
4. Za pomocą standardowych narzędzi transformacyjnych zaznacz i ustaw próbnik
w odpowiednim miejscu.
5. Powtarzając czynności z etapów 3. i 4., utwórz całą sieć próbników rozstawionych
w różnych miejscach sceny. Próbniki automatycznie połączą się ze sobą w jedną
sieć. Cała sztuka polega na tym, żeby jak najmniejszą liczbą próbników obstawić
wszystkie ważne miejsca, czyli te, w których występują istotne efekty oświetleniowe.
Oznacza to, że najwięcej próbników trzeba umieścić w obszarach o zróżnicowanym
oświetleniu, a tam, gdzie światło jest w miarę jednorodne, można ich wstawić mniej.
Sieć, jaką ja stworzyłem, jest pokazana na rysunku 9.30.

Rysunek 9.30. Rozstaw próbniki światła w całym poziomie, aby zarejestrować jak najlepsze
przybliżenie oświetlenia
Źródło: Unity Technologies.

Uwa ga
Nie ustawiaj wszystkich próbników na tej samej wysokości (z tą samą wartością współrzędnej Y). Jeśli
poprzesuwasz je również w pionie, rozkład zrealizowanego za ich pomocą oświetlenia będzie bardziej
przestrzenny.

6. Samo rozmieszczenie sieci próbników w scenie nie spowoduje, że docierające do


nich światło zostanie zarejestrowane. Po utworzeniu całej sieci musisz otworzyć
edytor Lightmapping, kliknąć w nim zakładkę Bake, rozwinąć listę Bake Probes
(wypalanie próbek) i zaznaczyć w niej opcję Bake Probes (rysunek 9.31). Wypalanie
próbek światła jest szybsze niż mapowanie światła, ale i tak w przypadku dużych
poziomów z wieloma próbnikami może potrwać kilka minut.
Wypalanie oświetlenia dynamicznego z użyciem próbników światła 277

Rysunek 9.31. Aby wypalić oświetlenie sceny, włącz w edytorze Lightmapping opcję Bake Probes
Źródło: Unity Technologies.

7. Proces wypalania osadza w próbnikach istotne dane oświetleniowe, które potem są


na bieżąco interpolowane i nakładane na dynamiczne siatki, co w sumie daje efekt
podobny do tego, jaki można uzyskać na drodze obliczeń w czasie rzeczywistym.
Domyślnie jednak żadna siatka nie jest w ten sposób oświetlana. Aby to nastąpiło,
trzeba taką siatkę wyraźnie wskazać. W tym celu zaznacz wszystkie dynamiczne
siatki i w rolecie Mesh Renderer (renderer siatki) lub Skinned Mesh Renderer (ren-
derer siatki powleczonej skórą) zaznacz pole wyboru Use Light Probes (użyj prób-
ników światła). (W przypadku postaci z ćwiczeniowego pliku należy zaznaczyć
siatkę retop_char, która ma komponent Skinned Mesh Renderer, co widać na ry-
sunku 9.32). Teraz postać otrzyma na wpół wypalone oświetlenie od próbników
światła. Znakomicie! Umiesz już optymalizować oświetlenie siatek dynamicznych.
278 Rozdział 9  Wypalanie

Rysunek 9.32. Aby oświetlić siatkę dynamiczną za pomocą próbników, włącz opcję Use Light Probes
Źródło: Unity Technologies.

Wypalanie nawigacji
Ostatnia technika wypalania, jaką rozpatrujemy w tym rozdziale, ma związek z wy-
znaczaniem tras i nawigacją. Wszyscy wrogowie i postacie typu NPC powinny prze-
cież wykazywać pewien poziom inteligencji. Nie powinny wpadać na ściany, krzesła
czy zamknięte drzwi, a na dodatek powinny wybierać najkrótszą i najsensowniejszą
drogę do miejsca, w którym chciałyby się znaleźć. Zachowanie takie można im przypisać
za pomocą Unity na wiele sposobów. W wersjach wcześniejszych niż 3.5 najczęściej
stosowana była technika oparta na węzłach i wyznaczaniu tras za pomocą algorytmu
A* lub Dijkstry. Później jednak popularniejsze stało się stosowanie funkcji wbudowanych
w Unity, a szczególnie siatek nawigacyjnych. Podobnie jak próbniki światła siatki na-
wigacyjne pozwalają tylko na połowiczne wykorzystanie techniki wypalania, bo przecież
muszą w naturalny sposób współpracować z siatkami dynamicznymi. Sporą część danych
nawigacyjnych można wypalić w siatce nawigacyjnej, ale i tak Unity musi pewne obli-
czenia przeprowadzać w czasie rzeczywistym.
Aby zobaczyć, jak to działa w praktyce, wykonaj opisane poniżej ćwiczenie. Zacznij od
wczytania pliku Rozdział09/Navigation_Start. Jego zawartość stanowią statyczne środo-
wisko i postać gracza. Obiekty te będą pełniły funkcję wrogów. Będą ciągle podążały za
postacią gracza, starając się omijać wszelkie napotkane przeszkody. Do kierowania ich
ruchem użyjemy siatki nawigacyjnej. Wstępny układ tej przykładowej sceny jest poka-
zany na rysunku 9.33.
Wypalanie nawigacji 279

Rysunek 9.33. Scena przygotowana do ćwiczenia z użyciem siatek nawigacyjnych. Klocki będą
musiały ciągle odnajdywać drogę do postaci gracza, gdy ta będzie zmieniała położenie
Źródło: Unity Technologies.

Zanim zaczniesz wypalać nawigację, musisz najpierw wygenerować siatkę nawigacyj-


ną. Jest to niewidoczna w czasie gry niskorozdzielcza siatka wytyczająca obszary, po
których obiekty mogą się poruszać. To właśnie na jej podstawie wrogowie będą wyty-
czać swoje ścieżki w czasie rzeczywistym.
Aby wygenerować siatkę nawigacyjną, wykonaj następujące czynności:
1. Za pomocą polecenia Window/Navigation (okno/nawigacja) otwórz edytor Navi-
gation. Podobnie jak edytor Lightmapping ten też warto zadokować przy prawej
krawędzi interfejsu, aby nie zasłaniał okna widokowego (rysunek 9.34).

Rysunek 9.34. Edytor Navigation zadokowany obok panelu Inspector


Źródło: Unity Technologies.

2. W edytorze Navigation kliknij przycisk Bake.


280 Rozdział 9  Wypalanie

3. Upewnij się, że w oknie Navmesh Display (wyświetlanie siatki nawigacyjnej) wi-


docznym w prawym dolnym rogu okna widokowego włączona jest opcja Show
NavMesh (pokaż siatkę nawigacyjną).
4. Kliknij przycisk Bake, aby wygenerować siatkę nawigacyjną dla bieżącej sceny. Pojawi
się ona tuż przy podłodze i będzie miała kolor niebieski. W trakcie gry nie będzie wi-
doczna; teraz wyświetlamy ją tylko dla celów diagnostycznych (rysunek 9.35).

Rysunek 9.35. Wygeneruj wstępną siatkę nawigacyjną dla sceny


Źródło: Unity Technologies.

Po wygenerowaniu siatki nawigacyjnej z domyślnymi parametrami przyjrzyj się jej


uważnie. Mogą się pojawić dwa istotne problemy:
■ Siatka nawigacyjna może być przesunięta w pionie w stosunku do podłogi sceny,
jakby unosiła się w powietrzu (rysunek 9.36).

Rysunek 9.36. Siatka nawigacyjna wydaje się unosić w powietrzu


Źródło: Unity Technologies.
Wypalanie nawigacji 281

■ Siatka może za bardzo odsuwać się od ścian i w wąskich korytarzach może jej
w ogóle nie być (rysunek 9.37).

Rysunek 9.37. Siatka odsunięta od ścian


Źródło: Unity Technologies.

Aby obniżyć siatkę do poziomu podłogi, rozwiń w edytorze Navigation roletę Advan-
ced (zaawansowane) i zmniejsz wartość parametru Height Inaccuracy (niedokładność
wysokości). Ja zmniejszyłem ją z 8 do 1. W przypadku tej sceny taka wartość jest wy-
starczająca (rysunek 9.38).

Rysunek 9.38. Obniżanie siatki nawigacyjnej do poziomu podłogi


Źródło: Unity Technologies.
282 Rozdział 9  Wypalanie

Uwa ga
Po zmodyfikowaniu parametrów siatki nawigacyjnej musisz ją na nowo wygenerować, klikając ponow-
nie przycisk Bake.

Drugi problem — odsunięcie siatki nawigacyjnej od ścian — można rozwiązać przez


zmianę parametru Radius (promień) dostępnego na zakładce Bake edytora Navigation.
Nie wolno jednak zapominać o powodach, dla których to odsunięcie w ogóle powstało.
Otóż zewnętrzne krawędzie siatki nawigacyjnej wyznaczają skrajne możliwe położenia
środków transformacji tych obiektów, które mają się poruszać w obszarze wyznaczonym
przez siatkę, więc pewien odstęp między tymi krawędziami a ścianami jest konieczny,
żeby obiekty podczas przemieszczania się nie przenikały częściowo przez ściany. Raczej
rzadkie są przypadki, kiedy siatka może ściśle przylegać do stałych elementów środo-
wiska. Niemal zawsze jakieś odsunięcie jest potrzebne. Pozostaje tylko pytanie: jak duże
powinno być? Odpowiedź zależy od rozmiarów siatek NPC, struktury ścian i innych ele-
mentów środowiska, a także od sposobu, w jaki gra ma się toczyć. Krótko mówiąc: wartość
parametru Radius trzeba dobierać metodą prób i błędów, aż znajdzie się taką, która będzie
odpowiadała naszym potrzebom. Ja zmniejszyłem ją z 0,5 do 0,4 (rysunek 9.39).

Rysunek 9.39. Parametr Radius decyduje o wielkości przerwy między siatką nawigacyjną a ścianami
Źródło: Unity Technologies.

Wygenerowanie siatki nawigacyjnej to dopiero pierwszy krok na drodze do skonstru-


owania mechanizmu wyznaczania tras. Następny będzie polegał na takim skonfiguro-
waniu obiektów NPC, aby z tej siatki faktycznie korzystały. W tym celu trzeba każdy taki
obiekt wyposażyć w komponent o nazwie Nav Mesh Agent (agent siatki nawigacyjnej).
W terminologii systemów wyznaczania tras pojęcie agent oznacza byt, który może
w sposób inteligentny przejść z jednego punktu do drugiego, omijając napotkane po
drodze przeszkody. Właśnie takimi inteligentnymi agentami potrafiącymi znaleźć wła-
Wypalanie nawigacji 283

ściwą drogę trzeba uczynić wszystkie cztery prostopadłościenne klocki. W Unity można
to zrobić bardzo łatwo — wystarczy każdemu z klocków przypisać wspomniany kompo-
nent przez wybranie polecenia Component/Navigation/Nav Mesh Agent (rysunek 9.40).

Rysunek 9.40. Dodawanie komponentu Nav Mesh Agent potencjalnym wrogom


Źródło: Unity Technologies.

Następnie trzeba te komponenty we wszystkich czterech klockach odpowiednio skon-


figurować. Ja ustawiłem w nich Speed (szybkość) na 2 (jednostki globalne na sekundę)
i Stopping Distance (dystans hamujący) na 3. Ten drugi parametr określa odległość
(w jednostkach globalnych), na jaką agent może się zbliżyć do celu, zanim się zatrzyma.
Wartość 3 zapobiegnie wchodzeniu klocków na postać gracza, gdy ją już dogonią. Po
prostu klocek zatrzyma się, gdy jego odległość od postaci gracza stanie się równa bądź
mniejsza od 3 jednostek (rysunek 9.41).

Rysunek 9.41. Ustawianie parametrów komponentu Nav Mesh Agent


Źródło: Unity Technologies.

Jeśli teraz uruchomisz grę, okaże się, że mimo skonfigurowania komponentów agen-
towych klocki nadal stoją nieruchomo i wcale nie mają zamiaru ścigać postaci gracza.
Nic nie zmusza ich do ruszenia w drogę. Żeby to zmienić, musisz napisać odpowiedni
skrypt i przypisać go wszystkim klockom. Zawartość takiego skryptu przedstawia li-
sting 9.1.
284 Rozdział 9  Wypalanie

Listing 9.1. Skrypt EnemyAI.cs — sztuczna inteligencja wroga


using UnityEngine;
using System.Collections;
public class EnemyAI : MonoBehaviour
{
//Komponent Nav Mesh Agent.
private NavMeshAgent NMAgent = null;
//Referencja do postaci gracza.
private Transform PlayerTransform = null;
//Inicjalizacja komponentu agentowego i postaci gracza.
void Start ()
{
//Pobierz komponent Nav Mesh Agent.
NMAgent = GetComponent<NavMeshAgent>();
//Pobierz transformacje postaci gracza.
PlayerTransform = GameObject.FindGameObjectWithTag("Player").transform;
}
//Aktualizacja wywoływana w każdej klatce.
void Update ()
{
//Powiąż wroga z postacią gracza.
NMAgent.SetDestination(PlayerTransform.position);
}
}

W funkcji Update() wywoływana jest metoda NMAgent.SetDestination(), która śledząc


zmiany położenia postaci gracza jako celu, ciągle aktualizuje prowadzącą do niego trasę.
Powyższy skrypt przypisany do obiektu NPC spowoduje, że ten rozpocznie swój ruch
w kierunku postaci gracza i będzie wszędzie za nią podążał. Na rysunku 9.42 widać, że
to działa!

Rysunek 9.42. Naprzód! Agenci NPC ścigają gracza


Źródło: Unity Technologies.
Podsumowanie 285

Uwa ga
Więcej informacji na temat komponentu Nav Mesh Agent znajdziesz w dokumentacji programu Unity pod
adresem: http://docs.unity3d.com/Documentation/ScriptReference/NavMeshAgent.SetDestination.html.

Podsumowanie
Głównym tematem tego rozdziału było pojęcie wypalania, czyli wcześniejszego przy-
gotowywania takich elementów jak oświetlenie czy wytyczanie trasy w celu skrócenia
obliczeń wykonywanych w czasie rzeczywistym podczas działania gry. Najczęściej wy-
palane są mapy światła i tekstury, ale w zasadzie wypalać można — jeśli nie całkowicie,
to przynajmniej częściowo — wszystkie elementy gry, włącznie z oświetleniem dy-
namicznym i wyznaczaniem tras.
Unity oferuje również możliwość wypalania widoczności obiektów z uwzględnieniem
ich wzajemnego zasłaniania się (occlusion culling), ale to zagadnienie wykracza poza
ramy książki. Wiele ważnych technik wypalania udało mi się jednak zaprezentować.
Pokazałem też obszary, w których niezwykle pomocne mogą się okazać programy takie
jak Blender i GIMP. Z tego wszystkiego każdy twórca gier powinien wyciągnąć dość
istotny wniosek: jeśli tylko coś da się wypalić, to należy wypalać, bo niemal zawsze jest
to korzystne ze względów wydajnościowych.
286 Rozdział 9  Wypalanie
R OZ DZ I AŁ 10

U NITY , B LENDER
I INNE PROGRAMY

Jeśli patrzysz długo w otchłań, ona również zajrzy w ciebie.


— Friedrich Wilhelm Nietzsche

Po przeczytaniu tego rozdziału powinieneś:


■ znać dodatkowe programy mogące współpracować z Unity i Blenderem;
■ umieć ocenić przydatność innych programów jako pośredników między Blenderem
a Unity;
■ znać jeszcze inne aspekty współpracy Blendera z Unity;
■ wiedzieć, na jakie narzędzia możesz jeszcze liczyć.
Powoli zbliżamy się do zakończenia książki, ale zanim się rozstaniemy, chciałbym po-
krótce omówić inne programy, które nie kosztują nic lub stosunkowo niewiele, a mogą
stanowić znakomite uzupełnienie duetu Blender – Unity. A zatem zobaczmy!

Inne programy
Jednym z głównych celów tej książki jest pokazanie olbrzymich możliwości, jakie Blender
i Unity mają w zakresie tworzenia gier. Blender oferuje mnóstwo wysokiej jakości narzę-
dzi do modelowania, renderowania i animowania elementów gry, które to elementy
z kolei doskonale integrują się ze środowiskiem znakomitego silnika gier, jakim jest
Unity. Przy użyciu formatów FBX i DAE można łatwo i pewnie przenosić między tymi
aplikacjami niemal wszystkie rodzaje danych (siatki, mapy UV, szkielety, animacje itp.).
Unity nawet obsługuje rdzenny format Blendera (.blend) i można z tego korzystać, ale
w rozdziale 2. chyba dostatecznie jasno pokazałem, że raczej nie powinno się tego robić.
Niezależnie od tego potężnego duetu istnieje wiele innych programów, które również

287
288 Rozdział 10  Unity, Blender i inne programy

mogą się okazać przydatne. W następnych podrozdziałach omówię krótko kilka takich
pozycji i wskażę, w czym mogą być użyteczne.
Przy wyborze tych programów kierowałem się tym, że mają to być programy tanie lub
darmowe i powinny działać na większości platform komputerowych używanych współ-
cześnie do tworzenia gier, a przede wszystkim na tych z systemami Windows, Mac
i Linux. Nie chodziło mi też o promowanie takiego czy innego programu ze względów
ideologicznych lub tylko dlatego, że jest darmowy. Starałem się być wierny idei nieza-
leżności, która przyświecała mi podczas pisania tej książki i kazała szukać narzędzi na
poziomie profesjonalnym, a przy tym dostępnych dla wszystkich twórców niezależnie
od zasobności ich portfela, działających na wielu platformach i dopuszczonych do użytku
zarówno prywatnego, jak i komercyjnego.

MakeHuman
MakeHuman (http://www.makehuman.org/) jest darmowym programem do generowa-
nia proceduralnych siatek humanoidalnych, włącznie z siatkami typu low-poly. Siatki
te można przenosić do Blendera, gdzie mogą być optymalizowane, rigowane, mapo-
wane i animowane, aby w końcu trafić do Unity jako pełnoprawne elementy gry. Krótko
mówiąc: MakeHuman może służyć jako narzędzie do szybkiego tworzenia siatek dla
postaci występujących w grze.
Oczywiście program ten nie jest w stanie wygenerować każdej wymyślonej przez nas
postaci (np. trójgłowego potwora), ale nawet w takich sytuacjach może być pomocny
w przygotowaniu siatki stanowiącej punkt wyjścia do dalszego modelowania.
W MakeHuman (rysunek 10.1) możesz kształtować model postaci za pomocą suwaków,
parametrów i opcji. W ten sposób zmienisz wielkość głowy, rozmieścisz na niej elementy
twarzy, ustalisz wiek postaci, płeć, wagę, wzrost itp. Program potrafi wyeksportować
siatkę wraz z danymi mapowania i rigowania w większości popularnych formatów,
włącznie z DAE i FBX.

GIMP
GIMP (http://www.gimp.org/) to potężny edytor obrazów cyfrowych, który pod wieloma
względami nie ustępuje słynnemu Photoshopowi. Oczywiście obie aplikacje różnią się
wyglądem i sposobem obsługi, ale ich możliwości są porównywalne. Obie też nadają się
do tworzenia tekstur, przygotowywania graficznych elementów interfejsu i opracowy-
wania materiałów.
GIMP ma kilka istotnych ograniczeń, przynajmniej na razie. Przede wszystkim nie
obsługuje 16-bitowej głębi kolorów i modelu CMYK. Podobno w przyszłych wersjach
ma się to zmienić. Nie są to jednak ograniczenia, które by uniemożliwiały stosowanie
GIMP-a przy produkcji gier. Przykładowo: w większości gier używane są kolory zgodne
z modelem RGB, a nie CMYK.
GIMP 289

Rysunek 10.1. Model postaci gotowy do eksportu


Źródło: MakeHuman.

GIMP (rysunek 10.2) oferuje imponujący zestaw narzędzi do zaznaczania, malowania,


retuszowania, modyfikowania tonów i kolorów, operowania maskami i warstwami itp.

Rysunek 10.2. Edycja obrazu w GIMP-ie na potrzeby gry Mega Bad Code tworzonej przez Wax
Lyrical Games
Źródło: GNU Project.

Uwa ga
GIMP był moim głównym edytorem obrazów, gdy pracowałem nad grami Bounders and Cads i Mega Bad Code.
290 Rozdział 10  Unity, Blender i inne programy

GIMP dobrze współpracuje zarówno z Blenderem, jak i z Unity. Obsługuje szeroką gamę
popularnych formatów graficznych, takich jak: PNG, JPG, BMP, TIFF, TGA i wiele
innych. Na dodatek Unity można tak skonfigurować, że każda próba otwarcia jakie-
gokolwiek obrazu (podwójne kliknięcie miniatury w panelu Project) spowoduje auto-
matyczne otwarcie tego obrazu w GIMP-ie. Żeby coś takiego uzyskać, wybierz w pro-
gramie Unity polecenie File/Preferences (plik/preferencje), aby otworzyć okno dialogowe
z preferencjami programu. W oknie tym rozwiń kategorię External Tools (narzędzia
zewnętrzne) i na rozwijanej liście Image application (edytor obrazu) zaznacz pozycję
GNU Image Manipulation Program, tak jak na rysunku 10.3.

Rysunek 10.3. Ustawianie GIMP-a jako domyślnego edytora obrazów w Unity


Źródło: Unity Technologies.

Uwa ga
GIMP obsługuje także mnóstwo dodatków, z których wiele przydaje się przy tworzeniu gier. Jednym z nich
jest plugin o nazwie gimp-normalmap (http://code.google.com/p/gimp-normalmap/), który umożliwia ge-
nerowanie map normalnych na podstawie obrazów w skali szarości.

Uwa ga
Popularnym i również darmowym edytorem obrazów jest Paint.NET. Więcej informacji na jego temat
znajdziesz pod adresem: http://www.getpaint.net/.

Inkscape
Inkscape (https://www.inkscape.org/) stara się na różne sposoby, aby być darmową alter-
natywą słynnego Illustratora stworzonego i rozwijanego przez firmę Adobe. W przeci-
wieństwie do programów GIMP i Photoshop, które służą do edycji obrazów rastrowych,
Inkscape i Illustrator oferują narzędzia do tworzenia i edycji grafik wektorowych, czyli
obrazów będących zbiorami nie pikseli, lecz matematycznie zdefiniowanych kształtów.
Obrazy takie, dzięki ich matematycznej naturze, można dowolnie powiększać i po-
mniejszać bez obawy o najmniejszą chociażby utratę jakości. W przypadku kształtów
Inkscape 291

wektorowych powiększanie i pomniejszanie sprowadza się do obliczania nowych warto-


ści, ale zawsze według tych samych formuł matematycznych. Natomiast w obrazach
rastrowych wiąże się to z próbkowaniem obrazu, czyli bezpośrednim manipulowaniem
wartościami pikseli.
Inkscape (rysunek 10.4) oferuje potężny arsenał narzędzi pozwalających tworzyć grafiki
wektorowe w bardzo popularnym formacie SVG (Scalable Vector Graphic). Na pierw-
szy rzut oka wybór tego programu jako narzędzia do produkcji gier może wydawać się
dziwny, ponieważ ani Blender, ani Unity nie obsługują grafiki wektorowej. Inkscape
potrafi jednak konwertować takie grafiki na zwykłe obrazy pikselowe i zapisywać je
w formatach czytelnych dla Blendera i Unity, np. PNG lub BMP. Może się więc przydać
do tworzenia obrazów, które w przyszłości będą musiały być powiększone bądź zmniej-
szone, a nie powinny przy tym tracić na jakości.

Rysunek 10.4. Postać kosmicznego wroga stworzona za pomocą programu Inkscape


Źródło: Inkscape.

Uwa ga
GIMP potrafi importować pliki SVG z programu Inkscape. Wystarczy taki plik przeciągnąć do okna GIMP-a,
aby ten automatycznie przekonwertował grafikę wektorową na obraz pikselowy (rysunek 10.5).

Rysunek 10.5. Importowanie pliku SVG do GIMP-a


Źródło: GNU Project.
292 Rozdział 10  Unity, Blender i inne programy

MyPaint i Krita
Wielu ludzi tworzy obrazy za pomocą GIMP-a, ale są też tacy, którzy wolą używać de-
dykowanych programów malarskich ze specyficznymi pędzlami i innymi wyspecjali-
zowanymi narzędziami. Spośród wszystkich darmowych aplikacji tego typu najbardziej
znane są obecnie MyPaint (http://mypaint.intilinux.com/; rysunek 10.6) oraz Krita
(https://krita.org/; rysunek 10.7). Obie oferują szeroki wachlarz cyfrowych narzędzi
malarskich zaprojektowanych tak, aby mogły współpracować z tabletami graficznymi.
Aplikacje te potrafią doskonale symulować rzeczywiste pędzle, płótna, rozmaite rodzaje
papieru itd.

Rysunek 10.6. Materiał marketingowy opracowany za pomocą MyPainta


Źródło: MyPaint.

Rysunek 10.7. Materiał marketingowy opracowany za pomocą programu malarskiego Krita


Źródło: Krita.
Synfig Studio 293

Synfig Studio
Synfig Studio (http://www.synfig.org/; rysunek 10.8) jest darmową aplikacją typu open
source, która stosunkowo niedawno trafiła na listę narzędzi przydatnych podczas two-
rzenia gier. Za jej pomocą można tworzyć dwuwymiarowe animacje, czyli wszelkiego
rodzaju kreskówki, prezentacje i inne tego typu filmy animowane. Twórca opracowuje
tylko klatki kluczowe, a generowaniem klatek pośrednich zajmuje się aplikacja. Gotowe
animacje można zapisywać w filmowych formatach, takich jak AVI czy Theora, albo
w formie sekwencji obrazów PNG.

Rysunek 10.8. Animowanie kosmicznego wroga w Synfig Studio


Źródło: Synfig Studio.

Tiled
Tiled (http://www.mapeditor.org/) jest darmowym edytorem graficznym typu open sour-
ce wyspecjalizowanym w tworzeniu kafelkowych poziomów i map. Obsługuje rozmaite
układy kafelków i potrafi tworzyć mapy zarówno ortogonalne, jak i izometryczne. Umoż-
liwia importowanie gotowych kafelków w formatach PNG oraz JPG i ułatwia układanie
z nich kompletnych poziomów.
Tiled (rysunek 10.9) jest aplikacją niezależną od silnika gry, co oznacza, że jest prze-
znaczony wyłącznie do tworzenia map, które potem można zapisać w formacie XML,
a ten jest akceptowany przez większość współcześnie używanych silników. Wiele silni-
ków, w tym Unity, ma już wbudowane mechanizmy pozwalające na odczytywanie takich
plików i rekonstruowanie na ich podstawie map wygenerowanych za pomocą aplikacji
Tiled.
294 Rozdział 10  Unity, Blender i inne programy

Rysunek 10.9. Edycja mapy w programie Tiled


Źródło: Tiled.

Uwa ga
Unity nie tylko oferuje własne mechanizmy importowania map z programu Tiled, ale zezwala także na
używanie narzędzi firm trzecich. Odpowiednie informacje, klasy i biblioteki można znaleźć pod nastę-
pującymi adresami:
■ http://karnakgames.com/wp/unity-tiled-tilemaps/,
■ https://bitbucket.org/PolCPP/unitmx/overview,
■ www.wyrmtale.com/products/unity3d-components/orthello-pro.

MonoDevelop
W pakiecie Unity znajduje się nie tylko silnik gier, ale również wieloplatformowe
środowisko programistyczne (Integrated Development Environment — IDE) o nazwie
MonoDevelop. Można go używać do edycji zarówno skryptów, jak i zwykłych tekstów,
a nawet plików XML. Podczas tworzenia gier, a także innych programów, edytor kodu
jest niezbędny. Jest on potrzebny do pisania skryptów oraz do przeglądania i edytowania
plików konfiguracyjnych z danymi zapisanymi w formatach XML i JSON.
Aby przystosować edytor MonoDevelop do pracy z plikami XML i innymi hierarchicz-
nymi strukturami danych, włącz w nim funkcję odpowiedzialną za zwijanie i rozwijanie
określonych fragmentów kodu. Możliwość rozwijania tylko interesujących nas węzłów
znakomicie poprawia przejrzystość wyświetlanego pliku i ułatwia dotarcie do tych danych,
które nas interesują. Wspomnianą funkcję można włączyć w oknie dialogowym Options
(opcje) otwieranym za pomocą polecenia Tools/Options (narzędzia/opcje). W oknie tym
BMFont 295

należy z grupy ustawień Text Editor (edytor tekstu) wybrać kategorię General (ogólne)
i zaznaczyć pole wyboru Enable code folding (włącz zwijanie kodu), tak jak na ry-
sunku 10.10.

Rysunek 10.10. Włączanie funkcji zwijania i rozwijania kodu w edytorze MonoDevelop


Źródło: MonoDevelop.

Uwa ga
Środowisko programistyczne MonoDevelop jest dostępne również jako samodzielna aplikacja, którą
można pobrać z witryny: http://monodevelop.com/.

Uwa ga
Alternatywnym rozwiązaniem może być Notepad++, darmowy edytor tekstu z funkcją wyróżniania
składni języka C#. Działa tylko w systemach Windows i jest dostępny pod adresem: http://notepad-plus-
plus.org/.

BMFont
Przy tworzeniu gier — szczególnie ich interfejsów — często zachodzi potrzeba wyświe-
tlania tekstów zapisanych rozmaitymi czcionkami. Może to być imię i nazwisko gracza,
które ten powinien wpisać, aby rozpocząć grę, lub nazwa pliku z zapisywanym właśnie
stanem gry. Mogą to być także napisy ułatwiające użytkownikowi orientację w tym,
co dzieje się nie tylko na ekranie, ale i poza nim. Krótko mówiąc: potrzebna jest możli-
wość szybkiego budowania dynamicznie zmieniających się tekstów.
296 Rozdział 10  Unity, Blender i inne programy

Podstawową metodą tworzenia takich napisów jest składanie ich ze znaków alfanume-
rycznych, którym wcześniej nadano formę małych obrazów bitmapowych. Zestaw takich
znaków zwykle umieszcza się w jednym pliku (np. PNG), gdzie każdy znak zajmuje
określone miejsce w jednorodnej siatce współrzędnych UV. Mając dostęp do takiej tablicy
znaków, silnik gry może szybko zamienić pobrany z pamięci łańcuch tekstowy na ciąg
pikselowych obrazów odpowiadających poszczególnym literom, cyfrom i innym znakom.
Dopiero utworzony w ten sposób ciąg pikselowych obrazów jest wyświetlany na ekranie.
BMFont (Bitmap Font Generator; http://www.angelcode.com/products/bmfont/) jest
jednym z programów, które służą do renderowania tablic znakowych (rysunek 10.11).
Jest darmowy, ale działa tylko na platformie Windows.

Rysunek 10.11. Renderowanie bitmapowej tablicy znaków alfanumerycznych


Źródło: BMFont.

TexturePacker
Jednym z najbardziej popularnych i efektywnych sposobów optymalizowania tekstur
w Unity jest stosowanie tekstur atlasowych, czyli takich, które zawierają wiele mniejszych
obrazów. Z punktu widzenia renderowania sceny korzystniejsze jest odwoływanie się do
określonych prostokątnych fragmentów jednej tekstury niż do wielu odrębnych tekstur.
Można oczywiście tworzyć takie atlasy ręcznie przez kopiowanie i wklejanie poszcze-
gólnych obrazów na jedno duże płótno w GIMP-ie, ale znacznie szybciej robią to spe-
cjalnie w tym celu zaprojektowane narzędzia. Jednym z nich jest aplikacja o nazwie
TexturePacker (https://www.codeandweb.com/texturepacker; rysunek 10.12) działająca
na większości platform desktopowych, takich jak Windows, Mac czy Linux.
LibreOffice 297

Rysunek 10.12. Tworzenie atlasu sprajtów w programie TexturePacker


Źródło: TexturePacker.

LibreOffice
Projektowanie to ważny etap procesu tworzenia gry. Jego rezultatem jest przecież do-
kument projektowy. To właśnie wtedy wiele rzeczy się planuje i testuje, zapisuje nowe
pomysły, rysuje wykresy i schematy, ustala wersje językowe itp. Niezwykle pomocne
okazują się wtedy programy biurowe, a szczególnie procesor tekstu, arkusz kalkulacyjny
i edytor wykresów. Istnieje wiele pakietów biurowych z tego typu programami, a jednym
z darmowych i działających na wielu platformach jest LibreOffice (http://pl.libreoffice.org/;
rysunek 10.13).

Rysunek 10.13. Tworzenie wykresu za pomocą aplikacji LibreOffice Draw


Źródło: LibreOffice.
298 Rozdział 10  Unity, Blender i inne programy

LibreOffice, poza tym że jest darmowy i wieloplatformowy, ma jeszcze wiele innych


zalet. Może otwierać i zapisywać pliki w nowych macierzystych formatach pakietu
Microsoft Office (takich jak .docx i .xlsx), a także eksportować dokumenty do formatu
PDF. Zawiera też aplikację służącą do sporządzania rozmaitych diagramów, włącznie
z diagramami UML.

Anime Studio Pro


Jednym z komercyjnych, ale stosunkowo tanich programów do tworzenia animacji
2D jest Anime Studio Pro (http://anime.smithmicro.com; rysunek 10.14). Działa on
podobnie jak opisywana już aplikacja Synfig Studio. Umożliwia animowanie dwuwy-
miarowych postaci za pomocą kości, szkieletów i kinematyki odwrotnej. Można go
używać do tworzenia kreskówek i animowanych sprajtów dla gier typu platformówki
2D. Anime Studio Pro obsługuje import plików SVG z programu Inkscape i eksport do
większości formatów filmowych i graficznych, włącznie z AVI i PNG.

Rysunek 10.14. Rigowanie postaci w Anime Studio Pro


Źródło: Anime Studio Pro.

Audacity
Audacity (http://audacity.sourceforge.net; rysunek 10.15) jest znanym i cenionym, a przy
tym darmowym edytorem dźwięku działającym na wielu platformach, który był (i wciąż
jest) używany przy produkcji olbrzymiej liczby gier. Popularne określenie „edytor audio”
nie oddaje w pełni jego możliwości, gdyż jest programem, który potrafi nie tylko otwierać
pojedyncze pliki audio, takie jak WAV, zmieniać w nich poziom dźwięku, wycinać
i łączyć fragmenty oraz modyfikować je na wiele sposobów. Potrafi również działać jak
kompletny wielościeżkowy sekwencer, umożliwiając komponowanie niepowtarzalnych
nagrań muzycznych i ogólnie dźwiękowych.
SFXR 299

Rysunek 10.15. Tworzenie wielościeżkowej kompozycji dźwiękowej w Audacity


Źródło: Audacity.

SFXR
Jeśli tworzysz grę na platformę Windows i chcesz szybko wygenerować dźwięki znane
z dawnych gier platformowych, to sięgnij po SFXR (http://www.drpetter.se/project_
sfxr.html; rysunek 10.16). Jest to darmowy generator proceduralnych efektów dźwięko-
wych, w którym za pomocą kilku suwaków możesz szybko uzyskać dźwięki nadające
się do odtwarzania w takich sytuacjach jak atak wroga, zadanie ciosu, podskok itp.
Każdy efekt można wyeksportować do formatu WAV, a więc da się go bezpośrednio
zaimportować do Unity.

Rysunek 10.16. Tworzenie efektów dźwiękowych przy użyciu programu SFXR


Źródło: SFXR.
300 Rozdział 10  Unity, Blender i inne programy

Podsumowanie
Tym rozdziałem kończymy nasze rozważania nad praktycznym wykorzystaniem
Blendera i Unity w tworzeniu gier. Dokonałem tu pobieżnego przeglądu programów,
które mogą być przydatne dla twórcy gier, a przy tym dają się bezproblemowo włączyć
w tok pracy oparty na Blenderze i Unity. Ważnym kryterium mojego wyboru była rów-
nież dostępność na wielu platformach i niezbyt wygórowana cena. Jeśli do tych progra-
mów dołączyć Blendera i Unity, otrzymamy zestaw narzędzi, które w rękach utalen-
towanego i kreatywnego twórcy gier mogą zaowocować całkiem udanym produktem.
Żeby narzędzie działało właściwie, trzeba się nauczyć nim posługiwać, i tak jest z więk-
szością narzędzi. Ale wystarczy trochę cierpliwości, ćwiczeń i ochoty do nauki, aby każdy
z wymienionych programów uczynić narzędziem przydatnym w produkcji nawet naj-
wyższej jakości gier. Nie wierz mi jednak na słowo, spróbuj sam się o tym przekonać!
DODATEK A

I NNE ŹRÓDŁA WIEDZY

Tworzenie gier komputerowych jest dziedziną pod wieloma względami bardziej


otwartą niż inne sfery ludzkiej działalności. Żeby zostać lekarzem, prawnikiem lub pilo-
tem samolotu, trzeba odbyć studia lub/i formalne szkolenie i uzyskać zezwolenie na wy-
konywanie zawodu. Podobnie jest w wielu innych dziedzinach. Bez pokonania mniej-
szych lub większych przeszkód formalnych nie da się nic zrobić. Na szczęście żeby
zostać twórcą gier, wystarczy mieć komputer i może połączenie z internetem. Może.
Gry możesz tworzyć przecież w biurze, w studiu, na lotnisku, w kawiarni, garażu, a nawet
w sypialni.
Ponadto ten, kto chciałby stworzyć grę, ma swobodny dostęp do wszelkich potrzebnych
mu narzędzi. Dzisiaj niemal każdy, niezależnie od wieku i wykształcenia, może usiąść
przy komputerze i zacząć tworzyć gry. Musi tylko wiedzieć, co i jak ma robić, ale wie-
dzę tę może zdobyć z książek takich jak ta, kursów internetowych i innych źródeł.
Oczywiście sama możliwość użycia takiego czy innego narzędzia nie wystarczy. Trzeba
jeszcze umieć się tymi narzędziami posługiwać, bo dopiero wtedy można za ich po-
mocą uzyskać to, czego się naprawdę chce. Możesz mieć najlepsze lekarstwo na świe-
cie, ale jeśli nie potrafisz dotrzeć z nim do pacjentów, będzie bezużyteczne. Dlatego
żeby pomóc Ci w jeszcze lepszym poznaniu narzędzi opisanych w tej książce, zamiesz-
czam na koniec listę zasobów, dzięki którym będziesz mógł swoją wiedzę poszerzyć.

Witryny internetowe
Dokumentacja pakietu Unity: http://unity3d.com/learn/documentation.
Dokumentacja Blendera: http://wiki.blender.org/index.php/Doc:2.6/Manual.
Dokumentacja GIMP-a: www.gimp.org/docs/.
Artykuły szkoleniowe na temat Unity: http://unitygems.com/.
Tutoriale z zakresu obsługi Blendera: www.blender.org/support/tutorials/.
Tutoriale z zakresu obsługi GIMP-a: www.gimp.org/tutorials/.

301
302 Dodatek A  Inne źródła wiedzy

Książki
Alan Thorn, Unity 4 Fundamentals. Get Started at Making Games with Unity. (ISBN:
978-0415823838).
Alan Thorn, Learn Unity for 2D Game Development. (ISBN: 978-1430262299).
Alan Thorn, Pro Unity Game Development with C#. (ISBN: 978-1-4302-6746-1).
Roland Hess, Blender Foundations. (ISBN: 978-0240814308).
Ben Simonds, Blender. Praktyczny przewodnik po modelowaniu, rzeźbieniu i rendero-
waniu. (ISBN: 978-8324685714).
John M. Blain, The Complete Guide to Blender Graphics. Computer Modeling and
Animation. (ISBN: 978-1466517035).
Olivier Lecarme i Karine Delvare, The Book of GIMP. A Complete Guide to Nearly
Everything. (ISBN: 978-1593273835).
Jan Smith i Roman Joost, GIMP for Absolute Beginners. (ISBN: 978-1430231684).

Filmy wideo
Alan Thorn, Complete Beginners Guide to Unity. Dostępny w 3DMotive.com.
Adam Crespi, Materials and Lighting in Unity. Dostępny w Lynda.com.
Alan Thorn, Modular Building in Unity and Blender. Dostępny w 3DMotive.com.
Alan Thorn, Introduction to C# in Unity. Dostępny w 3DMotive.com.
Jonathan Williamson, Blender Inside Out. Dostępny w Blender 3D Shop.
S KOROWIDZ

A automatyczne
generowanie współrzędnych, 72
agent, 282 kluczowanie, 152
animacja, Animation, 149, 152 awatar, 186
automatyczne kluczowanie, 152
eksportowanie, 156
klatka kluczowa, 150
B
liczba klatek, 155 Blender, 45
retargetowanie, 161 tworzenie animacji, 151
wypalanie, 166, 170 tworzenie terenu, 119
wzdłuż ścieżki, 166 wypalanie map, 265
animowanie ruchu, 166 błędy, 30
animuj ścieżkę, Animate Path, 169 błędy cieniowania, 55, 57
aplikacja budowanie, 40
Anime Studio Pro, 298 budowanie grafu animatora, 165
Audacity, 298 burza mózgów, 24
Blender, 14
BMFont, 295 C
GIMP, 14, 271, 288
Inkscape, 290 cel, Target, 168
Krita, 292 cel przyciągania, Snap Target, 225
LibreOffice, 297 chmury, Clouds, 141
MakeHuman, 288 ciemny motyw, 46
MonoDevelop, 294 cienie, 55
MyPaint, 292 cieniowanie, Shading, 56, 85
SFXR, 299 cień kontaktowy, contact shadow, 262
Synfig Studio, 293 cofanie operacji, 92
TexturePacker, 296 cykliczność, 145
Tiled, 293
Unity, 14 D
aproksymowanie, 229
dane kolizyjne, 105
atak na obiekty, 201
dane trwałe, persistent data, 235
atlas tekstur, 100
definiowanie kluczy kształtu, 174
DI, Dependency Injection, 190

303
304 Skorowidz

długość, Length, 119 format


animacji, 155 Collada, 182
łańcucha, Chain Length, 180 DAE, 184
dodaj teksturę, Add Texture, 116 FBX, 55, 156, 183
dodatek Texture Paint Layer Manager, 137 JSON, 241
dodawanie tekstury, 116, 117 formaty
dołącz animację, Include Animation, 70 dźwięku, 35
domyślna orientacja obiektu, 64 filmów, 35
dopracowanie projektu, 30 obrazów, 35
droga, 143 plików, 35
duplikaty, 92 siatek, 35
dzielenie siatki, 121 FSM, finite state machine, 164
dziesiątkowanie, Decimate, 130, 231 funkcja
dziesięcioetapowy tok pracy, 21 ApplyDamage, 194
Auto-Key, 152
BroadcastMessage, 194
E DealDamage, 189, 192
edycja proporcjonalna, 121, 123 OnCastFireBallSpell, 189
edytor Proportional Editing, 121
współrzędnych UV, 103 przyciągania, 85, 88
wykresów, Graph Editor, 159 SendMessage, 194, 202
edytuj tekstury, Edit Textures, 116 Sharp Edges, 59
eksport do FBX, 55 X-Axis Mirror, 178, 179
eksportowanie
animacji, 156, 157 G
do formatu FBX, 66 gatunek, 25
do pliku FBX, 67 GDD, game design document, 27
postaci, 157 generowanie
zrigowanej siatki, 183, 184 chmur, 125
zrigowanych postaci, 182 siatki nawigacyjnej, 279
elementy gry, 33 tekstury, 124, 132, 140
etap terenu, 112
budowanie, 40 współrzędnych UV, 106
burza mózgów, 24 generuj zderzacze, Generate Colliders, 105
dopracowanie projektu, 30 gęstość
importowanie elementów gry, 34 siatki, 120
kodowanie, 37 tekselowa, 102
projekt wstępny, 27 gizmo transformacji, 60, 62
projektowanie poziomów, 36 gładkie, Smooth, 121
testowanie, 39 głębokość, Depth, 166
tworzenie elementów gry, 33 głębokość fazowania, 168
tworzenie prototypu, 29 graf animatora, 165
etykietki, 48 grupa docelowa, 26
grupowanie wierzchołków, 94
F gry czasu rzeczywistego, 208

filtr siatki, Mesh Filter, 190 H


folder
Editor, 74 hierarchia obiektów, 203
Preferences, 239 hierarchie, 194
Skorowidz 305

I Transform, 190
Wizard, 192
IDE, Integrated Development Environment, 294 komponowanie renderingów, 271
importowanie komunikat odrodzenia, 195
elementów gry, 34 komunikaty, 191, 202
kluczy kształtów, 176 konfigurowanie
plików, 71 interfejsu Blendera, 46
pliku, 54 klipu, 163
zrigowanych postaci, 184 kontroler animatora, 164
intensywność odbicia, Bounce Intensity, 261 kontrolki, 49
interaktywne reorganizowanie siatki, 89 kontury, Wire, 224
interfejs Blendera, 46 kopia bezpieczeństwa, 83
kości, 177
J deformowane, 182
sterujące, 182
język Python, 48
kratka UV, 103
krawędzie, 58
K krycie, Opacity, 114
kant, Crease, 219 krzywa
kąt krawędzi, Edge Angle, 59 Beziera, 144
kinematyka funkcyjna, F-curve, 150
odwrotna, 181 zaniku, 122
prosta, 180 kursor 3D, 80, 81
klasa
Enemy, 189 L
GUI, 197
liczba ścianek w siatce, 131
PlayerPrefs, 237, 238
lustro, Mirror, 94
SaveState, 245–248
lustrzane odbicie, 218
Wizard, 189, 194, 201
klatka
kluczowa, keyframe, 70, 150 Ł
końcowa, End Frame, 155 łączenie, Merge, 130
początkowa, Start Frame, 158
pośrednia, tween, 150
klocek podstawowy, 82, 83
M
klucze kształtu, Shape Keys, 173 malowanie teksturą, Paint Texture, 115, 131,
kluczowanie 134, 140, 142
kształtów, 172 3D View, 138
wizualne, Visual Keying, 171 UV/Image Editor, 134
kodowanie, 37 mapa
kolekcja prefabrykatów, 107 normalnych, 208
kolor światła firmamentu, 261 okluzji otoczenia, 270, 273
komponent szachownicowa, 103
Box Collider, 190 światła, 71, 257
klasa Enemy, 192 kierunkowe, 260
Light Probe Group, 275 podwójne, 259
Mesh Filter, 190 pojedyncze, 259
Mesh Renderer, 190 światła dla siatki, 106
Nav Mesh Agent, 283, 285 wysokości, 124
306 Skorowidz

mapowanie Extrude, 144


normalnych, 208 Knife Project, 145, 147
światła, Lightmapping, 71, 252, 255, 259 Select Faces by Sides, 91
UV, 98 Subdivide, 119, 120
Maya, 49 Transform, 87
metoda Triangulate Faces, 90
edycji proporcjonalnej, 121, 123 natężenie światła firmamentu, 261
kaskadowa, 24 nazywanie obiektów, 67
modułowa, 36, 78, 79 n-kąty, 88
pudełkowa, 209 normalna, Normal, 84, 139
rzeźbienia, 127 NotificationsManager, 198–201
tekstury przemieszczeń, 124 numeracja klatek animacyjnych, 158
zagęszczania siatki, 120
miękkie zaznaczanie, Soft Selection, 121
O
miksowanie kształtów, 172
mirroring, 93 obiekt nadrzędny, 197
mnożenie, Multiply, 272 obiekty
model, 161 aktywne, 202
biznesowy, 26 dynamiczne, 109
szczegółowy, 209 statyczne, 109
uproszczony, 209 oblicz, Calculate, 57
modelowanie obracanie obiektów, 64
3D, 89 obsługiwane rozdzielczości, 26
dróg, 144 odbicia, Bounces, 260
pudełkowe, 205 odczyt z pliku, 246
terenu, 118–120 odejmowanie, Subtract, 129
wysokorozdzielcze, 205 odległość, 32
moduł, 77 odłączanie tekstury, 143
modułowe środowiska, 77 odrzucanie ścianek, 85
modyfikator odstęp między klatkami, Frame Step, 171
Decimate, 130, 232, 233 odtwarzanie, Frame Rate, 151
Displace, 125, 126 odwracanie normalnych, 84
Edge Split, 58, 59, 60 odzyskiwanie rezultatów sesji, 52
Mirror, 94, 213 ograniczenia
Multiresolution, 120, 215–217 Auto-Key, 154
Shrinkwrap, 227–231
mapy wysokości, 119
Subdivision Surface, 213, 215
okluzja otoczenia, Ambient Occlusion, 260, 262,
motyw Elsyiun, 47
269
motywy, Themes, 46
okno
3D View, 138
N Blender User Preferences, 50
nakład pracy, 30 Timeline, 155
narzędzia UV/Image Editor, 134
do retopologizacji modeli, 89 okrąg, Circle, 228
malarskie, 138 opcja
rzeźbiarskie, 127 Alpha, 268
narzędzie Connected, 121
Backface Culling, 85 Extend, 92
Beast Lightmapper, 71 Generic, 162
Skorowidz 307

Greater Than, 92 planowanie pracy, 33


Use Light Probes, 278 platformy, 26
opcje wypalania, 270 plik, 20
opis szczegółów, 29 Enemy.cs, 193
opracowywanie modułów, 83 EnemyAI.cs, 284
optymalizacja tekstur, 79 Wizard.cs, 193
optymalność topologii, 118 z obrazem, 142
ostre krawędzie, Sharp Edges, 58, 59 pliki
oś czasu, Timeline, 152 .blend, 54, 55
oświetlenie binarne, 241
bezpośrednie, 260 FBX, 70
dynamiczne, 252, 274 JSON, 241
pośrednie, 260 skryptowe, 192
statyczne, 252 XML, 240, 246
outsourcing, 34 płaszczyzna, Plane, 222
oznacz szew, Mark Seam, 99 pobieranie komponentu, 204
podgląd, Preview, 124, 216
P podgląd awatara, 186
podziel, Subdivide, 119, 214
parametr polecenie
Brush Size, 114 Add Texture, 116
Edge Angle, 59 Add/Curve/Path, 166
Frame Step, 171 Add/Mesh/Plane, 119, 222
Height, 119 Animate Path, 169
Heightmap Resolution, 114 Assign, 95
Length, 119 Bake Action, 170
Opacity, 114 Calculate, 57
Preview, 216 Clear Constraints, 171
Radius, 129, 282 Draw All Edges, 224
Ratio, 232 Edit Textures, 116
Render, 216 Extrude, 144
Resolution, 257 Flip Normals, 84
Scale, 69 Generate Colliders, 105
Scale Factor, 57, 73 Include Animation, 70
Sculpt, 216 Insert Single Keyframe, 153
Smooth, 121 Join, 101
Start Frame, 158 Mark Seam, 99
Strength, 126 Optimize Keyframes, 70
Texture, 220 Origin to 3D Cursor, 80
View, 213 Recover Last Session, 52
Width, 119 Remove Doubles, 92
parametry Select, 95
komponentu Nav Mesh Agent, 283 Select All, 84
mapowania światła, 261, 264 Smart UV Project, 125
tekstury, 268 Subdivide, 119, 120, 214
terenu, 113 Undo, 92
wyświetlania siatki, 97 Unlink datablock, 143
pędzel, Brush, 114, 128, 219 Unwrap, 99
User Preferences, 97, 137
308 Skorowidz

popychanie, Nudge, 219 rozdzielczość


poszerz, Extend, 92 mapy światła, 257, 258
powierzchnia wielokrotnie dzielona, 206 siatki, 212
prefabrykat, 107 terenu, 130, 131
preferencje rozmiar
gracza, 237, 238 pędzla, Brush Size, 114
użytkownika, User Preferences, 97 wierzchołka, 97
problem z cieniowaniem, 56 rozpraszanie światła, 272
program Maya, 49 rozsyłanie komunikatów, 195, 203
programowanie zdarzeniowe, 187 rozwiń, Unwrap, 99
projekt wstępny, 27 rysuj wszystkie krawędzie, 224
projektowanie rzeźbiące wyciąganie, SculptDraw, 128
komponentowe, 190 rzeźbienie, Sculpt, 127, 216
poziomów, 36 rzeźbienie terenu, 114, 123
promienie Final Gather, 262 rzutowanie
promień, Radius, 129 elementów, 225
prototyp, 29 malowania, Project Paint, 139
próbnik światła, light probes, 253, 274 terenu, 126
przekształcenie, Transform, 87, 190 tnące, Knife Project, 145
przemieszczenie, Displace, 125
przenoszenie S
animacji, 158
modeli, 53 scena, 190
przesyłanie danych, 245 serializacja, 243, 244
przezroczystość, 268 danych, 240
przyciąganie, snapping, 225 klasy, 242
do powierzchni, 221, 226 siatka, Mesh, 67, 99
przyrostowe, Incremental Snapping, 61, 81, 86 high-poly, 206
przypisywanie wierzchołków, 96 low-poly, 227
przypisz, Assign, 95 nawigacyjna, 279, 280
przyrost, Increment, 86 nawigacyjna, navmesh, 254
przywracanie poprzedniej sesji, 53 niskorozdzielcza, 231
punkty kontrolne, 167 statyczna, 77
Python, 48 terenu, 127
wielokątna, 88
wysokorozdzielcza, 208
R silnik, 34
raport operatorski, Dopesheet, 159 siła, Strength, 126
rejestr systemowy, 239 singletony, 201
rejestracja klasy, 200 składniki kolizyjne, 106
renderer siatki, Mesh Renderer, 190, 277 skrypt, 48, 73, 192
renderowanie, Render, 151, 216 sterownik, Controller, 165
renderowanie cieni, 56 sterownik animatora, Animator Controller,
rentgen, X-Ray, 224 162, 164
retargeting, 185 stosowanie prefabrykatów, 107
retargetowanie animacji, 161 stożek, Cone, 67
retopologizacja, 205, 208, 221, 227, 234 symetria, Symmetry, 218
retopologizacja modeli, 89 system
rigi, 177 bytów, entity system, 191
Skorowidz 309

Mecanim, 162 Subtract, 129


NotificationsManager, 198 Texture Paint, 138
powiadomień, 197 układania póz, 180
sterowania, 50 tryby mieszania, 135
szczypanie, Pinch, 219 tworzenie
szerokość, Width, 119 animacji, 151
sześcian, 80 dróg, 143
szkielet, Rig, 161 elementów gry, 33
szkielety symetryczne, 178 grupy, 96
sztuczna inteligencja, 284 kluczy kształtu, 173
szwy, seams, 98 krzywej, 167
krzywej Beziera, 145
Ś modeli, 55
płaszczyzn, 223
ścieżka animacji, 167 prefabrykatu, 108
środek, 32 prototypu, 29
obiektu, 60 scen, 196
transformacji, 146 skryptu, 192
światło otaczające, 256 tekstur, 98, 133
terenu, 111
T tytuł, 25
tablet graficzny, 217
tekstura, Texture, 98, 100, 115, 132, 220 U
mapy światła, 266 układ Animation, 152
przemieszczenia, 124, 125 ukrywanie
typu Clouds, 124, 141 deformowanych kości, 183
teren, 111 ścianek, 85
generowanie, 112 Unity, 35, 45
malowanie teksturami, 115 importowanie środowisk, 104
modelowanie, 119, 120 konfigurowanie środowisk, 104
parametry, 113 tworzenie terenu, 111
rozdzielczość, 130 ustalanie gęstości tekselowej, 102
rzeźbienie, 114, 123 ustawienia eksportu, 69
rzutowanie, 126 usuń więzy, Clear Constraints, 171
teselacja, 119 usuwanie, Delete, 130
testowanie, 39 usuwanie duplikatów, 92
topologia siatki, 118 używanie klocka podstawowego, 83
triangulacja ścianek, Triangulate Faces, 89
trwałość danych, 235
tryb
W
Connected, 121 warstwa okluzji otoczenia, 273
edycji, Edit Mode, 225 warstwy, Layers, 272
Increment, 86 wczytywanie stanów gry, 248
mapowania światła, 259 węzeł BasicAnimation, 165
mieszania, 272 widoczność ścieżki, 168
rzeźbienia, 127 widok, View, 213
rzeźbienia, Sculpt Mode, 216 widok z góry, 144
Single Lightmaps, 263 wielokrotność użycia, 79
310 Skorowidz

wielorozdzielczość, 120 wyrównanie wierzchołków ściany, 87


wierzchołek, Vertex, 97 wysokość, Height, 119
więcej niż, Greater Than, 92 wysyłanie komunikatów, 195–197
więzy, Constraints, 167 wyszukiwanie n-kątów, 91
Follow Path, 168 wyświetlanie
kości, Bone Constraints, 180 informacji pythonowych, 49
wizualizacja gry, 30 siatki, 97
właściwości, Properties, 151 siatki nawigacyjnej, 280
włączanie trybu wytłaczanie, Extrude, 92, 144, 225
malowania, 135 wywołanie rysujące, 100
rzeźbienia, 128 wyznaczanie szwów, 98
wsad statyczny, 109 wzmocnienie odbicia, Bounce Boost, 261
współczynnik skali, Scale Factor, 73
współrzędne UV, 71 Z
mapy światła, 105
terenu, 132 zagęszczanie siatki, 120, 215, 217
wstawianie klatek kluczowych, 153, 154 zalecenia, 41
wstrzykiwanie zależności, DI, 190 zależności zaprogramowane, 188
wybieranie załączniki, 29
danych trwałych, 239 zamykanie bez zapisu, 51
systemu sterowania, 51 zapętlenie czasu, Loop Time, 162
typu pędzla, 128 zapis
wycinanie, Cut, 130 do pliku, 245
wydajność, 79, 118 mapy okluzji, 270
wymiary, Dimensions, 82, 155 ręczny, 242
wymiary klocka podstawowego, 82 rozdzielczości, 237
wypalanie, baking, 208, 251 stanu gry, 235, 240, 248
animacji, 166, 169, 171 zarys gry, 28
map, 265 zarządzanie projektami, 31, 33
map światła, 263 zaznacz, Select, 95
nawigacji, 253, 278 zaznaczenie wierzchołka, 97
oświetlenia dynamicznego, 252, 274 zderzacz
oświetlenia statycznego, 252 prostopadłościenny, Box Collider, 190
próbek, Bake Probes, 276 siatkowy, 105
tekstur oświetleniowych, 267 zestaw środowiska modułowego, 104
widoczności obiektów, 285 zgłoszenia, 33
złącz, Join, 101
zmiana typu tekstury, 141

You might also like